From 7b4a65dba4b37111ec56b9cbb5d462bc08d4b0db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 3 Jun 2005 16:40:15 +0000 Subject: [PATCH] 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. --- ChangeLog | 6 ++++ src/cairo-gstate.c | 75 ++++++++++++++++++++++++++++++++-------- test/clip-twice-ref.png | Bin 751 -> 1191 bytes test/clip-twice.c | 6 ++++ 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 + + * 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 * 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 ab0ae1aeb158439e272bd6fa7f158ef68918d812..bd3e3dbec7247c628fc04d4e8f518666eb4eb41d 100644 GIT binary patch delta 1153 zcmV-{1b+MP1*Zv+HGcpHbV*G`2h|1x7a$?iR{VPa00c=%L_t(|ob8%VXdG1>$3HV0 z+7)clpn_Q%q>@Vy?N$(5w+g9xkfhF~gj^cfhG4n}Deg@V4ckLK2=U+{jg(|1z2&w| zf(QRBsL_-bvlJ~?;-bFbMkAN0aw#tdw@ih;3YL3X;vYTQMnyV`Ph@m+CBeY4IVG{ z_OzFa91Wh-QFwZV$PYY^Lx% zLDGP)X2I==($cajT)#fSfdgW%?#GXloI5v2sg#b`!dw2 z8&fFUptUu&a-G)JEeeGjA+3zEmzx-pb-+#yzki#~&ULccc{$ktvf256UYnvh1tDob zuH0xASXL$URVPDBixcoHFv{V}Y=0CgL4U`4dhWY@H{M_78dC3qOYs=39Ndx?^K0v9I#FhWL0|SFm27ezZw|Zm@_yO;@Dv(ksO+MeJWP;-u`7d3xa0@O<)oBy(xQQtWdF>-+J;+ zX=&d2H=I>32l?Z2#gc7k3HSi-pz>Ms#EY$VOddncI=leRyTF>dR%F(^m})1(5Ziu0 z?j|Ho0*lf67-euyd%xga<~kO=SnA&ffc`{Ae5pcuAFVlhYD_B4E*La1BJc2-b8Tbg?&L`fD^dNZw zwIgky91LhL1Am`^Tl!dDoB_|EdZ-DaG+=uk1_!_$T^uo8C_m6Fhmt(^&Rn+UCpCFo z?!m6pB12)oMT3zyyh2&bw1^Ncfvp9Iesb+k-Pq|vdQWmr5LQ5`K{%5Kn8`GGBdCDZ z5|n<)#uiEn$z9)Lv!DW^Rl=J*K$L0oLSlgW@KGH8+J6KFRKK}nY-mKW)8>b86C9r5 zLqeuWv6esVdt6`&CW_&;_xcCbK`5jukZV!y<{?yp{ON5gHK6(;p(Q0-*sRJ^djvO@ebk`w{R}l57k- z_Pq}XDt{oo?>}Z-_-m6Gu#an3g+`ib^Fm-i?HHmx|8YeV?Ma%b!c8!#<9c5td sz+REDm!zitH95mD48t%C!!V|k--0T@B=Vk*vj6}907*qoM6N<$f}F8PS^xk5 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; }