[gtk] snapshot: Introduce transform APIs



commit 51fac44ba543f587e44b9c91d4d0eb6e7d90afb0
Author: Benjamin Otte <otte redhat com>
Date:   Thu Feb 21 04:24:24 2019 +0100

    snapshot: Introduce transform APIs
    
    Instead of gtk_snapshot_offset(), provide a full set of functions
    kept in sync with GtkTransform APIs.
    
    On top of that, add gtk_snapshot_save() and gtk_snapshot_restore()
    mirroring cairo_save()/restore() that allow saving a snapshot's
    transform state.

 docs/reference/gtk/gtk4-sections.txt |  10 ++
 gtk/gtksnapshot.c                    | 260 ++++++++++++++++++++++++++++++++++-
 gtk/gtksnapshot.h                    |  32 +++++
 gtk/gtksnapshotprivate.h             |   4 +
 4 files changed, 303 insertions(+), 3 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 1ed8a64df7..ddb3c3c2bc 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -4402,6 +4402,16 @@ gtk_snapshot_push_rounded_clip
 gtk_snapshot_push_cross_fade
 gtk_snapshot_push_blend
 gtk_snapshot_pop
+gtk_snapshot_save
+gtk_snapshot_restore
+gtk_snapshot_transform
+gtk_snapshot_transform_matrix
+gtk_snapshot_translate
+gtk_snapshot_translate_3d
+gtk_snapshot_rotate
+gtk_snapshot_rotate_3d
+gtk_snapshot_scale
+gtk_snapshot_scale_3d
 gtk_snapshot_offset
 gtk_snapshot_append_node
 gtk_snapshot_append_cairo
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index 11dfa7bff8..fed71a8f5b 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -275,8 +275,7 @@ gtk_snapshot_autopush_transform (GtkSnapshot *snapshot)
 static gboolean
 gtk_snapshot_state_should_autopop (const GtkSnapshotState *state)
 {
-  return state->collect_func == NULL ||
-         state->collect_func == gtk_snapshot_collect_autopush_transform;
+  return state->collect_func == gtk_snapshot_collect_autopush_transform;
 }
 
 static GskRenderNode *
@@ -1033,11 +1032,16 @@ gtk_snapshot_pop_internal (GtkSnapshot *snapshot)
 {
   GtkSnapshotState *state;
   GskRenderNode *node;
+  guint forgotten_restores = 0;
 
   for (state = gtk_snapshot_get_current_state (snapshot);
-       gtk_snapshot_state_should_autopop (state);
+       gtk_snapshot_state_should_autopop (state) ||
+       state->collect_func == NULL;
        state = gtk_snapshot_get_current_state (snapshot))
     {
+      if (state->collect_func == NULL)
+        forgotten_restores++;
+
       node = gtk_snapshot_pop_one (snapshot);
       if (node)
         {
@@ -1046,6 +1050,11 @@ gtk_snapshot_pop_internal (GtkSnapshot *snapshot)
         }
     }
 
+  if (forgotten_restores)
+    {
+      g_warning ("Too many gtk_snapshot_save() calls. %u saves remaining.", forgotten_restores);
+    }
+
   return gtk_snapshot_pop_one (snapshot);
 }
 
@@ -1149,6 +1158,251 @@ gtk_snapshot_pop (GtkSnapshot *snapshot)
     }
 }
 
