[gtk+/wip/otte/rendernode: 33/100] snapshot: Change how gtk_snapshot_push/pop works



commit 44c55ff37c5547874212fc85d23c6adea031419d
Author: Benjamin Otte <otte redhat com>
Date:   Tue Dec 13 02:33:15 2016 +0100

    snapshot: Change how gtk_snapshot_push/pop works
    
    Instead of appending a container node and adding the nodes to it as they
    come in, we now collect the nodes until gtk_snapshot_pop() is called and
    then hand them out in a container node.
    
    The caller of gtk_snapshot_push() is then responsible for doing whatever
    he wants with the created node.
    
    Another addigion is the keep_coordinates flag to gtk_snapshot_push()
    which allows callers to keep the current offset and clip region or
    discard it. Discarding is useful when doing transforms, keeping it is
    useful when inserting effect nodes (like the ones I'm about to add).

 docs/reference/gsk/gsk4-sections.txt |    1 -
 gsk/gskrendernode.h                  |   12 ++--
 gsk/gskrendernodeimpl.c              |   64 +++++++------------
 gtk/gtkrendericon.c                  |   15 ++--
 gtk/gtksnapshot.c                    |  117 ++++++++++++++++++++--------------
 gtk/gtksnapshot.h                    |    8 +--
 gtk/gtksnapshotprivate.h             |    4 +-
 7 files changed, 112 insertions(+), 109 deletions(-)
---
diff --git a/docs/reference/gsk/gsk4-sections.txt b/docs/reference/gsk/gsk4-sections.txt
index 102d084..4bbeba5 100644
--- a/docs/reference/gsk/gsk4-sections.txt
+++ b/docs/reference/gsk/gsk4-sections.txt
@@ -38,7 +38,6 @@ gsk_texture_node_new
 gsk_cairo_node_new
 gsk_cairo_node_get_draw_context
 gsk_container_node_new
-gsk_container_node_append_child
 gsk_container_node_get_n_children
 gsk_container_node_get_child
 gsk_transform_node_new
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index b98bd56..93a100e 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -55,15 +55,13 @@ cairo_t *               gsk_cairo_node_get_draw_context         (GskRenderNode
                                                                  GskRenderer              *renderer);
 
 GDK_AVAILABLE_IN_3_90
-GskRenderNode *         gsk_container_node_new                  (void);
+GskRenderNode *         gsk_container_node_new                  (GskRenderNode           **children,
+                                                                 guint                     n_children);
 GDK_AVAILABLE_IN_3_90
-GskRenderNode *         gsk_container_node_append_child         (GskRenderNode           *node,
-                                                                 GskRenderNode           *child);
+guint                   gsk_container_node_get_n_children       (GskRenderNode            *node);
 GDK_AVAILABLE_IN_3_90
-guint                   gsk_container_node_get_n_children       (GskRenderNode           *node);
-GDK_AVAILABLE_IN_3_90
-GskRenderNode *         gsk_container_node_get_child            (GskRenderNode           *node,
-                                                                 guint                    idx);
+GskRenderNode *         gsk_container_node_get_child            (GskRenderNode            *node,
+                                                                 guint                     idx);
 
 GDK_AVAILABLE_IN_3_90
 GskRenderNode *         gsk_transform_node_new                  (GskRenderNode            *child,
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index e719a1d..d23d18d 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -285,15 +285,20 @@ struct _GskContainerNode
 {
   GskRenderNode render_node;
 
-  GPtrArray *children;
+  GskRenderNode **children;
+  guint n_children;
 };
 
 static void
 gsk_container_node_finalize (GskRenderNode *node)
 {
   GskContainerNode *container = (GskContainerNode *) node;
+  guint i;
+
+  for (i = 0; i < container->n_children; i++)
+    gsk_render_node_unref (container->children[i]);
 
-  g_ptr_array_unref (container->children);
+  g_free (container->children);
 }
 
 static void
@@ -302,9 +307,9 @@ gsk_container_node_make_immutable (GskRenderNode *node)
   GskContainerNode *container = (GskContainerNode *) node;
   guint i;
 
-  for (i = 1; i < container->children->len; i++)
+  for (i = 1; i < container->n_children; i++)
     {
-      gsk_render_node_make_immutable (g_ptr_array_index (container->children, i));
+      gsk_render_node_make_immutable (container->children[i]);
     }
 }
 
@@ -343,53 +348,32 @@ static const GskRenderNodeClass GSK_CONTAINER_NODE_CLASS = {
 
 /**
  * gsk_container_node_new:
+ * @children: (array length=n_children) (transfer none): The children of the node
+ * @n_children: Number of children in the @children array
  *
- * Creates a new #GskRenderNode instance for holding multiple different
- * render nodes. You can use gsk_container_node_append_child() to add
- * nodes to the container.
+ * Creates a new #GskRenderNode instance for holding the given @children.
+ * The new node will acquire a reference to each of the children.
  *
  * Returns: (transfer full): the new #GskRenderNode
  *
  * Since: 3.90
  */
 GskRenderNode *
-gsk_container_node_new (void)
+gsk_container_node_new (GskRenderNode **children,
+                        guint           n_children)
 {
   GskContainerNode *container;
+  guint i;
 
   container = (GskContainerNode *) gsk_render_node_new (&GSK_CONTAINER_NODE_CLASS);
 
-  container->children = g_ptr_array_new_with_free_func ((GDestroyNotify) gsk_render_node_unref);
+  container->children = g_memdup (children, sizeof (GskRenderNode *) * n_children);
+  container->n_children = n_children;
 
-  return &container->render_node;
-}
+  for (i = 0; i < container->n_children; i++)
+    gsk_render_node_ref (container->children[i]);
 
-/**
- * gsk_container_node_append_child:
- * @node: a container node
- * @child: a #GskRenderNode
- *
- * Appends @child to the list of children of @node.
- *
- * This function acquires a reference on @child.
- *
- * Returns: (transfer none): the #GskRenderNode
- *
- * Since: 3.90
- */
-GskRenderNode *
-gsk_container_node_append_child (GskRenderNode *node,
-                                 GskRenderNode *child)
-{
-  GskContainerNode *container = (GskContainerNode *) node;
-
-  g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_CONTAINER_NODE), NULL);
-  g_return_val_if_fail (GSK_IS_RENDER_NODE (child), node);
-  g_return_val_if_fail (node->is_mutable, node);
-
-  g_ptr_array_add (container->children, gsk_render_node_ref (child));
-
-  return node;
+  return &container->render_node;
 }
 
 /**
@@ -409,7 +393,7 @@ gsk_container_node_get_n_children (GskRenderNode *node)
 
   g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_CONTAINER_NODE), 0);
 
-  return container->children->len;
+  return container->n_children;
 }
 
 GskRenderNode *
@@ -419,9 +403,9 @@ gsk_container_node_get_child (GskRenderNode *node,
   GskContainerNode *container = (GskContainerNode *) node;
 
   g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_CONTAINER_NODE), NULL);
-  g_return_val_if_fail (idx < container->children->len, 0);
+  g_return_val_if_fail (idx < container->n_children, 0);
 
-  return g_ptr_array_index (container->children, idx);
+  return container->children[idx];
 }
 
 /*** GSK_TRANSFORM_NODE ***/
