diff options
author | Kristian Høgsberg <krh@redhat.com> | 2005-06-03 16:40:15 +0000 |
---|---|---|
committer | Kristian Høgsberg <krh@redhat.com> | 2005-06-03 16:40:15 +0000 |
commit | 7b4a65dba4b37111ec56b9cbb5d462bc08d4b0db (patch) | |
tree | cfa1e28577a4df1b16eaa0aecf2bceb155cbc7bb | |
parent | 7c47633b2c74e329f04b9f1ebde4c05c409d73c0 (diff) |
When clipping, update the clip surface to a new surface the size of the intersection of the old clip surface and the extents of the new clip path.
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | src/cairo-gstate.c | 75 | ||||
-rw-r--r-- | test/clip-twice-ref.png | bin | 751 -> 1191 bytes | |||
-rw-r--r-- | test/clip-twice.c | 6 |
4 files changed, 72 insertions, 15 deletions
@@ -1,3 +1,9 @@ +2005-06-02 Kristian Høgsberg <krh@redhat.com> + + * src/cairo-gstate.c (_cairo_gstate_clip): When clipping, update + the clip surface to a new surface the size of the intersection of + the old clip surface and the extents of the new clip path. + 2005-06-03 Carl Worth <cworth@cworth.org> * src/cairoint.h: diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index c197b87ca..89eb3092a 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -1569,7 +1569,9 @@ _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path) cairo_status_t status; cairo_pattern_union_t pattern; cairo_traps_t traps; + cairo_rectangle_t surface_rect; cairo_box_t extents; + cairo_surface_t *surface; pixman_region16_t *region; /* Fill the clip region as traps. */ @@ -1621,38 +1623,81 @@ _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path) } } - /* Otherwise represent the clip as a mask surface. */ + /* Otherwise represent the clip as a mask surface. We create a + * new surface the size of the intersection of the old mask + * surface and the extents of the new clip path. */ if (gstate->clip.surface == NULL) { _cairo_traps_extents (&traps, &extents); - _cairo_box_round_to_rectangle (&extents, &gstate->clip.surface_rect); - gstate->clip.surface = - _cairo_surface_create_similar_solid (gstate->target, - CAIRO_FORMAT_A8, - gstate->clip.surface_rect.width, - gstate->clip.surface_rect.height, - CAIRO_COLOR_WHITE); - if (gstate->clip.surface == NULL) - return CAIRO_STATUS_NO_MEMORY; + _cairo_box_round_to_rectangle (&extents, &surface_rect); + } else { + _cairo_traps_extents (&traps, &extents); + _cairo_box_round_to_rectangle (&extents, &surface_rect); + _cairo_rectangle_intersect (&surface_rect, &gstate->clip.surface_rect); } - translate_traps (&traps, -gstate->clip.surface_rect.x, -gstate->clip.surface_rect.y); + surface = _cairo_surface_create_similar_solid (gstate->target, + CAIRO_FORMAT_A8, + surface_rect.width, + surface_rect.height, + CAIRO_COLOR_WHITE); + if (surface == NULL) + return CAIRO_STATUS_NO_MEMORY; + + /* Render the new clipping path into the new mask surface. */ + + translate_traps (&traps, -surface_rect.x, -surface_rect.y); _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE); status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN, &pattern.base, - gstate->clip.surface, + surface, 0, 0, 0, 0, - gstate->clip.surface_rect.width, - gstate->clip.surface_rect.height, + surface_rect.width, + surface_rect.height, traps.traps, traps.num_traps); _cairo_pattern_fini (&pattern.base); - _cairo_traps_fini (&traps); + if (!STATUS_OK (status)) { + cairo_surface_destroy (surface); + return status; + } + + /* If there was a clip surface already, combine it with the new + * mask surface using the IN operator, so we get the intersection + * of the old and new clipping paths. */ + + if (gstate->clip.surface != NULL) { + _cairo_pattern_init_for_surface (&pattern.surface, gstate->clip.surface); + + status = _cairo_surface_composite (CAIRO_OPERATOR_IN, + &pattern.base, + NULL, + surface, + surface_rect.x - gstate->clip.surface_rect.x, + surface_rect.y - gstate->clip.surface_rect.y, + 0, 0, + 0, 0, + surface_rect.width, + surface_rect.height); + + _cairo_pattern_fini (&pattern.base); + + if (!STATUS_OK (status)) { + cairo_surface_destroy (surface); + return status; + } + + cairo_surface_destroy (gstate->clip.surface); + } + + gstate->clip.surface = surface; + gstate->clip.surface_rect = surface_rect; + return CAIRO_STATUS_SUCCESS; } diff --git a/test/clip-twice-ref.png b/test/clip-twice-ref.png Binary files differindex ab0ae1aeb..bd3e3dbec 100644 --- a/test/clip-twice-ref.png +++ b/test/clip-twice-ref.png diff --git a/test/clip-twice.c b/test/clip-twice.c index eebfec944..446447c68 100644 --- a/test/clip-twice.c +++ b/test/clip-twice.c @@ -63,6 +63,12 @@ draw (cairo_t *cr, int width, int height) cairo_close_path (cr); cairo_fill (cr); + cairo_new_path (cr); + cairo_arc (cr, WIDTH / 2, HEIGHT / 2, WIDTH / 5, 0, 2 * M_PI); + cairo_clip (cr); + cairo_set_source_rgb (cr, 1, 1, 0); + cairo_paint (cr); + return CAIRO_TEST_SUCCESS; } |