/* * Copyright (c) 2012 Petr Koupy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @addtogroup draw * @{ */ /** * @file */ #include #include #include #include "drawctx.h" void drawctx_init(drawctx_t *context, surface_t *surface) { assert(surface); list_initialize(&context->list); context->surface = surface; context->compose = compose_src; context->mask = NULL; context->source = NULL; context->shall_clip = false; context->clip_x = 0; context->clip_y = 0; surface_get_resolution(surface, &context->clip_width, &context->clip_height); } void drawctx_save(drawctx_t *context) { drawctx_t *to_save = (drawctx_t *) malloc(sizeof(drawctx_t)); if (to_save) { link_initialize(&to_save->link); to_save->compose = context->compose; to_save->mask = context->mask; to_save->source = context->source; to_save->shall_clip = context->shall_clip; to_save->clip_x = context->clip_x; to_save->clip_y = context->clip_y; to_save->clip_width = context->clip_width; to_save->clip_height = context->clip_height; list_append(&to_save->link, &context->list); } } void drawctx_restore(drawctx_t *context) { drawctx_t *to_load = (drawctx_t *) list_last(&context->list); if (to_load) { list_remove(&to_load->link); context->compose = to_load->compose; context->mask = to_load->mask; context->source = to_load->source; context->shall_clip = to_load->shall_clip; context->clip_x = to_load->clip_x; context->clip_y = to_load->clip_y; context->clip_width = to_load->clip_width; context->clip_height = to_load->clip_height; free(to_load); } } void drawctx_set_compose(drawctx_t *context, compose_t compose) { context->compose = compose; } void drawctx_set_clip(drawctx_t *context, sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height) { surface_get_resolution(context->surface, &context->clip_width, &context->clip_height); context->shall_clip = (x > 0) || (y > 0) || (width < context->clip_width) || (height < context->clip_height); context->clip_x = x; context->clip_y = y; context->clip_width = width; context->clip_height = height; } void drawctx_set_mask(drawctx_t *context, surface_t *mask) { context->mask = mask; } void drawctx_set_source(drawctx_t *context, source_t *source) { context->source = source; } void drawctx_set_font(drawctx_t *context, font_t *font) { context->font = font; } void drawctx_transfer(drawctx_t *context, sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height) { if (!context->source) { return; } bool clipped = false; bool masked = false; for (sysarg_t _y = y; _y < y + height; ++_y) { for (sysarg_t _x = x; _x < x + width; ++_x) { if (context->shall_clip) { clipped = _x < context->clip_x && _x >= context->clip_width && _y < context->clip_y && _y >= context->clip_height; } if (context->mask) { pixel_t p = surface_get_pixel(context->mask, _x, _y); masked = p > 0 ? false : true; } if (!clipped && !masked) { pixel_t p_src = source_determine_pixel(context->source, _x, _y); pixel_t p_dst = surface_get_pixel(context->surface, _x, _y); pixel_t p_res = context->compose(p_src, p_dst); surface_put_pixel(context->surface, _x, _y, p_res); } } } } void drawctx_stroke(drawctx_t *context, path_t *path) { if (!context->source || !path) { return; } /* Note: * Antialiasing could be achieved by up-scaling path coordinates and * rendering into temporary higher-resolution surface. Then, the temporary * surface would be set as a source and its damaged region would be * transferred to the original surface. */ list_foreach(*((list_t *) path), link) { path_step_t *step = (path_step_t *) link; switch (step->type) { case PATH_STEP_MOVETO: // TODO break; case PATH_STEP_LINETO: // TODO break; default: break; } } } void drawctx_fill(drawctx_t *context, path_t *path) { if (!context->source || !path) { return; } // TODO } void drawctx_print(drawctx_t *context, const char *text, sysarg_t x, sysarg_t y) { if (context->font && context->source) { font_draw_text(context->font, context, context->source, text, x, y); } } /** @} */