diff --git a/gtk/gtkrendericon.c b/gtk/gtkrendericon.c
index 0304f0d..082f87d 100644
--- a/gtk/gtkrendericon.c
+++ b/gtk/gtkrendericon.c
@@ -126,7 +126,7 @@ gtk_css_style_snapshot_icon (GtkCssStyle            *style,
   else
     {
       graphene_matrix_t m1, m2, m3;
-      GskRenderNode *transform_node, *container_node;
+      GskRenderNode *transform_node, *icon_node;
       double offset_x, offset_y;
 
       gtk_snapshot_get_offset (snapshot, &offset_x, &offset_y);
@@ -136,15 +136,16 @@ gtk_css_style_snapshot_icon (GtkCssStyle            *style,
       graphene_matrix_init_translate (&m2, &GRAPHENE_POINT3D_INIT(- width / 2.0, - height / 2.0, 0));
       graphene_matrix_multiply (&m2, &m3, &m1);
 
-      container_node = gsk_container_node_new ();
-      gsk_render_node_set_name (container_node, "CSS Icon Transform Container");
-      transform_node = gsk_transform_node_new (container_node, &m1);
+      gtk_snapshot_push (snapshot, FALSE, "CSS Icon Transform Container");
+      gtk_css_image_builtin_snapshot (image, snapshot, width, height, builtin_type);
+      icon_node = gtk_snapshot_pop (snapshot);
+
+      transform_node = gsk_transform_node_new (icon_node, &m1);
       gsk_render_node_set_name (transform_node, "CSS Icon Transform");
       gtk_snapshot_append_node (snapshot, transform_node);
       
-      gtk_snapshot_push_node (snapshot, container_node);
-      gtk_css_image_builtin_snapshot (image, snapshot, width, height, builtin_type);
-      gtk_snapshot_pop (snapshot);
+      gsk_render_node_unref (transform_node);
+      gsk_render_node_unref (icon_node);
     }
 }
 
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index 331e980..ff0eda2 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -50,15 +50,21 @@
 
 static GtkSnapshotState *
 gtk_snapshot_state_new (GtkSnapshotState *parent,
+                        char             *name,
                         cairo_region_t   *clip,
-                        GskRenderNode    *node)
+                        double            translate_x,
+                        double            translate_y)
 {
   GtkSnapshotState *state;
 
   state = g_slice_new0 (GtkSnapshotState);
 
-  state->node = node;
+  state->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify) gsk_render_node_unref);
+
   state->parent = parent;
