[gtk] snapshot: Store an actual GtkTransform



commit 4a293aa762630bbf798f255dd6dc0a828db50344
Author: Benjamin Otte <otte redhat com>
Date:   Thu Feb 21 01:54:01 2019 +0100

    snapshot: Store an actual GtkTransform
    
    Instead of just tracking 2 integer translate_x/y coordinates, tracka a
    full GtkTransform.
    
    When creating actual nodes, if the transform is simple enough, just
    create the node in a way that makes use of the transform. If the
    node, can't represent the transform, just push a transform node instead
    and automatically pop that node with the next gtk_snapshot_pop() call.

 gtk/gtksnapshot.c        | 373 ++++++++++++++++++++++++++++-------------------
 gtk/gtksnapshotprivate.h |   3 +-
 2 files changed, 228 insertions(+), 148 deletions(-)
---
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index eccf83f99f..b862e5a7a6 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -28,6 +28,7 @@
 #include "gtkrendericonprivate.h"
 #include "gtkrendernodepaintableprivate.h"
 #include "gtkstylecontextprivate.h"
+#include "gtktransformprivate.h"
 
 #include "gsk/gskrendernodeprivate.h"
 
@@ -108,8 +109,7 @@ gtk_snapshot_collect_default (GtkSnapshot       *snapshot,
 
 static GtkSnapshotState *
 gtk_snapshot_push_state (GtkSnapshot            *snapshot,
-                         int                     translate_x,
-                         int                     translate_y,
+                         GtkTransform           *transform,
                          GtkSnapshotCollectFunc  collect_func)
 {
   const gsize n_states = snapshot->state_stack->len;
@@ -118,8 +118,7 @@ gtk_snapshot_push_state (GtkSnapshot            *snapshot,
   g_array_set_size (snapshot->state_stack, n_states + 1);
   state = &g_array_index (snapshot->state_stack, GtkSnapshotState, n_states);
 
-  state->translate_x = translate_x;
-  state->translate_y = translate_y;
+  state->transform = gtk_transform_ref (transform);
   state->collect_func = collect_func;
   state->start_node_index = snapshot->nodes->len;
   state->n_nodes = 0;
@@ -146,6 +145,7 @@ gtk_snapshot_get_previous_state (const GtkSnapshot *snapshot)
 static void
 gtk_snapshot_state_clear (GtkSnapshotState *state)
 {
+  gtk_transform_unref (state->transform);
 }
 
 /**
@@ -168,7 +168,7 @@ gtk_snapshot_new (void)
   snapshot->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_render_node_unref);
 
   gtk_snapshot_push_state (snapshot,
-                           0, 0,
+                           NULL,
                            gtk_snapshot_collect_default);
 
   return snapshot;
@@ -186,7 +186,7 @@ gtk_snapshot_new_with_parent (GtkSnapshot *parent_snapshot)
   snapshot->from_parent = TRUE;
 
   gtk_snapshot_push_state (snapshot,
-                           0, 0,
+                           NULL,
                            gtk_snapshot_collect_default);
 
   return snapshot;
@@ -235,6 +235,50 @@ gtk_snapshot_free_to_paintable (GtkSnapshot           *snapshot,
   return result;
 }
 
+static GskRenderNode *
+gtk_snapshot_collect_autopush_transform (GtkSnapshot      *snapshot,
+                                         GtkSnapshotState *state,
+                                         GskRenderNode   **nodes,
+                                         guint             n_nodes)
+{
+  GskRenderNode *node, *transform_node;
+
+  node = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes);
+  if (node == NULL)
+    return NULL;
+
+  transform_node = gsk_transform_node_new_with_category (node,
+                                                         &state->data.transform.transform,
+                                                         state->data.transform.category);
+
+  gsk_render_node_unref (node);
+
+  return transform_node;
+}
+
+static void
+gtk_snapshot_autopush_transform (GtkSnapshot *snapshot)
+{
+  GtkSnapshotState *previous_state;
+  GtkSnapshotState *state;
+
+  state = gtk_snapshot_push_state (snapshot,
+                                   NULL,
+                                   gtk_snapshot_collect_autopush_transform);
+
+  previous_state = gtk_snapshot_get_previous_state (snapshot);
+
+  gtk_transform_to_matrix (previous_state->transform, &state->data.transform.transform);
+  state->data.transform.category = gtk_transform_categorize (previous_state->transform);
+}
+
+static gboolean
+gtk_snapshot_state_should_autopop (const GtkSnapshotState *state)
+{
+  return state->collect_func == NULL ||
+         state->collect_func == gtk_snapshot_collect_autopush_transform;
+}
+
 static GskRenderNode *
 gtk_snapshot_collect_debug (GtkSnapshot      *snapshot,
                             GtkSnapshotState *state,
@@ -266,8 +310,7 @@ gtk_snapshot_push_debug (GtkSnapshot *snapshot,
   GtkSnapshotState *state;
 
   state = gtk_snapshot_push_state (snapshot,
-                                   current_state->translate_x,
-                                   current_state->translate_y,
+                                   current_state->transform,
                                    gtk_snapshot_collect_debug);
 
   if (GTK_DEBUG_CHECK (SNAPSHOT))
@@ -324,71 +367,15 @@ gtk_snapshot_push_transform_with_category (GtkSnapshot             *snapshot,
   graphene_matrix_t offset;
 
   state = gtk_snapshot_push_state (snapshot,
-                                   0, 0,
+                                   NULL,
                                    gtk_snapshot_collect_transform);
 
   previous_state = gtk_snapshot_get_previous_state (snapshot);
 
-  graphene_matrix_init_translate (&offset,
-                                  &GRAPHENE_POINT3D_INIT(
-                                      previous_state->translate_x,
-                                      previous_state->translate_y,
-                                      0
-                                  ));
+  gtk_transform_to_matrix (previous_state->transform, &offset);
 
   graphene_matrix_multiply (transform, &offset, &state->data.transform.transform);
-  if (previous_state->translate_x || previous_state->translate_y)
-    state->data.transform.category = MIN (GSK_MATRIX_CATEGORY_2D_TRANSLATE, category);
-  else
-    state->data.transform.category = category;
-}
-
-static GskRenderNode *
-gtk_snapshot_collect_offset (GtkSnapshot       *snapshot,
-                             GtkSnapshotState  *state,
-                             GskRenderNode    **nodes,
-                             guint              n_nodes)
-{
-  GskRenderNode *node, *result;
-  GtkSnapshotState  *previous_state;
-  graphene_matrix_t matrix;
-  GskMatrixCategory category;
-
-  node = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes);
-  if (node == NULL)
-    return NULL;
-
-  previous_state = gtk_snapshot_get_previous_state (snapshot);
-  if (previous_state->translate_x == 0.0 &&
-      previous_state->translate_y == 0.0)
-    return node;
-
-  graphene_matrix_init_translate (&matrix,
-                                  &GRAPHENE_POINT3D_INIT (previous_state->translate_x,
-                                                          previous_state->translate_y,
-                                                          0));
-  category = GSK_MATRIX_CATEGORY_2D_TRANSLATE;
-
-  if (gsk_render_node_get_node_type (node) == GSK_TRANSFORM_NODE)
-    {
-      node = gsk_render_node_ref (gsk_transform_node_get_child (node));
-      graphene_matrix_multiply (&matrix, gsk_transform_node_peek_transform (node), &matrix);
-      category = MIN (category, gsk_transform_node_get_category (node));
-    }
-  
-  result = gsk_transform_node_new_with_category (node, &matrix, category);
-
-  gsk_render_node_unref (node);
-
-  return result;
-}
-
-static void
-gtk_snapshot_push_offset (GtkSnapshot *snapshot)
-{
-  gtk_snapshot_push_state (snapshot,
-                           0, 0,
-                           gtk_snapshot_collect_offset);
+  state->data.transform.category = MIN (gtk_transform_categorize (previous_state->transform), category);
 }
 
 static GskRenderNode *
@@ -429,8 +416,7 @@ gtk_snapshot_push_opacity (GtkSnapshot *snapshot,
   GtkSnapshotState *state;
 
   state = gtk_snapshot_push_state (snapshot,
-                                   current_state->translate_x,
-                                   current_state->translate_y,
+                                   current_state->transform,
                                    gtk_snapshot_collect_opacity);
   state->data.opacity.opacity = CLAMP (opacity, 0.0, 1.0);
 }
@@ -468,8 +454,7 @@ gtk_snapshot_push_blur (GtkSnapshot *snapshot,
   GtkSnapshotState *state;
 
   state = gtk_snapshot_push_state (snapshot,
-                                   current_state->translate_x,
-                                   current_state->translate_y,
+                                   current_state->transform,
                                    gtk_snapshot_collect_blur);
   state->data.blur.radius = radius;
 }
@@ -534,8 +519,7 @@ gtk_snapshot_push_color_matrix (GtkSnapshot             *snapshot,
   GtkSnapshotState *state;
 
   state = gtk_snapshot_push_state (snapshot,
-                                   current_state->translate_x,
-                                   current_state->translate_y,
+                                   current_state->transform,
                                    gtk_snapshot_collect_color_matrix);
 
   graphene_matrix_init_from_matrix (&state->data.color_matrix.matrix, color_matrix);
@@ -565,26 +549,93 @@ gtk_snapshot_collect_repeat (GtkSnapshot      *snapshot,
   return repeat_node;
 }
 
+static void
+gtk_graphene_rect_scale_affine (const graphene_rect_t *rect,
+                                float                  scale_x,
+                                float                  scale_y,
+                                float                  dx,
+                                float                  dy,
+                                graphene_rect_t       *res)
+{
+  res->origin.x = scale_x * rect->origin.x + dx;
+  res->origin.y = scale_y * rect->origin.y + dy;
+  res->size.width = scale_x * rect->size.width;
+  res->size.height = scale_y * rect->size.height;
+  /* necessary when scale_x or scale_y are < 0 */
+  graphene_rect_normalize (res);
+}
+
+static void
+gtk_rounded_rect_scale_affine (GskRoundedRect       *dest,
+                               const GskRoundedRect *src,
+                               float                 scale_x,
+                               float                 scale_y,
+                               float                 dx,
+                               float                 dy)
+{
+  guint flip;
+  guint i;
+
+  g_assert (dest != src);
+
+  gtk_graphene_rect_scale_affine (&src->bounds, scale_x, scale_y, dx, dy, &dest->bounds);
+  flip = ((scale_x < 0) ? 1 : 0) + (scale_y < 0 ? 2 : 0);
+
+  for (i = 0; i < 4; i++)
+    {
+      dest->corner[i].width = src->corner[i ^ flip].width * fabsf (scale_x);
+      dest->corner[i].height = src->corner[i ^ flip].height * fabsf (scale_y);
+    }
+}
+
+static void
+gtk_snapshot_ensure_affine (GtkSnapshot *snapshot,
+                            float       *scale_x,
+                            float       *scale_y,
+                            float       *dx,
+                            float       *dy)
+{
+  const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
+
+  if (gtk_transform_to_affine (current_state->transform, scale_x, scale_y, dx, dy))
+    return;
+
+  gtk_snapshot_autopush_transform (snapshot);
+
+  *scale_x = *scale_y = 1;
+  *dx = *dy = 0;
+}
+
+static void
+gtk_snapshot_ensure_identity (GtkSnapshot *snapshot)
+{
+  const GtkSnapshotState *state = gtk_snapshot_get_current_state (snapshot);
+
+  if (state->transform == NULL)
+    return;
+
+  gtk_snapshot_autopush_transform (snapshot);
+}
+
 void
 gtk_snapshot_push_repeat (GtkSnapshot           *snapshot,
                           const graphene_rect_t *bounds,
                           const graphene_rect_t *child_bounds)
 {
-  const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
   GtkSnapshotState *state;
   graphene_rect_t real_child_bounds = { { 0 } };
+  float scale_x, scale_y, dx, dy;
+
+  gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
 
   if (child_bounds)
-    graphene_rect_offset_r (child_bounds, current_state->translate_x, current_state->translate_y, 
&real_child_bounds);
+    gtk_graphene_rect_scale_affine (child_bounds, scale_x, scale_y, dx, dy, &real_child_bounds);
 
   state = gtk_snapshot_push_state (snapshot,
-                                   current_state->translate_x,
-                                   current_state->translate_y,
+                                   gtk_snapshot_get_current_state (snapshot)->transform,
                                    gtk_snapshot_collect_repeat);
 
-  current_state = gtk_snapshot_get_previous_state (snapshot);
-
-  graphene_rect_offset_r (bounds, current_state->translate_x, current_state->translate_y, 
&state->data.repeat.bounds);
+  gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &state->data.repeat.bounds);
   state->data.repeat.child_bounds = real_child_bounds;
 }
 
@@ -619,18 +670,16 @@ void
 gtk_snapshot_push_clip (GtkSnapshot           *snapshot,
                         const graphene_rect_t *bounds)
 {
-  const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
   GtkSnapshotState *state;
-  graphene_rect_t real_bounds;
-
-  graphene_rect_offset_r (bounds, current_state->translate_x, current_state->translate_y, &real_bounds);
+  float scale_x, scale_y, dx, dy;
+ 
+  gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
 
   state = gtk_snapshot_push_state (snapshot,
-                                   current_state->translate_x,
-                                   current_state->translate_y,
+                                   gtk_snapshot_get_current_state (snapshot)->transform,
                                    gtk_snapshot_collect_clip);
 
-  state->data.clip.bounds = real_bounds;
+  gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &state->data.clip.bounds);
 }
 
 static GskRenderNode *
