[gtk+/wip/otte/rendernode: 4/34] gsk: Add gsk_render_node_draw()



commit 742baa15235dc55be47593c00d129b86204384ba
Author: Benjamin Otte <otte redhat com>
Date:   Tue Dec 13 03:05:15 2016 +0100

    gsk: Add gsk_render_node_draw()
    
    Draws a node to a given cairo_t. This is mostly intended for fallback
    usage.

 docs/reference/gsk/gsk4-sections.txt |    1 +
 gsk/gskcairorenderer.c               |  117 +---------------------------------
 gsk/gskrendernode.c                  |   59 +++++++++++++++++
 gsk/gskrendernode.h                  |    3 +
 gsk/gskrendernodeimpl.c              |   87 ++++++++++++++++++++++++-
 gsk/gskrendernodeprivate.h           |    2 +
 6 files changed, 151 insertions(+), 118 deletions(-)
---
diff --git a/docs/reference/gsk/gsk4-sections.txt b/docs/reference/gsk/gsk4-sections.txt
index 4bbeba5..8e6239d 100644
--- a/docs/reference/gsk/gsk4-sections.txt
+++ b/docs/reference/gsk/gsk4-sections.txt
@@ -28,6 +28,7 @@ gsk_render_node_ref
 gsk_render_node_unref
 GskRenderNodeType
 gsk_render_node_get_node_type
+gsk_render_node_draw
 gsk_render_node_set_opacity
 GskBlendMode
 gsk_render_node_set_blend_mode
diff --git a/gsk/gskcairorenderer.c b/gsk/gskcairorenderer.c
index 4fd8592..3fb394a 100644
--- a/gsk/gskcairorenderer.c
+++ b/gsk/gskcairorenderer.c
@@ -47,121 +47,6 @@ gsk_cairo_renderer_unrealize (GskRenderer *renderer)
 }
 
 static void
