From: Benjamin Otte Date: Mon, 18 Sep 2023 05:48:10 +0000 (+0200) Subject: gsk: Fix clipping error when drawing shadows X-Git-Tag: archive/raspbian/4.12.4+ds-3+rpi1^2~21^2~2^2~8 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=152c09ee86a97fd141d51f617b492922522df1dd;p=gtk4.git gsk: Fix clipping error when drawing shadows When shadows were offset - in particular when offset so the original source was out of bounds of the result - the drawing code would create a pattern for it that didn't include enough of it to compose a shadow. Fix that by not creating those patterns anymore, but instead drawing the source (potentially multiple times) at the required offsets. While that does more drawing, it simplifies the shadow node draw code, and that's the primary goal of the Cairo rendering. Test included. --- diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index 80bf406ae3..3790fcb4c3 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -4432,18 +4432,8 @@ gsk_shadow_node_draw (GskRenderNode *node, cairo_t *cr) { GskShadowNode *self = (GskShadowNode *) node; - cairo_pattern_t *pattern; gsize i; - cairo_save (cr); - /* clip so the push_group() creates a small surface */ - gsk_cairo_rectangle (cr, &self->child->bounds); - cairo_clip (cr); - cairo_push_group (cr); - gsk_render_node_draw (self->child, cr); - pattern = cairo_pop_group (cr); - cairo_restore (cr); - cairo_save (cr); /* clip so the blur area stays small */ gsk_cairo_rectangle (cr, &node->bounds); @@ -4452,27 +4442,31 @@ gsk_shadow_node_draw (GskRenderNode *node, for (i = 0; i < self->n_shadows; i++) { GskShadow *shadow = &self->shadows[i]; + cairo_pattern_t *pattern; /* We don't need to draw invisible shadows */ if (gdk_rgba_is_clear (&shadow->color)) continue; cairo_save (cr); - gdk_cairo_set_source_rgba (cr, &shadow->color); cr = gsk_cairo_blur_start_drawing (cr, shadow->radius, GSK_BLUR_X | GSK_BLUR_Y); + cairo_save (cr); cairo_translate (cr, shadow->dx, shadow->dy); + cairo_push_group (cr); + gsk_render_node_draw (self->child, cr); + pattern = cairo_pop_group (cr); + gdk_cairo_set_source_rgba (cr, &shadow->color); cairo_mask (cr, pattern); + cairo_restore (cr); cr = gsk_cairo_blur_finish_drawing (cr, shadow->radius, &shadow->color, GSK_BLUR_X | GSK_BLUR_Y); cairo_restore (cr); } - cairo_set_source (cr, pattern); - cairo_paint (cr); - cairo_restore (cr); + gsk_render_node_draw (self->child, cr); - cairo_pattern_destroy (pattern); + cairo_restore (cr); } static void diff --git a/testsuite/gsk/compare/shadow-clip-contents.node b/testsuite/gsk/compare/shadow-clip-contents.node new file mode 100644 index 0000000000..8906577319 --- /dev/null +++ b/testsuite/gsk/compare/shadow-clip-contents.node @@ -0,0 +1,10 @@ +clip { + clip: 0 0 50 50; + child: shadow { + shadows: rgb(0,0,0) -20 -20; + child: color { + bounds: 40 40 50 50; + color: rgb(255,0,204); + } + } +} diff --git a/testsuite/gsk/compare/shadow-clip-contents.png b/testsuite/gsk/compare/shadow-clip-contents.png new file mode 100644 index 0000000000..ffe7bff09a Binary files /dev/null and b/testsuite/gsk/compare/shadow-clip-contents.png differ diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index bbcefc9205..cd1a32c331 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -90,6 +90,7 @@ compare_render_tests = [ 'scaled-cairo', 'scaled-texture', 'shadow-behind', + 'shadow-clip-contents', 'shadow-in-opacity', 'shadow-opacity', 'shrink-rounded-border',