@@ -679,19 +728,16 @@ void
 gtk_snapshot_push_rounded_clip (GtkSnapshot          *snapshot,
                                 const GskRoundedRect *bounds)
 {
-  const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
   GtkSnapshotState *state;
-  GskRoundedRect real_bounds;
+  float scale_x, scale_y, dx, dy;
 
-  gsk_rounded_rect_init_copy (&real_bounds, bounds);
-  gsk_rounded_rect_offset (&real_bounds, current_state->translate_x, current_state->translate_y);
+  gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
 
   state = gtk_snapshot_push_state (snapshot,
-                                   current_state->translate_x,
-                                   current_state->translate_y,
+                                   gtk_snapshot_get_current_state (snapshot)->transform,
                                    gtk_snapshot_collect_rounded_clip);
 
-  state->data.rounded_clip.bounds = real_bounds;
+  gtk_rounded_rect_scale_affine (&state->data.rounded_clip.bounds, bounds, scale_x, scale_y, dx, dy);
 }
 
 static GskRenderNode *
@@ -727,8 +773,7 @@ gtk_snapshot_push_shadow (GtkSnapshot     *snapshot,
   GtkSnapshotState *state;
 
   state = gtk_snapshot_push_state (snapshot,
-                                   current_state->translate_x,
-                                   current_state->translate_y,
+                                   current_state->transform,
                                    gtk_snapshot_collect_shadow);
 
   state->data.shadow.n_shadows = n_shadows;
@@ -809,14 +854,12 @@ gtk_snapshot_push_blend (GtkSnapshot  *snapshot,
   GtkSnapshotState *top_state;
 
   top_state = gtk_snapshot_push_state (snapshot,
-                                       current_state->translate_x,
-                                       current_state->translate_y,
+                                       current_state->transform,
                                        gtk_snapshot_collect_blend_top);
   top_state->data.blend.blend_mode = blend_mode;
 
   gtk_snapshot_push_state (snapshot,
-                           top_state->translate_x,
-                           top_state->translate_y,
+                           top_state->transform,
                            gtk_snapshot_collect_blend_bottom);
 }
 
@@ -909,19 +952,17 @@ gtk_snapshot_push_cross_fade (GtkSnapshot *snapshot,
   GtkSnapshotState *end_state;
 
   end_state = gtk_snapshot_push_state (snapshot,
-                                       current_state->translate_x,
-                                       current_state->translate_y,
+                                       current_state->transform,
                                        gtk_snapshot_collect_cross_fade_end);
   end_state->data.cross_fade.progress = progress;
 
   gtk_snapshot_push_state (snapshot,
-                           end_state->translate_x,
-                           end_state->translate_y,
+                           end_state->transform,
                            gtk_snapshot_collect_cross_fade_start);
 }
 
 static GskRenderNode *
-gtk_snapshot_pop_internal (GtkSnapshot *snapshot)
+gtk_snapshot_pop_one (GtkSnapshot *snapshot)
 {
   GtkSnapshotState *state;
   guint state_index;
@@ -937,25 +978,60 @@ gtk_snapshot_pop_internal (GtkSnapshot *snapshot)
   state = gtk_snapshot_get_current_state (snapshot);
   state_index = snapshot->state_stack->len - 1;
 
-  node = state->collect_func (snapshot,
-                              state,
-                              (GskRenderNode **) snapshot->nodes->pdata + state->start_node_index,
-                              state->n_nodes);
+  if (state->collect_func)
+    {
+      node = state->collect_func (snapshot,
+                                  state,
+                                  (GskRenderNode **) snapshot->nodes->pdata + state->start_node_index,
+                                  state->n_nodes);
+
+      /* The collect func may not modify the state stack... */
+      g_assert (state_index == snapshot->state_stack->len - 1);
+
+      /* Remove all the state's nodes from the list of nodes */
+      g_assert (state->start_node_index + state->n_nodes == snapshot->nodes->len);
+      g_ptr_array_remove_range (snapshot->nodes,
+                                snapshot->nodes->len - state->n_nodes,
+                                state->n_nodes);
+    }
+  else
+    {
+      GtkSnapshotState *previous_state;
 
-  /* The collect func may not modify the state stack... */
-  g_assert (state_index == snapshot->state_stack->len - 1);
+      node = NULL;
 
-  /* Remove all the state's nodes from the list of nodes */
-  g_assert (state->start_node_index + state->n_nodes == snapshot->nodes->len);
-  g_ptr_array_remove_range (snapshot->nodes,
-                            snapshot->nodes->len - state->n_nodes,
-                            state->n_nodes);
+      /* move the nodes to the parent */
+      previous_state = gtk_snapshot_get_previous_state (snapshot);
+      previous_state->n_nodes += state->n_nodes;
+      g_assert (previous_state->start_node_index + previous_state->n_nodes == snapshot->nodes->len);
+    }
 
   g_array_remove_index (snapshot->state_stack, state_index);
 
   return node;
 }
 
+static GskRenderNode *
+gtk_snapshot_pop_internal (GtkSnapshot *snapshot)
+{
+  GtkSnapshotState *state;
+  GskRenderNode *node;
+
+  for (state = gtk_snapshot_get_current_state (snapshot);
+       gtk_snapshot_state_should_autopop (state);
+       state = gtk_snapshot_get_current_state (snapshot))
+    {
+      node = gtk_snapshot_pop_one (snapshot);
+      if (node)
+        {
+          gtk_snapshot_append_node_internal (snapshot, node);
+          gsk_render_node_unref (node);
+        }
+    }
+
+  return gtk_snapshot_pop_one (snapshot);
+}
+
 /**
  * gtk_snapshot_to_node:
  * @snapshot: a #GtkSnapshot
@@ -973,15 +1049,15 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot)
 {
   GskRenderNode *result;
 
+  result = gtk_snapshot_pop_internal (snapshot);
+
   /* We should have exactly our initial state */
-  if (snapshot->state_stack->len > 1 &&
+  if (snapshot->state_stack->len > 0 &&
       !snapshot->from_parent)
     {
       g_warning ("Too many gtk_snapshot_push() calls. %u states remaining.", snapshot->state_stack->len);
     }
 
-  result = gtk_snapshot_pop_internal (snapshot);
-
   if (!snapshot->from_parent)
     {
       g_array_free (snapshot->state_stack, TRUE);
@@ -1071,8 +1147,7 @@ gtk_snapshot_offset (GtkSnapshot *snapshot,
 {
   GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
 
-  current_state->translate_x += x;
-  current_state->translate_y += y;
+  current_state->transform = gtk_transform_translate (current_state->transform, &GRAPHENE_POINT_INIT (x, y));
 }
 
 /**
@@ -1097,13 +1172,14 @@ gtk_snapshot_get_offset (GtkSnapshot *snapshot,
                          int         *x,
                          int         *y)
 {
-  const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
+  /* FIXME: remove this function */
+  gtk_snapshot_ensure_identity (snapshot);
 
   if (x)
-    *x = current_state->translate_x;
+    *x = 0;
 
   if (y)
-    *y = current_state->translate_y;
+    *y = 0;
 }
 
 void
@@ -1142,9 +1218,9 @@ gtk_snapshot_append_node (GtkSnapshot   *snapshot,
   g_return_if_fail (snapshot != NULL);
   g_return_if_fail (GSK_IS_RENDER_NODE (node));
 
-  gtk_snapshot_push_offset (snapshot);
+  gtk_snapshot_ensure_identity (snapshot);
+
   gtk_snapshot_append_node_internal (snapshot, node);
-  gtk_snapshot_pop (snapshot);
 }
 
 /**
@@ -1162,15 +1238,16 @@ cairo_t *
 gtk_snapshot_append_cairo (GtkSnapshot           *snapshot,
                            const graphene_rect_t *bounds)
 {
-  const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
   GskRenderNode *node;
   graphene_rect_t real_bounds;
+  float scale_x, scale_y, dx, dy;
   cairo_t *cr;
 
   g_return_val_if_fail (snapshot != NULL, NULL);
   g_return_val_if_fail (bounds != NULL, NULL);
 
-  graphene_rect_offset_r (bounds, current_state->translate_x, current_state->translate_y, &real_bounds);
+  gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
+  gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &real_bounds);
 
   node = gsk_cairo_node_new (&real_bounds);
 
@@ -1179,7 +1256,8 @@ gtk_snapshot_append_cairo (GtkSnapshot           *snapshot,
 
   cr = gsk_cairo_node_get_draw_context (node);
 
-  cairo_translate (cr, current_state->translate_x, current_state->translate_y);
+  cairo_scale (cr, scale_x, scale_y);
+  cairo_translate (cr, dx, dy);
 
   return cr;
 }
@@ -1198,15 +1276,16 @@ gtk_snapshot_append_texture (GtkSnapshot           *snapshot,
                              GdkTexture            *texture,
                              const graphene_rect_t *bounds)
 {
-  GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
   GskRenderNode *node;
   graphene_rect_t real_bounds;
+  float scale_x, scale_y, dx, dy;
 
   g_return_if_fail (snapshot != NULL);
   g_return_if_fail (GDK_IS_TEXTURE (texture));
   g_return_if_fail (bounds != NULL);
 
-  graphene_rect_offset_r (bounds, current_state->translate_x, current_state->translate_y, &real_bounds);
+  gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
+  gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &real_bounds);
   node = gsk_texture_node_new (texture, &real_bounds);
 
   gtk_snapshot_append_node_internal (snapshot, node);
@@ -1229,16 +1308,16 @@ gtk_snapshot_append_color (GtkSnapshot           *snapshot,
                            const GdkRGBA         *color,
                            const graphene_rect_t *bounds)
 {
-  const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
   GskRenderNode *node;
   graphene_rect_t real_bounds;
+  float scale_x, scale_y, dx, dy;
 
   g_return_if_fail (snapshot != NULL);
   g_return_if_fail (color != NULL);
   g_return_if_fail (bounds != NULL);
 
-
-  graphene_rect_offset_r (bounds, current_state->translate_x, current_state->translate_y, &real_bounds);
+  gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
+  gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &real_bounds);
 
   node = gsk_color_node_new (color, &real_bounds);
 
@@ -1403,11 +1482,11 @@ gtk_snapshot_append_linear_gradient (GtkSnapshot            *snapshot,
                                      const GskColorStop     *stops,
                                      gsize                   n_stops)
 {
-  const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
   GskRenderNode *node;
   graphene_rect_t real_bounds;
   graphene_point_t real_start_point;
   graphene_point_t real_end_point;
+  float scale_x, scale_y, dx, dy;
 
   g_return_if_fail (snapshot != NULL);
   g_return_if_fail (start_point != NULL);
@@ -1415,11 +1494,12 @@ gtk_snapshot_append_linear_gradient (GtkSnapshot            *snapshot,
   g_return_if_fail (stops != NULL);
   g_return_if_fail (n_stops > 1);
 
-  graphene_rect_offset_r (bounds, current_state->translate_x, current_state->translate_y, &real_bounds);
-  real_start_point.x = start_point->x + current_state->translate_x;
-  real_start_point.y = start_point->y + current_state->translate_y;
-  real_end_point.x = end_point->x + current_state->translate_x;
-  real_end_point.y = end_point->y + current_state->translate_y;
+  gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
+  gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &real_bounds);
+  real_start_point.x = scale_x * start_point->x + dx;
+  real_start_point.y = scale_y * start_point->y + dy;
+  real_end_point.x = scale_x * end_point->x + dx;
+  real_end_point.y = scale_y * end_point->y + dy;
 
   node = gsk_linear_gradient_node_new (&real_bounds,
                                        &real_start_point,
@@ -1450,11 +1530,11 @@ gtk_snapshot_append_repeating_linear_gradient (GtkSnapshot            *snapshot,
                                                const GskColorStop     *stops,
                                                gsize                   n_stops)
 {
-  const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
   GskRenderNode *node;
   graphene_rect_t real_bounds;
   graphene_point_t real_start_point;
   graphene_point_t real_end_point;
+  float scale_x, scale_y, dx, dy;
 
   g_return_if_fail (snapshot != NULL);
   g_return_if_fail (start_point != NULL);
@@ -1462,11 +1542,12 @@ gtk_snapshot_append_repeating_linear_gradient (GtkSnapshot            *snapshot,
   g_return_if_fail (stops != NULL);
   g_return_if_fail (n_stops > 1);
 
-  graphene_rect_offset_r (bounds, current_state->translate_x, current_state->translate_y, &real_bounds);
-  real_start_point.x = start_point->x + current_state->translate_x;
-  real_start_point.y = start_point->y + current_state->translate_y;
-  real_end_point.x = end_point->x + current_state->translate_x;
-  real_end_point.y = end_point->y + current_state->translate_y;
+  gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
+  gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &real_bounds);
+  real_start_point.x = scale_x * start_point->x + dx;
+  real_start_point.y = scale_y * start_point->y + dy;
+  real_end_point.x = scale_x * end_point->x + dx;
+  real_end_point.y = scale_y * end_point->y + dy;
 
   node = gsk_repeating_linear_gradient_node_new (&real_bounds,
                                                  &real_start_point,
diff --git a/gtk/gtksnapshotprivate.h b/gtk/gtksnapshotprivate.h
index b03205d5cd..e19d0b2a20 100644
--- a/gtk/gtksnapshotprivate.h
+++ b/gtk/gtksnapshotprivate.h
@@ -35,8 +35,7 @@ struct _GtkSnapshotState {
   guint                  start_node_index;
   guint                  n_nodes;
 
-  int                    translate_x;
-  int                    translate_y;
+  GtkTransform *         transform;
 
   GtkSnapshotCollectFunc collect_func;
   union {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]