-gsk_cairo_renderer_render_node (GskCairoRenderer *self,
-                                GskRenderNode    *node,
-                                cairo_t          *cr)
-{
-  gboolean pop_group = FALSE;
-  graphene_rect_t frame;
-
-  cairo_save (cr);
-
-  gsk_render_node_get_bounds (node, &frame);
-  GSK_NOTE (CAIRO, g_print ("CLIP = { .x = %g, .y = %g, .width = %g, .height = %g }\n",
-                            frame.origin.x, frame.origin.y,
-                            frame.size.width, frame.size.height));
-
-  if (!GSK_RENDER_MODE_CHECK (GEOMETRY))
-    {
-      cairo_rectangle (cr, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
-      cairo_clip (cr);
-    }
-
-  if (gsk_render_node_get_opacity (node) != 1.0)
-    {
-      GSK_NOTE (CAIRO, g_print ("Pushing opacity group (opacity:%g)\n",
-                                gsk_render_node_get_opacity (node)));
-      cairo_push_group (cr);
-      pop_group = TRUE;
-    }
-
-  GSK_NOTE (CAIRO, g_print ("Rendering node %s[%p] at %g, %g\n",
-                            node->name,
-                            node,
-                            frame.origin.x, frame.origin.y));
-
-  switch (gsk_render_node_get_node_type (node))
-    {
-    case GSK_NOT_A_RENDER_NODE:
-    default:
-      g_assert_not_reached ();
-      break;
-
-    case GSK_CONTAINER_NODE:
-      {
-        guint i;
-        GSK_NOTE (CAIRO, g_print ("Drawing %d children of node [%p]\n",
-                                  gsk_container_node_get_n_children (node),
-                                  node));
-        for (i = 0; i < gsk_container_node_get_n_children (node); i++)
-          {
-            gsk_cairo_renderer_render_node (self, gsk_container_node_get_child (node, i), cr);
-          }
-      }
-      break;
-
-    case GSK_TEXTURE_NODE:
-      {
-        GskTexture *texture = gsk_texture_node_get_texture (node);
-        cairo_surface_t *surface = gsk_texture_download (texture);
-
-        cairo_set_source_surface (cr, surface, frame.origin.x, frame.origin.y); 
-        cairo_paint (cr);
-        cairo_surface_destroy (surface);
-      }
-      break;
-
-    case GSK_CAIRO_NODE:
-      {
-        cairo_set_source_surface (cr, gsk_cairo_node_get_surface (node), frame.origin.x, frame.origin.y); 
-        cairo_paint (cr);
-      }
-      break;
-
-    case GSK_TRANSFORM_NODE:
-      {
-        graphene_matrix_t mat;
-        cairo_matrix_t ctm;
-
-        gsk_transform_node_get_transform (node, &mat);
-        if (graphene_matrix_to_2d (&mat, &ctm.xx, &ctm.yx, &ctm.xy, &ctm.yy, &ctm.x0, &ctm.y0))
-          {
-            GSK_NOTE (CAIRO, g_print ("CTM = { .xx = %g, .yx = %g, .xy = %g, .yy = %g, .x0 = %g, .y0 = %g 
}\n",
-                                      ctm.xx, ctm.yx,
-                                      ctm.xy, ctm.yy,
-                                      ctm.x0, ctm.y0));
-            cairo_transform (cr, &ctm);
-          }
-        else
-          g_critical ("Invalid non-affine transformation for node %p", node);
-
-        gsk_cairo_renderer_render_node (self, gsk_transform_node_get_child (node), cr);
-      }
-      break;
-    }
-
-  if (GSK_RENDER_MODE_CHECK (GEOMETRY))
-    {
-      cairo_save (cr);
-      cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
-      cairo_rectangle (cr, frame.origin.x - 1, frame.origin.y - 1, frame.size.width + 2, frame.size.height + 
2);
-      cairo_set_line_width (cr, 2);
-      cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
-      cairo_stroke (cr);
-      cairo_restore (cr);
-    }
-
-  if (pop_group)
-    {
-      cairo_pop_group_to_source (cr);
-      cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
-      cairo_paint_with_alpha (cr, gsk_render_node_get_opacity (node));
-    }
-
-  cairo_restore (cr);
-}
-
-static void
 gsk_cairo_renderer_render (GskRenderer   *renderer,
                            GskRenderNode *root)
 {
@@ -209,7 +94,7 @@ gsk_cairo_renderer_render (GskRenderer   *renderer,
   gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
 #endif
 
-  gsk_cairo_renderer_render_node (self, root, cr);
+  gsk_render_node_draw (root, cr);
 
 #ifdef G_ENABLE_DEBUG
   cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
diff --git a/gsk/gskrendernode.c b/gsk/gskrendernode.c
index 5b53c91..1a343ae 100644
--- a/gsk/gskrendernode.c
+++ b/gsk/gskrendernode.c
@@ -335,3 +335,62 @@ gsk_render_node_make_immutable (GskRenderNode *node)
   node->is_mutable = FALSE;
 }
 
+/**
+ * gsk_render_node_draw:
+ * @node: a #GskRenderNode
+ * @cr: cairo context to draw to
+ *
+ * Draw the contents of @node to the given cairo context.
+ *
+ * Typically, you'll use this function to implement fallback rendering
+ * of #GskRenderNodes on an intermediate Cairo context, instead of using
+ * the drawing context associated to a #GdkWindow's rendering buffer.
+ *
+ * For advanced nodes that cannot be supported using Cairo, in particular
+ * for nodes doing 3D operations, this function may fail.
+ **/
+void
+gsk_render_node_draw (GskRenderNode *node,
+                      cairo_t       *cr)
+{
+  g_return_if_fail (GSK_IS_RENDER_NODE (node));
+  g_return_if_fail (cr != NULL);
+
+  cairo_save (cr);
+
+  if (!GSK_RENDER_MODE_CHECK (GEOMETRY))
+    {
+      graphene_rect_t frame;
+
+      gsk_render_node_get_bounds (node, &frame);
+      GSK_NOTE (CAIRO, g_print ("CLIP = { .x = %g, .y = %g, .width = %g, .height = %g }\n",
+                                frame.origin.x, frame.origin.y,
+                                frame.size.width, frame.size.height));
+
+      cairo_rectangle (cr, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
+      cairo_clip (cr);
+    }
+
+  GSK_NOTE (CAIRO, g_print ("Rendering node %s[%p]\n",
+                            node->name,
+                            node));
+
+  node->node_class->draw (node, cr);
+
+  if (GSK_RENDER_MODE_CHECK (GEOMETRY))
+    {
+      graphene_rect_t frame;
+
+      gsk_render_node_get_bounds (node, &frame);
+
+      cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+      cairo_rectangle (cr, frame.origin.x - 1, frame.origin.y - 1, frame.size.width + 2, frame.size.height + 
2);
+      cairo_set_line_width (cr, 2);
+      cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
+      cairo_stroke (cr);
+    }
+
+  cairo_restore (cr);
+}
+
+
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index 93a100e..c874cb5 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -88,6 +88,9 @@ void                    gsk_render_node_set_name                (GskRenderNode *
 GDK_AVAILABLE_IN_3_90
 const char *            gsk_render_node_get_name                (GskRenderNode *node);
 
+GDK_AVAILABLE_IN_3_90
+void                    gsk_render_node_draw                    (GskRenderNode *node,
+                                                                 cairo_t       *cr);
 G_END_DECLS
 
 #endif /* __GSK_RENDER_NODE_H__ */
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index d23d18d..b80c0f6 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -20,7 +20,7 @@
 
 #include "gskdebugprivate.h"
 #include "gskrendererprivate.h"
-#include "gsktexture.h"
+#include "gsktextureprivate.h"
 
 /*** GSK_TEXTURE_NODE ***/
 
@@ -48,6 +48,30 @@ gsk_texture_node_make_immutable (GskRenderNode *node)
 }
 
 static void
+gsk_texture_node_draw (GskRenderNode *node,
+                       cairo_t       *cr)
+{
+  GskTextureNode *self = (GskTextureNode *) node;
+  cairo_surface_t *surface;
+
+  surface = gsk_texture_download (self->texture);
+
+  cairo_save (cr);
+
+  cairo_translate (cr, self->bounds.origin.x, self->bounds.origin.y);
+  cairo_scale (cr,
+               self->bounds.size.width / gsk_texture_get_width (self->texture),
+               self->bounds.size.height / gsk_texture_get_height (self->texture));
+
+  cairo_set_source_surface (cr, surface, 0, 0);
+  cairo_paint (cr);
+
+  cairo_restore (cr);
+
+  cairo_surface_destroy (surface);
+}
+
+static void
 gsk_texture_node_get_bounds (GskRenderNode   *node,
                              graphene_rect_t *bounds)
 {
@@ -62,6 +86,7 @@ static const GskRenderNodeClass GSK_TEXTURE_NODE_CLASS = {
   "GskTextureNode",
   gsk_texture_node_finalize,
   gsk_texture_node_make_immutable,
+  gsk_texture_node_draw,
   gsk_texture_node_get_bounds
 };
 
@@ -131,6 +156,19 @@ gsk_cairo_node_make_immutable (GskRenderNode *node)
 }
 
 static void
+gsk_cairo_node_draw (GskRenderNode *node,
+                     cairo_t       *cr)
+{
+  GskCairoNode *self = (GskCairoNode *) node;
+
+  if (self->surface == NULL)
+    return;
+
+  cairo_set_source_surface (cr, self->surface, self->bounds.origin.x, self->bounds.origin.y);
+  cairo_paint (cr);
+}
+
+static void
 gsk_cairo_node_get_bounds (GskRenderNode   *node,
                            graphene_rect_t *bounds)
 {
@@ -145,6 +183,7 @@ static const GskRenderNodeClass GSK_CAIRO_NODE_CLASS = {
   "GskCairoNode",
   gsk_cairo_node_finalize,
   gsk_cairo_node_make_immutable,
+  gsk_cairo_node_draw,
   gsk_cairo_node_get_bounds
 };
 
@@ -314,6 +353,19 @@ gsk_container_node_make_immutable (GskRenderNode *node)
 }
 
 static void
+gsk_container_node_draw (GskRenderNode *node,
+                         cairo_t       *cr)
+{
+  GskContainerNode *container = (GskContainerNode *) node;
+  guint i;
+
+  for (i = 0; i < container->n_children; i++)
+    {
+      gsk_render_node_draw (container->children[i], cr);
+    }
+}
+
+static void
 gsk_container_node_get_bounds (GskRenderNode   *node,
                                graphene_rect_t *bounds)
 {
@@ -343,6 +395,7 @@ static const GskRenderNodeClass GSK_CONTAINER_NODE_CLASS = {
   "GskContainerNode",
   gsk_container_node_finalize,
   gsk_container_node_make_immutable,
+  gsk_container_node_draw,
   gsk_container_node_get_bounds
 };
 
@@ -437,8 +490,37 @@ gsk_transform_node_make_immutable (GskRenderNode *node)
 }
 
 static void
+gsk_transform_node_draw (GskRenderNode *node,
+                         cairo_t       *cr)
+{
+  GskTransformNode *self = (GskTransformNode *) node;
+  cairo_matrix_t ctm;
+
+  if (graphene_matrix_to_2d (&self->transform, &ctm.xx, &ctm.yx, &ctm.xy, &ctm.yy, &ctm.x0, &ctm.y0))
+    {
+      GSK_NOTE (CAIRO, g_print ("CTM = { .xx = %g, .yx = %g, .xy = %g, .yy = %g, .x0 = %g, .y0 = %g }\n",
+                                ctm.xx, ctm.yx,
+                                ctm.xy, ctm.yy,
+                                ctm.x0, ctm.y0));
+      cairo_transform (cr, &ctm);
+  
+      gsk_render_node_draw (self->child, cr);
+    }
+  else
+    {
+      graphene_rect_t bounds;
+
+      gsk_render_node_get_bounds (node, &bounds);
+
+      cairo_set_source_rgb (cr, 255 / 255., 105 / 255., 180 / 255.);
+      cairo_rectangle (cr, bounds.origin.x, bounds.origin.x, bounds.size.width, bounds.size.height);
+      cairo_fill (cr);
+    }
+}
+
+static void
 gsk_transform_node_get_bounds (GskRenderNode   *node,
-                           graphene_rect_t *bounds)
+                               graphene_rect_t *bounds)
 {
   GskTransformNode *self = (GskTransformNode *) node;
   graphene_rect_t child_bounds;
@@ -456,6 +538,7 @@ static const GskRenderNodeClass GSK_TRANSFORM_NODE_CLASS = {
   "GskTransformNode",
   gsk_transform_node_finalize,
   gsk_transform_node_make_immutable,
+  gsk_transform_node_draw,
   gsk_transform_node_get_bounds
 };
 
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index 85117f4..239e64d 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.h
@@ -40,6 +40,8 @@ struct _GskRenderNodeClass
   const char *type_name;
   void (* finalize) (GskRenderNode *node);
   void (* make_immutable) (GskRenderNode *node);
+  void (* draw) (GskRenderNode *node,
+                 cairo_t       *cr);
   void (* get_bounds) (GskRenderNode   *node,
                        graphene_rect_t *bounds);
 };


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