michael@0: changeset: 29338:f2a10f325734 michael@0: tag: qtip michael@0: tag: tip michael@0: tag: win32-raster-mask2.patch michael@0: tag: qbase michael@0: user: Jeff Muizelaar michael@0: date: Mon Jun 22 14:26:07 2009 -0400 michael@0: summary: imported patch win32-raster-mask2.patch michael@0: michael@0: diff --git a/gfx/cairo/cairo/src/cairo-image-surface.c b/gfx/cairo/cairo/src/cairo-image-surface.c michael@0: --- a/gfx/cairo/cairo/src/cairo-image-surface.c michael@0: +++ b/gfx/cairo/cairo/src/cairo-image-surface.c michael@0: @@ -1232,27 +1232,27 @@ typedef struct _cairo_image_surface_span michael@0: cairo_composite_rectangles_t composite_rectangles; michael@0: } cairo_image_surface_span_renderer_t; michael@0: michael@0: -static cairo_status_t michael@0: -_cairo_image_surface_span_renderer_render_row ( michael@0: - void *abstract_renderer, michael@0: +void michael@0: +_cairo_image_surface_span_render_row ( michael@0: int y, michael@0: const cairo_half_open_span_t *spans, michael@0: - unsigned num_spans) michael@0: + unsigned num_spans, michael@0: + cairo_image_surface_t *mask, michael@0: + const cairo_composite_rectangles_t *rects) michael@0: { michael@0: - cairo_image_surface_span_renderer_t *renderer = abstract_renderer; michael@0: - int xmin = renderer->composite_rectangles.mask.x; michael@0: - int xmax = xmin + renderer->composite_rectangles.width; michael@0: + int xmin = rects->mask.x; michael@0: + int xmax = xmin + rects->width; michael@0: uint8_t *row; michael@0: int prev_x = xmin; michael@0: int prev_alpha = 0; michael@0: unsigned i; michael@0: michael@0: /* Make sure we're within y-range. */ michael@0: - y -= renderer->composite_rectangles.mask.y; michael@0: - if (y < 0 || y >= renderer->composite_rectangles.height) michael@0: + y -= rects->mask.y; michael@0: + if (y < 0 || y >= rects->height) michael@0: return CAIRO_STATUS_SUCCESS; michael@0: michael@0: - row = (uint8_t*)(renderer->mask->data) + y*(size_t)renderer->mask->stride - xmin; michael@0: + row = (uint8_t*)(mask->data) + y*(size_t)mask->stride - xmin; michael@0: michael@0: /* Find the first span within x-range. */ michael@0: for (i=0; i < num_spans && spans[i].x < xmin; i++) {} michael@0: @@ -1286,7 +1286,17 @@ _cairo_image_surface_span_renderer_rende michael@0: if (prev_alpha != 0 && prev_x < xmax) { michael@0: memset(row + prev_x, prev_alpha, xmax - prev_x); michael@0: } michael@0: +} michael@0: michael@0: +static cairo_status_t michael@0: +_cairo_image_surface_span_renderer_render_row ( michael@0: + void *abstract_renderer, michael@0: + int y, michael@0: + const cairo_half_open_span_t *spans, michael@0: + unsigned num_spans) michael@0: +{ michael@0: + cairo_image_surface_span_renderer_t *renderer = abstract_renderer; michael@0: + _cairo_image_surface_span_render_row (y, spans, num_spans, renderer->mask, &renderer->composite_rectangles); michael@0: return CAIRO_STATUS_SUCCESS; michael@0: } michael@0: michael@0: diff --git a/gfx/cairo/cairo/src/cairo-tor-scan-converter.c b/gfx/cairo/cairo/src/cairo-tor-scan-converter.c michael@0: --- a/gfx/cairo/cairo/src/cairo-tor-scan-converter.c michael@0: +++ b/gfx/cairo/cairo/src/cairo-tor-scan-converter.c michael@0: @@ -295,9 +295,9 @@ typedef int grid_area_t; michael@0: #elif GRID_XY == 15 michael@0: # define GRID_AREA_TO_ALPHA(c) (((c) << 4) + (c)) michael@0: #elif GRID_XY == 2*256*15 michael@0: -# define GRID_AREA_TO_ALPHA(c) (((c) + ((c)<<4)) >> 9) michael@0: +# define GRID_AREA_TO_ALPHA(c) (((c) + ((c)<<4) + 256) >> 9) michael@0: #else michael@0: -# define GRID_AREA_TO_ALPHA(c) ((c)*255 / GRID_XY) /* tweak me for rounding */ michael@0: +# define GRID_AREA_TO_ALPHA(c) (((c)*255 + GRID_XY/2) / GRID_XY) michael@0: #endif michael@0: michael@0: #define UNROLL3(x) x x x michael@0: diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c michael@0: --- a/gfx/cairo/cairo/src/cairo-win32-surface.c michael@0: +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c michael@0: @@ -2048,6 +2048,148 @@ _cairo_win32_surface_reset (void *abstra michael@0: return CAIRO_STATUS_SUCCESS; michael@0: } michael@0: michael@0: +typedef struct _cairo_win32_surface_span_renderer { michael@0: + cairo_span_renderer_t base; michael@0: + michael@0: + cairo_operator_t op; michael@0: + const cairo_pattern_t *pattern; michael@0: + cairo_antialias_t antialias; michael@0: + michael@0: + cairo_image_surface_t *mask; michael@0: + cairo_win32_surface_t *dst; michael@0: + michael@0: + cairo_composite_rectangles_t composite_rectangles; michael@0: +} cairo_win32_surface_span_renderer_t; michael@0: + michael@0: +static cairo_status_t michael@0: +_cairo_win32_surface_span_renderer_render_row ( michael@0: + void *abstract_renderer, michael@0: + int y, michael@0: + const cairo_half_open_span_t *spans, michael@0: + unsigned num_spans) michael@0: +{ michael@0: + cairo_win32_surface_span_renderer_t *renderer = abstract_renderer; michael@0: + _cairo_image_surface_span_render_row (y, spans, num_spans, renderer->mask, &renderer->composite_rectangles); michael@0: + return CAIRO_STATUS_SUCCESS; michael@0: +} michael@0: + michael@0: +static void michael@0: +_cairo_win32_surface_span_renderer_destroy (void *abstract_renderer) michael@0: +{ michael@0: + cairo_win32_surface_span_renderer_t *renderer = abstract_renderer; michael@0: + if (!renderer) return; michael@0: + michael@0: + if (renderer->mask != NULL) michael@0: + cairo_surface_destroy (&renderer->mask->base); michael@0: + michael@0: + free (renderer); michael@0: +} michael@0: + michael@0: +static cairo_status_t michael@0: +_cairo_win32_surface_span_renderer_finish (void *abstract_renderer) michael@0: +{ michael@0: + cairo_win32_surface_span_renderer_t *renderer = abstract_renderer; michael@0: + cairo_status_t status = CAIRO_STATUS_SUCCESS; michael@0: + michael@0: + if (renderer->pattern == NULL || renderer->mask == NULL) michael@0: + return CAIRO_STATUS_SUCCESS; michael@0: + michael@0: + status = cairo_surface_status (&renderer->mask->base); michael@0: + if (status == CAIRO_STATUS_SUCCESS) { michael@0: + cairo_composite_rectangles_t *rects = &renderer->composite_rectangles; michael@0: + cairo_win32_surface_t *dst = renderer->dst; michael@0: + cairo_pattern_t *mask_pattern = cairo_pattern_create_for_surface (&renderer->mask->base); michael@0: + /* composite onto the image surface directly if we can */ michael@0: + if (dst->image) { michael@0: + GdiFlush(); michael@0: + michael@0: + status = dst->image->backend->composite (renderer->op, michael@0: + renderer->pattern, mask_pattern, dst->image, michael@0: + rects->src.x, michael@0: + rects->src.y, michael@0: + 0, 0, /* mask.x, mask.y */ michael@0: + rects->dst.x, rects->dst.y, michael@0: + rects->width, rects->height); michael@0: + } else { michael@0: + /* otherwise go through the fallback_composite path which michael@0: + * will do the appropriate surface acquisition */ michael@0: + status = _cairo_surface_fallback_composite ( michael@0: + renderer->op, michael@0: + renderer->pattern, mask_pattern, dst, michael@0: + rects->src.x, michael@0: + rects->src.y, michael@0: + 0, 0, /* mask.x, mask.y */ michael@0: + rects->dst.x, rects->dst.y, michael@0: + rects->width, rects->height); michael@0: + } michael@0: + cairo_pattern_destroy (mask_pattern); michael@0: + michael@0: + } michael@0: + if (status != CAIRO_STATUS_SUCCESS) michael@0: + return _cairo_span_renderer_set_error (abstract_renderer, michael@0: + status); michael@0: + return CAIRO_STATUS_SUCCESS; michael@0: +} michael@0: + michael@0: +static cairo_bool_t michael@0: +_cairo_win32_surface_check_span_renderer (cairo_operator_t op, michael@0: + const cairo_pattern_t *pattern, michael@0: + void *abstract_dst, michael@0: + cairo_antialias_t antialias, michael@0: + const cairo_composite_rectangles_t *rects) michael@0: +{ michael@0: + (void) op; michael@0: + (void) pattern; michael@0: + (void) abstract_dst; michael@0: + (void) antialias; michael@0: + (void) rects; michael@0: + return TRUE; michael@0: +} michael@0: + michael@0: +static cairo_span_renderer_t * michael@0: +_cairo_win32_surface_create_span_renderer (cairo_operator_t op, michael@0: + const cairo_pattern_t *pattern, michael@0: + void *abstract_dst, michael@0: + cairo_antialias_t antialias, michael@0: + const cairo_composite_rectangles_t *rects) michael@0: +{ michael@0: + cairo_win32_surface_t *dst = abstract_dst; michael@0: + cairo_win32_surface_span_renderer_t *renderer michael@0: + = calloc(1, sizeof(*renderer)); michael@0: + cairo_status_t status; michael@0: + int width = rects->width; michael@0: + int height = rects->height; michael@0: + michael@0: + if (renderer == NULL) michael@0: + return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY); michael@0: + michael@0: + renderer->base.destroy = _cairo_win32_surface_span_renderer_destroy; michael@0: + renderer->base.finish = _cairo_win32_surface_span_renderer_finish; michael@0: + renderer->base.render_row = michael@0: + _cairo_win32_surface_span_renderer_render_row; michael@0: + renderer->op = op; michael@0: + renderer->pattern = pattern; michael@0: + renderer->antialias = antialias; michael@0: + renderer->dst = dst; michael@0: + michael@0: + renderer->composite_rectangles = *rects; michael@0: + michael@0: + /* TODO: support rendering to A1 surfaces (or: go add span michael@0: + * compositing to pixman.) */ michael@0: + renderer->mask = (cairo_image_surface_t *) michael@0: + cairo_image_surface_create (CAIRO_FORMAT_A8, michael@0: + width, height); michael@0: + michael@0: + status = cairo_surface_status (&renderer->mask->base); michael@0: + michael@0: + if (status != CAIRO_STATUS_SUCCESS) { michael@0: + _cairo_win32_surface_span_renderer_destroy (renderer); michael@0: + return _cairo_span_renderer_create_in_error (status); michael@0: + } michael@0: + return &renderer->base; michael@0: +} michael@0: + michael@0: + michael@0: static const cairo_surface_backend_t cairo_win32_surface_backend = { michael@0: CAIRO_SURFACE_TYPE_WIN32, michael@0: _cairo_win32_surface_create_similar, michael@0: @@ -2060,8 +2202,8 @@ static const cairo_surface_backend_t cai michael@0: _cairo_win32_surface_composite, michael@0: _cairo_win32_surface_fill_rectangles, michael@0: NULL, /* composite_trapezoids */ michael@0: - NULL, /* create_span_renderer */ michael@0: - NULL, /* check_span_renderer */ michael@0: + _cairo_win32_surface_create_span_renderer, michael@0: + _cairo_win32_surface_check_span_renderer, michael@0: NULL, /* copy_page */ michael@0: NULL, /* show_page */ michael@0: _cairo_win32_surface_set_clip_region, michael@0: diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h michael@0: --- a/gfx/cairo/cairo/src/cairoint.h michael@0: +++ b/gfx/cairo/cairo/src/cairoint.h michael@0: @@ -2193,6 +2193,12 @@ _cairo_image_surface_set_clip_region (vo michael@0: cairo_private cairo_image_surface_t * michael@0: _cairo_image_surface_coerce (cairo_image_surface_t *surface, michael@0: cairo_format_t format); michael@0: +cairo_private void michael@0: +_cairo_image_surface_span_render_row (int y, michael@0: + const cairo_half_open_span_t *spans, michael@0: + unsigned num_spans, michael@0: + cairo_image_surface_t *mask, michael@0: + const cairo_composite_rectangles_t *rects); michael@0: michael@0: cairo_private cairo_image_transparency_t michael@0: _cairo_image_analyze_transparency (cairo_image_surface_t *image);