diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c index c158007d2a..b9e90431cc 100644 --- a/gtk/gtksnapshot.c +++ b/gtk/gtksnapshot.c @@ -747,12 +747,18 @@ gtk_graphene_rect_scale_affine (const graphene_rect_t *rect, graphene_rect_normalize (res); } +typedef enum { + ENSURE_POSITIVE_SCALE = (1 << 0), + ENSURE_UNIFORM_SCALE = (1 << 1), +} GtkEnsureFlags; + static void -gtk_snapshot_ensure_affine (GtkSnapshot *snapshot, - float *scale_x, - float *scale_y, - float *dx, - float *dy) +gtk_snapshot_ensure_affine_with_flags (GtkSnapshot *snapshot, + GtkEnsureFlags flags, + float *scale_x, + float *scale_y, + float *dx, + float *dy) { const GtkSnapshotState *state = gtk_snapshot_get_current_state (snapshot); @@ -765,7 +771,8 @@ gtk_snapshot_ensure_affine (GtkSnapshot *snapshot, else if (gsk_transform_get_category (state->transform) == GSK_TRANSFORM_CATEGORY_2D_AFFINE) { gsk_transform_to_affine (state->transform, scale_x, scale_y, dx, dy); - if (*scale_x < 0.0 || *scale_y < 0.0) + if (((flags & ENSURE_POSITIVE_SCALE) && (*scale_x < 0.0 || *scale_y < 0.0)) || + ((flags & ENSURE_UNIFORM_SCALE) && (*scale_x != *scale_y))) { gtk_snapshot_autopush_transform (snapshot); state = gtk_snapshot_get_current_state (snapshot); @@ -778,6 +785,19 @@ gtk_snapshot_ensure_affine (GtkSnapshot *snapshot, } } +static void +gtk_snapshot_ensure_affine (GtkSnapshot *snapshot, + float *scale_x, + float *scale_y, + float *dx, + float *dy) +{ + gtk_snapshot_ensure_affine_with_flags (snapshot, + ENSURE_POSITIVE_SCALE, + scale_x, scale_y, + dx, dy); +} + static void gtk_snapshot_ensure_translate (GtkSnapshot *snapshot, float *dx, @@ -1377,11 +1397,19 @@ gtk_snapshot_push_shadow (GtkSnapshot *snapshot, const GskShadow *shadow, gsize n_shadows) { - const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot); GtkSnapshotState *state; + GskTransform *transform; + float scale_x, scale_y, dx, dy; + gsize i; + + gtk_snapshot_ensure_affine_with_flags (snapshot, + ENSURE_POSITIVE_SCALE | ENSURE_UNIFORM_SCALE, + &scale_x, &scale_y, + &dx, &dy); + transform = gsk_transform_scale (gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (dx, dy)), scale_x, scale_y); state = gtk_snapshot_push_state (snapshot, - current_state->transform, + transform, gtk_snapshot_collect_shadow, gtk_snapshot_clear_shadow); @@ -1390,13 +1418,23 @@ gtk_snapshot_push_shadow (GtkSnapshot *snapshot, { state->data.shadow.shadows = NULL; memcpy (&state->data.shadow.a_shadow, shadow, sizeof (GskShadow)); + state->data.shadow.a_shadow.dx *= scale_x; + state->data.shadow.a_shadow.dy *= scale_y; + state->data.shadow.a_shadow.radius *= scale_x; } else { state->data.shadow.shadows = g_malloc (sizeof (GskShadow) * n_shadows); memcpy (state->data.shadow.shadows, shadow, sizeof (GskShadow) * n_shadows); + for (i = 0; i < n_shadows; i++) + { + state->data.shadow.shadows[i].dx *= scale_x; + state->data.shadow.shadows[i].dy *= scale_y; + state->data.shadow.shadows[i].radius *= scale_x; + } } + gsk_transform_unref (transform); } static GskRenderNode * diff --git a/testsuite/gsk/compare/shadow-replay-nocairo.node b/testsuite/gsk/compare/shadow-replay-nocairo.node new file mode 100644 index 0000000000..1b5be16374 --- /dev/null +++ b/testsuite/gsk/compare/shadow-replay-nocairo.node @@ -0,0 +1,63 @@ +color { + bounds: -10 0 70 60; + color: white; +} + +transform { + transform: scale(5); + child: shadow { + shadows: black 0 1; + child: color { + bounds: 0 0 10 1; + color: red; + } + } +} + +transform { + transform: rotate(90); + child: shadow { + shadows: black 5 0; + child: color { + bounds: 20 -50 5 50; + color: lime; + } + } +} + +clip { + clip: 0 40 50 10; + child: color-matrix "larry" { + matrix: matrix3d(1000, 0, 0, 0, + 0, 1000, 0, 0, + 0, 0, 1000, 0, + 0, 0, 0, 1000); + child: transform { + transform: scale(5, 1); + child: shadow { + shadows: black 0 5 2; + child: color { + bounds: 0 40 10 5; + color: yellow; + } + } + } + } +} + +/* This should be covered by the blur above */ +clip { + clip: -10 45 5 5; + child: "larry"; +} +clip { + clip: 55 45 5 5; + child: "larry"; +} + +/* This should not */ +clip { + clip: 0 55 50 5; + child: "larry"; +} + diff --git a/testsuite/gsk/compare/shadow-replay-nocairo.png b/testsuite/gsk/compare/shadow-replay-nocairo.png new file mode 100644 index 0000000000..7bbad6ce18 Binary files /dev/null and b/testsuite/gsk/compare/shadow-replay-nocairo.png differ diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 9c7c61fb21..400824aad4 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -149,6 +149,7 @@ compare_render_tests = [ 'shadow-offset-clip', 'shadow-offset-to-outside-clip', 'shadow-opacity', + 'shadow-replay-nocairo', 'shrink-rounded-border', 'stroke', 'stroke-clipped-nogl',