+/**
+ * gtk_snapshot_save:
+ * @snapshot: a #GtkSnapshot
+ *
+ * Makes a copy of the current state of @snapshot and saves it
+ * on an internal stack of saved states for @snapshot. When
+ * gtk_snapshot_restore() is called, @snapshot will be restored to
+ * the saved state. Multiple calls to gtk_snapshot_save() and
+ * gtk_snapshot_restore() can be nested; each call to
+ * gtk_snapshot_restore() restores the state from the matching paired
+ * gtk_snapshot_save().
+ *
+ * It is necessary to clear all saved states with corresponding calls
+ * to gtk_snapshot_restore().
+ **/
+void
+gtk_snapshot_save (GtkSnapshot *snapshot)
+{
+  g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
+
+  gtk_snapshot_push_state (snapshot,
+                           gtk_snapshot_get_current_state (snapshot)->transform,
+                           NULL);
+}
+
+/**
+ * gtk_snapshot_restore:
+ * @snapshot: a #GtkSnapshot
+ *
+ * Restores @snapshot to the state saved by a preceding call to
+ * gtk_snapshot_save() and removes that state from the stack of
+ * saved states.
+ **/
+void
+gtk_snapshot_restore (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);
+        }
+    }
+
+  if (state->collect_func != NULL)
+    {
+      g_warning ("Too many gtk_snapshot_restore() calls.");
+      return;
+    }
+
+  node = gtk_snapshot_pop_one (snapshot);
+  g_assert (node == NULL);
+}
+
+/**
+ * gtk_snapshot_transform:
+ * @snapshot: a #GtkSnapshot
+ * @tranform: (allow-none): the transform to apply
+ *
+ * Transforms @snapshot's coordinate system with the given @transform.
+ **/
+void
+gtk_snapshot_transform (GtkSnapshot  *snapshot,
+                        GtkTransform *transform)
+{
+  GtkSnapshotState *state;
+
+  g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
+
+  state = gtk_snapshot_get_current_state (snapshot);
+  state->transform = gtk_transform_transform (state->transform, transform);
+}
+
+/**
+ * gtk_snapshot_transform_matrix:
+ * @snapshot: a #GtkSnapshot
+ * @matrix: the matrix to multiply the transform with
+ *
+ * Transforms @snapshot's coordinate system with the given @matrix.
+ **/
+void
+gtk_snapshot_transform_matrix (GtkSnapshot             *snapshot,
+                               const graphene_matrix_t *matrix)
+{
+  GtkSnapshotState *state;
+
+  g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
+  g_return_if_fail (matrix != NULL);
+
+  state = gtk_snapshot_get_current_state (snapshot);
+  state->transform = gtk_transform_matrix (state->transform, matrix);
+}
+
+void
+gtk_snapshot_transform_matrix_with_category (GtkSnapshot             *snapshot,
+                                             const graphene_matrix_t *matrix,
+                                             GskMatrixCategory        category)
+{
+  GtkSnapshotState *state;
+
+  g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
+  g_return_if_fail (matrix != NULL);
+
+  state = gtk_snapshot_get_current_state (snapshot);
+  state->transform = gtk_transform_matrix_with_category (state->transform, matrix, category);
+}
+
+/**
+ * gtk_snapshot_transform_translate:
+ * @snapshot: a #GtkSnapshot
+ * @point: the point to translate the snapshot by
+ *
+ * Translates @snapshot's coordinate system by @point in 2-dimensional space.
+ */
+void
+gtk_snapshot_translate (GtkSnapshot            *snapshot,
+                        const graphene_point_t *point)
+{
+  GtkSnapshotState *state;
+
+  g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
+  g_return_if_fail (point != NULL);
+
+  state = gtk_snapshot_get_current_state (snapshot);
+  state->transform = gtk_transform_translate (state->transform, point);
+}
+
+/**
+ * gtk_snapshot_transform_translate_3d:
+ * @snapshot: a #GtkSnapshot
+ * @point: the point to translate the snapshot by
+ *
+ * Translates @snapshot's coordinate system by @point.
+ */
+void
+gtk_snapshot_translate_3d (GtkSnapshot              *snapshot,
+                           const graphene_point3d_t *point)
+{
+  GtkSnapshotState *state;
+
+  g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
+  g_return_if_fail (point != NULL);
+
+  state = gtk_snapshot_get_current_state (snapshot);
+  state->transform = gtk_transform_translate_3d (state->transform, point);
+}
+
+/**
+ * gtk_snapshot_transform_rotate:
+ * @snapshot: a #GtkSnapshot
+ * @angle: the rotation angle, in degrees (clockwise)
+ *
+ * Rotates @@snapshot's coordinate system by @angle degrees in 2D space -
+ * or in 3D speak, rotates around the z axis.
+ */
+void
+gtk_snapshot_rotate (GtkSnapshot *snapshot,
+                     float        angle)
+{
+  GtkSnapshotState *state;
+
+  g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
+
+  state = gtk_snapshot_get_current_state (snapshot);
+  state->transform = gtk_transform_rotate (state->transform, angle);
+}
+
+/**
+ * gtk_snapshot_transform_rotate_3d:
+ * @snapshot: a #GtkSnapshot
+ * @angle: the rotation angle, in degrees (clockwise)
+ * @axis: The rotation axis
+ *
+ * Rotates @snapshot's coordinate system by @angle degrees around @axis.
+ *
+ * For a rotation in 2D space, use gtk_transform_rotate().
+ */
+void
+gtk_snapshot_rotate_3d (GtkSnapshot           *snapshot,
+                        float                  angle,
+                        const graphene_vec3_t *axis)
+{
+  GtkSnapshotState *state;
+
+  g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
+  g_return_if_fail (axis != NULL);
+
+  state = gtk_snapshot_get_current_state (snapshot);
+  state->transform = gtk_transform_rotate_3d (state->transform, angle, axis);
+}
+
+/**
+ * gtk_snapshot_scale:
+ * @snapshot: a #GtkSnapshot
+ * @factor_x: scaling factor on the X axis
+ * @factor_y: scaling factor on the Y axis
+ *
+ * Scales @@snapshot's coordinate system in 2-dimensional space by
+ * the given factors.
+ *
+ * Use gtk_snapshot_scale_3d() to scale in all 3 dimensions.
+ **/
+void
+gtk_snapshot_scale (GtkSnapshot *snapshot,
+                    float        factor_x,
+                    float        factor_y)
+{
+  GtkSnapshotState *state;
+
+  g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
+
+  state = gtk_snapshot_get_current_state (snapshot);
+  state->transform = gtk_transform_scale (state->transform, factor_x, factor_y);
+}
+
+/**
+ * gtk_snapshot_scale_3d:
+ * @snapshot: a #GtkSnapshot
+ * @factor_x: scaling factor on the X axis
+ * @factor_y: scaling factor on the Y axis
+ * @factor_z: scaling factor on the Z axis
+ *
+ * Scales @@snapshot's coordinate system by the given factors.
+ */
+void
+gtk_snapshot_scale_3d (GtkSnapshot *snapshot,
+                       float        factor_x,
+                       float        factor_y,
+                       float        factor_z)
+{
+  GtkSnapshotState *state;
+
+  g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
+
+  state = gtk_snapshot_get_current_state (snapshot);
+  state->transform = gtk_transform_scale_3d (state->transform, factor_x, factor_y, factor_z);
+}
+
 /**
  * gtk_snapshot_offset:
  * @snapshot: a #GtkSnapshot
diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h
index 485d160fc0..abaf20f057 100644
--- a/gtk/gtksnapshot.h
+++ b/gtk/gtksnapshot.h
@@ -104,6 +104,38 @@ void            gtk_snapshot_push_cross_fade            (GtkSnapshot
 GDK_AVAILABLE_IN_ALL
 void            gtk_snapshot_pop                        (GtkSnapshot            *snapshot);
 
+GDK_AVAILABLE_IN_ALL
+void            gtk_snapshot_save                       (GtkSnapshot            *snapshot);
+GDK_AVAILABLE_IN_ALL
+void            gtk_snapshot_restore                    (GtkSnapshot            *snapshot);
+GDK_AVAILABLE_IN_ALL
+void            gtk_snapshot_transform                  (GtkSnapshot            *snapshot,
+                                                         GtkTransform           *transform);
+GDK_AVAILABLE_IN_ALL
+void            gtk_snapshot_transform_matrix           (GtkSnapshot            *snapshot,
+                                                         const graphene_matrix_t*matrix);
+GDK_AVAILABLE_IN_ALL
+void            gtk_snapshot_translate                  (GtkSnapshot            *snapshot,
+                                                         const graphene_point_t *point);
+GDK_AVAILABLE_IN_ALL
+void            gtk_snapshot_translate_3d               (GtkSnapshot            *snapshot,
+                                                         const graphene_point3d_t*point);
+GDK_AVAILABLE_IN_ALL
+void            gtk_snapshot_rotate                     (GtkSnapshot            *snapshot,
+                                                         float                  angle);
+GDK_AVAILABLE_IN_ALL
+void            gtk_snapshot_rotate_3d                  (GtkSnapshot            *snapshot,
+                                                         float                   angle,
+                                                         const graphene_vec3_t  *axis);
+GDK_AVAILABLE_IN_ALL
+void            gtk_snapshot_scale                      (GtkSnapshot            *snapshot,
+                                                         float                   factor_x,
+                                                         float                   factor_y);
+GDK_AVAILABLE_IN_ALL
+void            gtk_snapshot_scale_3d                   (GtkSnapshot            *snapshot,
+                                                         float                   factor_x,
+                                                         float                   factor_y,
+                                                         float                   factor_z);
 GDK_AVAILABLE_IN_ALL
 void            gtk_snapshot_offset                     (GtkSnapshot            *snapshot,
                                                          int                     x,
diff --git a/gtk/gtksnapshotprivate.h b/gtk/gtksnapshotprivate.h
index 7750cf5dbf..6954392bf4 100644
--- a/gtk/gtksnapshotprivate.h
+++ b/gtk/gtksnapshotprivate.h
@@ -108,6 +108,10 @@ GtkSnapshot *           gtk_snapshot_new_with_parent            (GtkSnapshot
 void                    gtk_snapshot_push_transform_with_category (GtkSnapshot          *snapshot,
                                                                  const graphene_matrix_t*transform,
                                                                  GskMatrixCategory       category);
+void                    gtk_snapshot_transform_matrix_with_category
+                                                                (GtkSnapshot            *snapshot,
+                                                                 const graphene_matrix_t*matrix,
+                                                                 GskMatrixCategory       category);
 void                    gtk_snapshot_append_text                (GtkSnapshot            *snapshot,
                                                                  PangoFont              *font,
                                                                  PangoGlyphString       *glyphs,


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