[gtk+/wip/otte/rendernode: 34/100] gsk: Add gsk_render_node_draw()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/rendernode: 34/100] gsk: Add gsk_render_node_draw()
- Date: Sun, 18 Dec 2016 06:31:33 +0000 (UTC)
commit aa6d975fcfd7d4db61906853d81d7a0b8b75192f
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]