From 8a323d7c8998f308fc222d65badb1289e3f7fb54 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 29 Aug 2009 14:15:07 +0100 Subject: [PATCH] [clip] Apply surface offset when combining with clip mask In order to correctly combine the clip mask with the compositing mask the clip path must be offset so that it is relative to the destination surface. --- src/cairo-clip-private.h | 2 +- src/cairo-clip.c | 85 ++++++++++++++++++---------------- src/cairo-region.c | 8 +++- src/cairo-surface-fallback.c | 8 +--- src/cairo-traps.c | 8 +--- src/cairo.h | 2 +- test/clip-stroke.xlib.ref.png | Bin 1563 -> 1490 bytes 7 files changed, 56 insertions(+), 57 deletions(-) diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h index f8faa75a1..131d4c7ef 100644 --- a/src/cairo-clip-private.h +++ b/src/cairo-clip-private.h @@ -116,7 +116,7 @@ _cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst); cairo_private cairo_status_t _cairo_clip_combine_with_surface (cairo_clip_t *clip, cairo_surface_t *dst, - int dst_x, int dst_y); + const cairo_rectangle_int_t *extents); cairo_private cairo_int_status_t _cairo_clip_get_region (cairo_clip_t *clip, diff --git a/src/cairo-clip.c b/src/cairo-clip.c index 0f4844241..6609f2842 100644 --- a/src/cairo-clip.c +++ b/src/cairo-clip.c @@ -973,6 +973,31 @@ _cairo_clip_path_to_boxes (cairo_clip_path_t *clip_path, return CAIRO_STATUS_SUCCESS; } +static cairo_status_t +_combine_region (cairo_surface_t *surface, + const cairo_region_t *region, + const cairo_rectangle_int_t *extents) +{ + cairo_region_t clear_region; + cairo_status_t status; + + _cairo_region_init_rectangle (&clear_region, extents); + status = cairo_region_subtract (&clear_region, region); + if (unlikely (status)) + return status; + + if (! cairo_region_is_empty (&clear_region)) { + cairo_region_translate (&clear_region, -extents->x, -extents->y); + status = _cairo_surface_fill_region (surface, + CAIRO_OPERATOR_CLEAR, + CAIRO_COLOR_TRANSPARENT, + &clear_region); + } + _cairo_region_fini (&clear_region); + + return status; +} + static cairo_surface_t * _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path, cairo_surface_t *target) @@ -1019,7 +1044,7 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path, if (unlikely (_cairo_status_is_error (status))) goto BAIL; - need_translate = clip_extents->x || clip_extents->y; + need_translate = clip_extents->x | clip_extents->y; if (status == CAIRO_STATUS_SUCCESS) { if (need_translate) { cairo_region_translate (clip_path->region, @@ -1069,18 +1094,7 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path, goto BAIL; if (status == CAIRO_STATUS_SUCCESS) { - if (need_translate) { - cairo_region_translate (prev->region, - -clip_extents->x, -clip_extents->y); - } - status = _cairo_surface_fill_region (surface, - CAIRO_OPERATOR_IN, - CAIRO_COLOR_WHITE, - prev->region); - if (need_translate) { - cairo_region_translate (prev->region, - clip_extents->x, clip_extents->y); - } + status = _combine_region (surface, prev->region, clip_extents); if (unlikely (status)) goto BAIL; } else if (prev->path.is_rectilinear) { @@ -1166,6 +1180,7 @@ _cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip) clip_path->region == NULL ? "no" : "yes", clip_path->surface == NULL ? "no" : "yes"); _cairo_debug_print_path (stream, &clip_path->path); + fprintf (stream, "\n"); } while ((clip_path = clip_path->prev) != NULL); } @@ -1179,12 +1194,11 @@ _cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target) cairo_status_t _cairo_clip_combine_with_surface (cairo_clip_t *clip, cairo_surface_t *dst, - int dst_x, - int dst_y) + const cairo_rectangle_int_t *extents) { cairo_pattern_union_t pattern; cairo_clip_path_t *clip_path = clip->path; - cairo_bool_t translate; + cairo_bool_t need_translate; cairo_status_t status; assert (clip_path != NULL); @@ -1195,8 +1209,8 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip, _cairo_pattern_init_for_surface (&pattern.surface, clip_path->surface); cairo_matrix_init_translate (&pattern.base.matrix, - dst_x - clip_path->extents.x, - dst_y - clip_path->extents.y); + extents->x - clip_path->extents.x, + extents->y - clip_path->extents.y); status = _cairo_surface_paint (dst, CAIRO_OPERATOR_IN, &pattern.base, @@ -1211,26 +1225,14 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR); - translate = dst_x | dst_y; + need_translate = extents->x | extents->y; do { status = _cairo_clip_path_to_region (clip_path); if (unlikely (_cairo_status_is_error (status))) return status; - if (status == CAIRO_STATUS_SUCCESS) { - if (translate) - cairo_region_translate (clip_path->region, -dst_x, -dst_y); - - status = _cairo_surface_fill_region (dst, - CAIRO_OPERATOR_IN, - CAIRO_COLOR_WHITE, - clip_path->region); - - if (translate) - cairo_region_translate (clip_path->region, dst_x, dst_y); - - return status; - } + if (status == CAIRO_STATUS_SUCCESS) + return _combine_region (dst, clip_path->region, extents); if (clip_path->surface != NULL && clip_path->surface->backend == dst->backend) @@ -1238,8 +1240,8 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip, _cairo_pattern_init_for_surface (&pattern.surface, clip_path->surface); cairo_matrix_init_translate (&pattern.base.matrix, - dst_x - clip_path->extents.x, - dst_y - clip_path->extents.y); + extents->x - clip_path->extents.x, + extents->y - clip_path->extents.y); status = _cairo_surface_paint (dst, CAIRO_OPERATOR_IN, &pattern.base, @@ -1250,10 +1252,10 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip, return status; } - if (translate) { + if (need_translate) { _cairo_path_fixed_translate (&clip_path->path, - _cairo_fixed_from_int (-dst_x), - _cairo_fixed_from_int (-dst_y)); + _cairo_fixed_from_int (-extents->x), + _cairo_fixed_from_int (-extents->y)); } status = _cairo_surface_fill (dst, CAIRO_OPERATOR_IN, @@ -1263,11 +1265,12 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip, clip_path->tolerance, clip_path->antialias, NULL); - if (translate) { + if (need_translate) { _cairo_path_fixed_translate (&clip_path->path, - _cairo_fixed_from_int (dst_x), - _cairo_fixed_from_int (dst_y)); + _cairo_fixed_from_int (extents->x), + _cairo_fixed_from_int (extents->y)); } + if (unlikely (status)) return status; } while ((clip_path = clip_path->prev) != NULL); diff --git a/src/cairo-region.c b/src/cairo-region.c index 9983481cc..2148fcabb 100644 --- a/src/cairo-region.c +++ b/src/cairo-region.c @@ -426,7 +426,7 @@ slim_hidden_def (cairo_region_status); * Since: 1.10 **/ cairo_status_t -cairo_region_subtract (cairo_region_t *dst, cairo_region_t *other) +cairo_region_subtract (cairo_region_t *dst, const cairo_region_t *other) { if (dst->status) return dst->status; @@ -434,8 +434,12 @@ cairo_region_subtract (cairo_region_t *dst, cairo_region_t *other) if (other->status) return _cairo_region_set_error (dst, other->status); - if (! pixman_region32_subtract (&dst->rgn, &dst->rgn, &other->rgn)) + if (! pixman_region32_subtract (&dst->rgn, + &dst->rgn, + CONST_CAST &other->rgn)) + { return _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); + } return CAIRO_STATUS_SUCCESS; } diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 0f5f8212e..79d719dc4 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -163,12 +163,8 @@ _create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern, if (unlikely (status)) goto CLEANUP_SURFACE; - if (clip_surface) { - status = _cairo_clip_combine_with_surface (clip, - mask, - extents->x, - extents->y); - } + if (clip_surface) + status = _cairo_clip_combine_with_surface (clip, mask, extents); _cairo_pattern_init_for_surface (mask_pattern, mask); diff --git a/src/cairo-traps.c b/src/cairo-traps.c index d6fec2602..70d4c69e0 100644 --- a/src/cairo-traps.c +++ b/src/cairo-traps.c @@ -264,9 +264,7 @@ _cairo_traps_tessellate_rectangle (cairo_traps_t *traps, continue; _left = left; - if (_left.p1.x <= limits->p1.x && - _left.p2.x <= limits->p1.x) - { + if (_left.p1.x < limits->p1.x) { _left.p1.x = limits->p1.x; _left.p1.y = limits->p1.y; _left.p2.x = limits->p1.x; @@ -274,9 +272,7 @@ _cairo_traps_tessellate_rectangle (cairo_traps_t *traps, } _right = right; - if (_right.p1.x >= limits->p2.x && - _right.p2.x >= limits->p2.x) - { + if (_right.p1.x > limits->p2.x) { _right.p1.x = limits->p2.x; _right.p1.y = limits->p1.y; _right.p2.x = limits->p2.x; diff --git a/src/cairo.h b/src/cairo.h index b750c4e32..a046a471f 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -2518,7 +2518,7 @@ cairo_public void cairo_region_translate (cairo_region_t *region, int dx, int dy); cairo_public cairo_status_t -cairo_region_subtract (cairo_region_t *dst, cairo_region_t *other); +cairo_region_subtract (cairo_region_t *dst, const cairo_region_t *other); cairo_public cairo_status_t cairo_region_subtract_rectangle (cairo_region_t *dst, diff --git a/test/clip-stroke.xlib.ref.png b/test/clip-stroke.xlib.ref.png index 142dc79d98b378a865c66ed4ba465cc902258066..b7767498f13bc51c7e25721bd21ba7199a055e28 100644 GIT binary patch delta 1454 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