+  state->name = name;
+  state->translate_x = translate_x;
+  state->translate_y = translate_y;
   if (clip)
     state->clip_region = cairo_region_reference (clip);
 
@@ -68,9 +74,13 @@ gtk_snapshot_state_new (GtkSnapshotState *parent,
 static void
 gtk_snapshot_state_free (GtkSnapshotState *state)
 {
+  g_ptr_array_unref (state->nodes);
+
   if (state->clip_region)
     cairo_region_destroy (state->clip_region);
 
+  g_free (state->name);
+
   g_slice_free (GtkSnapshotState, state);
 }
 
@@ -81,66 +91,49 @@ gtk_snapshot_init (GtkSnapshot          *snapshot,
                    const char           *name,
                    ...)
 {
-  cairo_rectangle_int_t extents;
-
-  cairo_region_get_extents (clip, &extents);
+  char *str;
 
   snapshot->state = NULL;
   snapshot->renderer = renderer;
-  snapshot->root = gsk_container_node_new ();
 
   if (name)
     {
       va_list args;
-      char *str;
 
       va_start (args, name);
       str = g_strdup_vprintf (name, args);
       va_end (args);
-
-      gsk_render_node_set_name (snapshot->root, str);
-
-      g_free (str);
     }
+  else
+    str = NULL;
 
-  snapshot->state = gtk_snapshot_state_new (NULL, (cairo_region_t *) clip, snapshot->root);
+  snapshot->state = gtk_snapshot_state_new (NULL,
+                                            str,
+                                            (cairo_region_t *) clip,
+                                            0, 0);
 }
 
 GskRenderNode *
 gtk_snapshot_finish (GtkSnapshot *snapshot)
 {
-  gtk_snapshot_pop (snapshot);
+  GskRenderNode *result;
+  
+  result = gtk_snapshot_pop (snapshot);
 
   if (snapshot->state != NULL)
     {
       g_warning ("Too many gtk_snapshot_push() calls.");
     }
 
-  return snapshot->root;
-}
-
-/**
- * gtk_snapshot_push_node:
- * @snapshot: a #GtkSnapshot
- * @node: the render node to push
- *
- * Makes @node the new current render node. You are responsible for adding
- * @node to the snapshot.
- *
- * Since: 3.90
- */
-void
-gtk_snapshot_push_node (GtkSnapshot   *snapshot,
-                        GskRenderNode *node)
-{
-  g_return_if_fail (gsk_render_node_get_node_type (node) == GSK_CONTAINER_NODE);
-
-  snapshot->state = gtk_snapshot_state_new (snapshot->state, snapshot->state->clip_region, node);
+  return result;
 }
 
 /**
  * gtk_snapshot_push:
  * @snapshot: a #GtkSnapshot
+ * @keep_coordinates: If %TRUE, the current offset and clip will be kept.
+ *     Otherwise, the clip will be unset and the offset will be reset to
+ *     (0, 0).
  * @bounds: the bounds for the new node
  * @name: (transfer none): a printf() style format string for the name for the new node
  * @...: arguments to insert into the format string
@@ -152,30 +145,38 @@ gtk_snapshot_push_node (GtkSnapshot   *snapshot,
  */
 void
 gtk_snapshot_push (GtkSnapshot           *snapshot,
+                   gboolean               keep_coordinates,
                    const char            *name,
                    ...)
 {
-  GskRenderNode *node;
-
-  node = gsk_container_node_new ();
+  char *str;
 
   if (name)
     {
       va_list args;
-      char *str;
 
       va_start (args, name);
       str = g_strdup_vprintf (name, args);
       va_end (args);
-
-      gsk_render_node_set_name (node, str);
-
-      g_free (str);
     }
+  else
+    str = NULL;
 
-  gtk_snapshot_append_node (snapshot, node);
-  gtk_snapshot_push_node (snapshot, node);
-  gsk_render_node_unref (node);
+  if (keep_coordinates)
+    {
+      snapshot->state = gtk_snapshot_state_new (snapshot->state,
+                                                str,
+                                                snapshot->state->clip_region,
+                                                snapshot->state->translate_x,
+                                                snapshot->state->translate_y);
+    }
+  else
+    {
+      snapshot->state = gtk_snapshot_state_new (snapshot->state,
+                                                str,
+                                                NULL,
+                                                0, 0);
+    }
 }
 
 /**
@@ -185,23 +186,45 @@ gtk_snapshot_push (GtkSnapshot           *snapshot,
  * Removes the top element from the stack of render nodes,
  * making the node underneath the current node again.
  *
+ * Returns: (transfer full) (allow none): A #GskRenderNode for
+ *     the contents that were rendered to @snapshot since
+ *     the corresponding gtk_snapshot_push() call
+ *
  * Since: 3.90
  */
-void
+GskRenderNode *
 gtk_snapshot_pop (GtkSnapshot *snapshot)
 {
   GtkSnapshotState *state;
+  GskRenderNode *node;
 
   if (snapshot->state == NULL)
     {
       g_warning ("Too many gtk_snapshot_pop() calls.");
-      return;
+      return NULL;
     }
 
   state = snapshot->state;
   snapshot->state = state->parent;
 
+  if (state->nodes->len == 0)
+    {
+      node = NULL;
+    }
+  else if (state->nodes->len == 1)
+    {
+      node = gsk_render_node_ref (g_ptr_array_index (state->nodes, 0));
+    }
+  else
+    {
+      node = gsk_container_node_new ((GskRenderNode **) state->nodes->pdata,
+                                     state->nodes->len);
+      gsk_render_node_set_name (node, state->name);
+    }
+
   gtk_snapshot_state_free (state);
+
+  return node;
 }
 
 /**
@@ -288,7 +311,7 @@ gtk_snapshot_append_node (GtkSnapshot   *snapshot,
 
   if (snapshot->state)
     {
-      gsk_container_node_append_child (snapshot->state->node, node);
+      g_ptr_array_add (snapshot->state->nodes, gsk_render_node_ref (node));
     }
   else
     {
diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h
index 6acb5aa..2c62533 100644
--- a/gtk/gtksnapshot.h
+++ b/gtk/gtksnapshot.h
@@ -41,13 +41,11 @@ GskRenderer *   gtk_snapshot_get_renderer               (const GtkSnapshot
 
 GDK_AVAILABLE_IN_3_90
 void            gtk_snapshot_push                       (GtkSnapshot            *snapshot,
+                                                         gboolean                keep_coordinates,
                                                          const char             *name,
-                                                         ...) G_GNUC_PRINTF(2, 3);
+                                                         ...) G_GNUC_PRINTF (3, 4);
 GDK_AVAILABLE_IN_3_90
-void            gtk_snapshot_push_node                  (GtkSnapshot            *snapshot,
-                                                         GskRenderNode          *node);
-GDK_AVAILABLE_IN_3_90
-void            gtk_snapshot_pop                        (GtkSnapshot            *snapshot);
+GskRenderNode * gtk_snapshot_pop                        (GtkSnapshot            *snapshot) 
G_GNUC_WARN_UNUSED_RESULT;
 
 GDK_AVAILABLE_IN_3_90
 void            gtk_snapshot_translate_2d               (GtkSnapshot            *snapshot,
diff --git a/gtk/gtksnapshotprivate.h b/gtk/gtksnapshotprivate.h
index 54b3a6b..eb8cbac 100644
--- a/gtk/gtksnapshotprivate.h
+++ b/gtk/gtksnapshotprivate.h
@@ -27,7 +27,8 @@ typedef struct _GtkSnapshotState GtkSnapshotState;
 struct _GtkSnapshotState {
   GtkSnapshotState      *parent;
 
-  GskRenderNode         *node;
+  char                  *name;
+  GPtrArray             *nodes;
 
   cairo_region_t        *clip_region;
   double                 translate_x;
@@ -37,7 +38,6 @@ struct _GtkSnapshotState {
 struct _GtkSnapshot {
   GtkSnapshotState      *state;
 
-  GskRenderNode         *root;
   GskRenderer           *renderer;
 };
 


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