summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2005-06-03 16:40:15 +0000
committerKristian Høgsberg <krh@redhat.com>2005-06-03 16:40:15 +0000
commit7b4a65dba4b37111ec56b9cbb5d462bc08d4b0db (patch)
treecfa1e28577a4df1b16eaa0aecf2bceb155cbc7bb
parent7c47633b2c74e329f04b9f1ebde4c05c409d73c0 (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--ChangeLog6
-rw-r--r--src/cairo-gstate.c75
-rw-r--r--test/clip-twice-ref.pngbin751 -> 1191 bytes
-rw-r--r--test/clip-twice.c6
4 files changed, 72 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index fe23fcd3f..0e0850e9c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index ab0ae1aeb..bd3e3dbec 100644
--- a/test/clip-twice-ref.png
+++ b/test/clip-twice-ref.png
Binary files differ
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;
}