summaryrefslogtreecommitdiff
path: root/gsk
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2020-04-07 23:33:54 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2020-04-08 15:40:15 +0100
commitd701a892815453dd38e19062761443eeda54a7c5 (patch)
treecc1d91b6e88ad16d97f9204817ad7b650c66150b /gsk
parent5e095cd208db14625a549a766f60c752c066da7b (diff)
downloadgtk+-d701a892815453dd38e19062761443eeda54a7c5.tar.gz
Turn GskRenderNode into a derivable type
Language bindings—especially ones based on introspection—cannot deal with custom type hiearchies. Luckily for us, GType has a derivable type with low overhead: GTypeInstance. By turning GskRenderNode into a GTypeInstance, and creating derived types for each class of node, we can provide an introspectable API to our non-C API consumers, with no functional change to the C API itself.
Diffstat (limited to 'gsk')
-rw-r--r--gsk/broadway/gskbroadwayrenderer.c2
-rw-r--r--gsk/gl/gskglnodesample.c2
-rw-r--r--gsk/gl/gskglrenderer.c47
-rw-r--r--gsk/gskenums.h4
-rw-r--r--gsk/gskrendernode.c316
-rw-r--r--gsk/gskrendernode.h55
-rw-r--r--gsk/gskrendernodeimpl.c1630
-rw-r--r--gsk/gskrendernodeparser.c10
-rw-r--r--gsk/gskrendernodeprivate.h74
-rw-r--r--gsk/vulkan/gskvulkanrenderpass.c12
10 files changed, 1525 insertions, 627 deletions
diff --git a/gsk/broadway/gskbroadwayrenderer.c b/gsk/broadway/gskbroadwayrenderer.c
index cb46f92bc2..89def7e807 100644
--- a/gsk/broadway/gskbroadwayrenderer.c
+++ b/gsk/broadway/gskbroadwayrenderer.c
@@ -595,7 +595,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
n = gsk_linear_gradient_node_get_n_color_stops (node);
add_uint32 (nodes, n);
for (i = 0; i < n; i++)
- add_color_stop (nodes, &gsk_linear_gradient_node_peek_color_stops (node)[i]);
+ add_color_stop (nodes, &gsk_linear_gradient_node_peek_color_stops (node, NULL)[i]);
}
return;
diff --git a/gsk/gl/gskglnodesample.c b/gsk/gl/gskglnodesample.c
index 1ee64c7790..cf1afa5a68 100644
--- a/gsk/gl/gskglnodesample.c
+++ b/gsk/gl/gskglnodesample.c
@@ -25,7 +25,7 @@ node_sample_add (NodeSample *self,
g_assert (node_type <= N_NODE_TYPES);
if (self->nodes[node_type].class_name == NULL)
- self->nodes[node_type].class_name = node->node_class->type_name;
+ self->nodes[node_type].class_name = g_type_name_from_instance ((GTypeInstance *) node);
self->nodes[node_type].count ++;
self->count ++;
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index f98527fb98..a706f0c18e 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -150,7 +150,7 @@ print_render_node_tree (GskRenderNode *root, int level)
break;
default:
- g_print ("%*s %s\n", level * INDENT, " ", root->node_class->type_name);
+ g_print ("%*s %s\n", level * INDENT, " ", g_type_name_from_instance ((GTypeInstance *) root));
}
#undef INDENT
@@ -623,7 +623,9 @@ render_fallback_node (GskGLRenderer *self,
surface,
GL_NEAREST, GL_NEAREST);
gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, texture_id,
- "Fallback %s %d", node->node_class->type_name, texture_id);
+ "Fallback %s %d",
+ g_type_name_from_instance ((GTypeInstance *) node),
+ texture_id);
cairo_surface_destroy (surface);
cairo_surface_destroy (rendered_surface);
@@ -643,7 +645,7 @@ render_text_node (GskGLRenderer *self,
gboolean force_color)
{
const PangoFont *font = gsk_text_node_peek_font (node);
- const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node);
+ const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node, NULL);
const float text_scale = ops_get_scale (builder);
const graphene_point_t *offset = gsk_text_node_get_offset (node);
const guint num_glyphs = gsk_text_node_get_num_glyphs (node);
@@ -1106,7 +1108,7 @@ render_linear_gradient_node (GskGLRenderer *self,
RenderOpBuilder *builder)
{
const int n_color_stops = MIN (8, gsk_linear_gradient_node_get_n_color_stops (node));
- const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node);
+ const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node, NULL);
const graphene_point_t *start = gsk_linear_gradient_node_peek_start (node);
const graphene_point_t *end = gsk_linear_gradient_node_peek_end (node);
OpLinearGradient *op;
@@ -3159,9 +3161,13 @@ add_offscreen_ops (GskGLRenderer *self,
gsk_gl_driver_create_render_target (self->gl_driver, width, height, &texture_id, &render_target);
gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, texture_id,
- "Offscreen<%s> %d", child_node->node_class->type_name, texture_id);
- gdk_gl_context_label_object_printf (self->gl_context, GL_FRAMEBUFFER, render_target,
- "Offscreen<%s> FB %d", child_node->node_class->type_name, render_target);
+ "Offscreen<%s> %d",
+ g_type_name_from_instance ((GTypeInstance *) child_node),
+ texture_id);
+ gdk_gl_context_label_object_printf (self->gl_context, GL_FRAMEBUFFER, render_target,
+ "Offscreen<%s> FB %d",
+ g_type_name_from_instance ((GTypeInstance *) child_node),
+ render_target);
graphene_matrix_init_ortho (&item_proj,
bounds->origin.x * scale,
@@ -3209,10 +3215,11 @@ add_offscreen_ops (GskGLRenderer *self,
if (G_UNLIKELY (flags & DUMP_FRAMEBUFFER))
{
static int k;
- ops_dump_framebuffer (builder, g_strdup_printf ("%s_%p_%d.png",
- child_node->node_class->type_name,
- child_node,
- k ++),
+ ops_dump_framebuffer (builder,
+ g_strdup_printf ("%s_%p_%d.png",
+ g_type_name_from_instance ((GTypeInstance *) child_node),
+ child_node,
+ k ++),
width, height);
}
#endif
@@ -3583,7 +3590,9 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
gdk_gl_context_make_current (self->gl_context);
gdk_gl_context_push_debug_group_printf (self->gl_context,
- "Render %s<%p> to texture", root->node_class->type_name, root);
+ "Render %s<%p> to texture",
+ g_type_name_from_instance ((GTypeInstance *) root),
+ root);
width = ceilf (viewport->size.width);
height = ceilf (viewport->size.height);
@@ -3595,8 +3604,11 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
glGenTextures (1, &texture_id);
glBindTexture (GL_TEXTURE_2D, texture_id);
- gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, texture_id,
- "Texture %s<%p> %d", root->node_class->type_name, root, texture_id);
+ gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, texture_id,
+ "Texture %s<%p> %d",
+ g_type_name_from_instance ((GTypeInstance *) root),
+ root,
+ texture_id);
if (gdk_gl_context_get_use_es (self->gl_context))
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
@@ -3605,8 +3617,11 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
glGenFramebuffers (1, &fbo_id);
glBindFramebuffer (GL_FRAMEBUFFER, fbo_id);
- gdk_gl_context_label_object_printf (self->gl_context, GL_FRAMEBUFFER, fbo_id,
- "FB %s<%p> %d", root->node_class->type_name, root, fbo_id);
+ gdk_gl_context_label_object_printf (self->gl_context, GL_FRAMEBUFFER, fbo_id,
+ "FB %s<%p> %d",
+ g_type_name_from_instance ((GTypeInstance *) root),
+ root,
+ fbo_id);
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0);
g_assert_cmphex (glCheckFramebufferStatus (GL_FRAMEBUFFER), ==, GL_FRAMEBUFFER_COMPLETE);
diff --git a/gsk/gskenums.h b/gsk/gskenums.h
index 1851918bd1..d5fcb8ec55 100644
--- a/gsk/gskenums.h
+++ b/gsk/gskenums.h
@@ -46,9 +46,9 @@
* @GSK_TEXT_NODE: A node containing a glyph string
* @GSK_BLUR_NODE: A node that applies a blur
* @GSK_DEBUG_NODE: Debug information that does not affect the rendering
- *
+
* The type of a node determines what the node is rendering.
- **/
+ */
typedef enum {
GSK_NOT_A_RENDER_NODE = 0,
GSK_CONTAINER_NODE,
diff --git a/gsk/gskrendernode.c b/gsk/gskrendernode.c
index fb80a7c3a0..2a614fd9ca 100644
--- a/gsk/gskrendernode.c
+++ b/gsk/gskrendernode.c
@@ -50,47 +50,297 @@
#include <gobject/gvaluecollector.h>
+G_DEFINE_QUARK (gsk-serialization-error-quark, gsk_serialization_error)
+
+#define GSK_RENDER_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_RENDER_NODE, GskRenderNodeClass))
+
/**
* GskRenderNode: (ref-func gsk_render_node_ref) (unref-func gsk_render_node_unref)
*
- * The `GskRenderNode` structure contains only private data.
+ * A node in the render tree.
*/
-G_DEFINE_BOXED_TYPE (GskRenderNode, gsk_render_node,
- gsk_render_node_ref,
- gsk_render_node_unref)
+static void
+value_render_node_init (GValue *value)
+{
+ value->data[0].v_pointer = NULL;
+}
+
+static void
+value_render_node_free_value (GValue *value)
+{
+ if (value->data[0].v_pointer != NULL)
+ gsk_render_node_unref (value->data[0].v_pointer);
+}
+
+static void
+value_render_node_copy_value (const GValue *src,
+ GValue *dst)
+{
+ if (src->data[0].v_pointer != NULL)
+ dst->data[0].v_pointer = gsk_render_node_ref (src->data[0].v_pointer);
+ else
+ dst->data[0].v_pointer = NULL;
+}
+
+static gpointer
+value_render_node_peek_pointer (const GValue *value)
+{
+ return value->data[0].v_pointer;
+}
-G_DEFINE_QUARK (gsk-serialization-error-quark, gsk_serialization_error)
+static char *
+value_render_node_collect_value (GValue *value,
+ guint n_collect_values,
+ GTypeCValue *collect_values,
+ guint collect_flags)
+{
+ GskRenderNode *node = collect_values[0].v_pointer;
+
+ if (node == NULL)
+ {
+ value->data[0].v_pointer = NULL;
+ return NULL;
+ }
+
+ if (node->parent_instance.g_class == NULL)
+ return g_strconcat ("invalid unclassed GskRenderNode pointer for "
+ "value type '",
+ G_VALUE_TYPE_NAME (value),
+ "'",
+ NULL);
+
+ value->data[0].v_pointer = gsk_render_node_ref (node);
+
+ return NULL;
+}
+
+static gchar *
+value_render_node_lcopy_value (const GValue *value,
+ guint n_collect_values,
+ GTypeCValue *collect_values,
+ guint collect_flags)
+{
+ GskRenderNode **node_p = collect_values[0].v_pointer;
+
+ if (node_p == NULL)
+ return g_strconcat ("value location for '",
+ G_VALUE_TYPE_NAME (value),
+ "' passed as NULL",
+ NULL);
+
+ if (value->data[0].v_pointer == NULL)
+ *node_p = NULL;
+ else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+ *node_p = value->data[0].v_pointer;
+ else
+ *node_p = gsk_render_node_ref (value->data[0].v_pointer);
+
+ return NULL;
+}
static void
gsk_render_node_finalize (GskRenderNode *self)
{
- self->node_class->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+}
- g_free (self);
+static void
+gsk_render_node_real_draw (GskRenderNode *node,
+ cairo_t *cr)
+{
}
-/*< private >
- * gsk_render_node_new:
- * @node_class: class structure for this node
- *
- * Returns: (transfer full): the newly created #GskRenderNode
- */
-GskRenderNode *
-gsk_render_node_new (const GskRenderNodeClass *node_class, gsize extra_size)
+static gboolean
+gsk_render_node_real_can_diff (const GskRenderNode *node1,
+ const GskRenderNode *node2)
+{
+ return FALSE;
+}
+
+static void
+gsk_render_node_real_diff (GskRenderNode *node1,
+ GskRenderNode *node2,
+ cairo_region_t *region)
+{
+}
+
+static void
+gsk_render_node_class_init (GskRenderNodeClass *klass)
+{
+ klass->node_type = GSK_NOT_A_RENDER_NODE;
+ klass->finalize = gsk_render_node_finalize;
+ klass->draw = gsk_render_node_real_draw;
+ klass->can_diff = gsk_render_node_real_can_diff;
+ klass->diff = gsk_render_node_real_diff;
+}
+
+static void
+gsk_render_node_init (GskRenderNode *self)
+{
+ g_atomic_ref_count_init (&self->ref_count);
+}
+
+GType
+gsk_render_node_get_type (void)
+{
+ static volatile gsize render_node_type__volatile;
+
+ if (g_once_init_enter (&render_node_type__volatile))
+ {
+ static const GTypeFundamentalInfo finfo = {
+ (G_TYPE_FLAG_CLASSED |
+ G_TYPE_FLAG_INSTANTIATABLE |
+ G_TYPE_FLAG_DERIVABLE |
+ G_TYPE_FLAG_DEEP_DERIVABLE),
+ };
+
+ static const GTypeValueTable value_table = {
+ value_render_node_init,
+ value_render_node_free_value,
+ value_render_node_copy_value,
+ value_render_node_peek_pointer,
+ "p",
+ value_render_node_collect_value,
+ "p",
+ value_render_node_lcopy_value,
+ };
+
+ const GTypeInfo node_info = {
+ /* Class */
+ sizeof (GskRenderNodeClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gsk_render_node_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+
+ /* Instance */
+ sizeof (GskRenderNode),
+ 0,
+ (GInstanceInitFunc) gsk_render_node_init,
+
+ /* GValue */
+ &value_table,
+ };
+
+ GType render_node_type =
+ g_type_register_fundamental (g_type_fundamental_next (),
+ g_intern_static_string ("GskRenderNode"),
+ &node_info, &finfo,
+ G_TYPE_FLAG_ABSTRACT);
+
+ g_once_init_leave (&render_node_type__volatile, render_node_type);
+ }
+
+ return render_node_type__volatile;
+}
+
+typedef struct
+{
+ GskRenderNodeType node_type;
+
+ void (* finalize) (GskRenderNode *node);
+ void (* draw) (GskRenderNode *node,
+ cairo_t *cr);
+ gboolean (* can_diff) (const GskRenderNode *node1,
+ const GskRenderNode *node2);
+ void (* diff) (GskRenderNode *node1,
+ GskRenderNode *node2,
+ cairo_region_t *region);
+} RenderNodeClassData;
+
+static void
+gsk_render_node_generic_class_init (gpointer g_class,
+ gpointer class_data)
{
- GskRenderNode *self;
+ GskRenderNodeClass *node_class = g_class;
+ RenderNodeClassData *node_data = class_data;
+
+ /* Mandatory */
+ node_class->node_type = node_data->node_type;
- g_return_val_if_fail (node_class != NULL, NULL);
- g_return_val_if_fail (node_class->node_type != GSK_NOT_A_RENDER_NODE, NULL);
+ /* Optional */
+ if (node_data->finalize != NULL)
+ node_class->finalize = node_data->finalize;
+ if (node_data->can_diff != NULL)
+ node_class->can_diff = node_data->can_diff;
- self = g_malloc0 (node_class->struct_size + extra_size);
+ /* Mandatory */
+ node_class->draw = node_data->draw;
+ node_class->diff = node_data->diff;
- self->node_class = node_class;
+ g_free (node_data);
+}
- self->ref_count = 1;
+static gboolean
+gsk_render_node_can_diff_true (const GskRenderNode *node1,
+ const GskRenderNode *node2)
+{
+ return TRUE;
+}
- return self;
+/*< private >
+ * gsk_render_node_type_register_static:
+ * @node_name: the name of the node
+ * @node_info: type information of the node
+ *
+ * Registers a new #GskRenderNode type for the given @node_name using
+ * the type information in @node_info.
+ *
+ * Returns: the newly registered GType
+ */
+GType
+gsk_render_node_type_register_static (const char *node_name,
+ const GskRenderNodeTypeInfo *node_info)
+{
+ GTypeInfo info;
+
+ info.class_size = sizeof (GskRenderNodeClass);
+ info.base_init = NULL;
+ info.base_finalize = NULL;
+ info.class_init = gsk_render_node_generic_class_init;
+ info.class_finalize = NULL;
+
+ /* Avoid having a class_init() and a class struct for every GskRenderNode,
+ * by passing the various virtual functions and class data when initializing
+ * the base class
+ */
+ info.class_data = g_new (RenderNodeClassData, 1);
+ ((RenderNodeClassData *) info.class_data)->node_type = node_info->node_type;
+ ((RenderNodeClassData *) info.class_data)->finalize = node_info->finalize;
+ ((RenderNodeClassData *) info.class_data)->draw = node_info->draw;
+ ((RenderNodeClassData *) info.class_data)->can_diff = node_info->can_diff != NULL
+ ? node_info->can_diff
+ : gsk_render_node_can_diff_true;
+ ((RenderNodeClassData *) info.class_data)->diff = node_info->diff != NULL
+ ? node_info->diff
+ : gsk_render_node_diff_impossible;
+
+ info.instance_size = node_info->instance_size;
+ info.n_preallocs = 0;
+ info.instance_init = (GInstanceInitFunc) node_info->instance_init;
+ info.value_table = NULL;
+
+ return g_type_register_static (GSK_TYPE_RENDER_NODE, node_name, &info, 0);
+}
+
+/*< private >
+ * gsk_render_node_alloc:
+ * @node_type: the #GskRenderNodeType to instantiate
+ *
+ * Instantiates a new #GskRenderNode for the given @node_type.
+ *
+ * Returns: (transfer full) (type GskRenderNode): the newly created #GskRenderNode
+ */
+gpointer
+gsk_render_node_alloc (GskRenderNodeType node_type)
+{
+ g_return_val_if_fail (node_type > GSK_NOT_A_RENDER_NODE, NULL);
+ g_return_val_if_fail (node_type < GSK_RENDER_NODE_TYPE_N_TYPES, NULL);
+
+ g_assert (gsk_render_node_types[node_type] != G_TYPE_INVALID);
+ return g_type_create_instance (gsk_render_node_types[node_type]);
}
/**
@@ -106,7 +356,7 @@ gsk_render_node_ref (GskRenderNode *node)
{
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
- g_atomic_int_inc (&node->ref_count);
+ g_atomic_ref_count_inc (&node->ref_count);
return node;
}
@@ -125,10 +375,11 @@ gsk_render_node_unref (GskRenderNode *node)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
- if (g_atomic_int_dec_and_test (&node->ref_count))
- gsk_render_node_finalize (node);
+ if (g_atomic_ref_count_dec (&node->ref_count))
+ GSK_RENDER_NODE_GET_CLASS (node)->finalize (node);
}
+
/**
* gsk_render_node_get_node_type:
* @node: a #GskRenderNode
@@ -142,14 +393,14 @@ gsk_render_node_get_node_type (GskRenderNode *node)
{
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), GSK_NOT_A_RENDER_NODE);
- return node->node_class->node_type;
+ return GSK_RENDER_NODE_GET_CLASS (node)->node_type;
}
G_GNUC_PURE static inline
GskRenderNodeType
_gsk_render_node_get_node_type (const GskRenderNode *node)
{
- return node->node_class->node_type;
+ return GSK_RENDER_NODE_GET_CLASS (node)->node_type;
}
/**
@@ -195,9 +446,10 @@ gsk_render_node_draw (GskRenderNode *node,
cairo_save (cr);
GSK_NOTE (CAIRO, g_message ("Rendering node %s[%p]",
- node->node_class->type_name, node));
+ g_type_name_from_instance ((GTypeInstance *) node),
+ node));
- node->node_class->draw (node, cr);
+ GSK_RENDER_NODE_GET_CLASS (node)->draw (node, cr);
#ifdef G_ENABLE_DEBUG
if (GSK_DEBUG_CHECK (GEOMETRY))
@@ -216,7 +468,7 @@ gsk_render_node_draw (GskRenderNode *node,
if (cairo_status (cr))
{
g_warning ("drawing failure for render node %s: %s",
- node->node_class->type_name,
+ g_type_name_from_instance ((GTypeInstance *) node),
cairo_status_to_string (cairo_status (cr)));
}
}
@@ -245,7 +497,7 @@ gsk_render_node_can_diff (const GskRenderNode *node1,
if (_gsk_render_node_get_node_type (node1) != _gsk_render_node_get_node_type (node2))
return FALSE;
- return node1->node_class->can_diff (node1, node2);
+ return GSK_RENDER_NODE_GET_CLASS (node1)->can_diff (node1, node2);
}
static void
@@ -299,7 +551,7 @@ gsk_render_node_diff (GskRenderNode *node1,
if (_gsk_render_node_get_node_type (node1) != _gsk_render_node_get_node_type (node2))
return gsk_render_node_diff_impossible (node1, node2, region);
- return node1->node_class->diff (node1, node2, region);
+ return GSK_RENDER_NODE_GET_CLASS (node1)->diff (node1, node2, region);
}
/**
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index 17a0549d36..7cc7b90b62 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -99,6 +99,53 @@ GskRenderNode * gsk_render_node_deserialize (GBytes
GskParseErrorFunc error_func,
gpointer user_data);
+#define GSK_TYPE_DEBUG_NODE (gsk_render_node_types[GSK_DEBUG_NODE])
+#define GSK_TYPE_COLOR_NODE (gsk_render_node_types[GSK_COLOR_NODE])
+#define GSK_TYPE_TEXTURE_NODE (gsk_render_node_types[GSK_TEXTURE_NODE])
+#define GSK_TYPE_LINEAR_GRADIENT_NODE (gsk_render_node_types[GSK_LINEAR_GRADIENT_NODE])
+#define GSK_TYPE_REPEATING_LINEAR_GRADIENT_NODE (gsk_render_node_types[GSK_REPEATING_LINEAR_GRADIENT_NODE])
+#define GSK_TYPE_BORDER_NODE (gsk_render_node_types[GSK_BORDER_NODE])
+#define GSK_TYPE_INSET_SHADOW_NODE (gsk_render_node_types[GSK_INSET_SHADOW_NODE])
+#define GSK_TYPE_OUTSET_SHADOW_NODE (gsk_render_node_types[GSK_OUTSET_SHADOW_NODE])
+#define GSK_TYPE_CAIRO_NODE (gsk_render_node_types[GSK_CAIRO_NODE])
+#define GSK_TYPE_CONTAINER_NODE (gsk_render_node_types[GSK_CONTAINER_NODE])
+#define GSK_TYPE_TRANSFORM_NODE (gsk_render_node_types[GSK_TRANSFORM_NODE])
+#define GSK_TYPE_OPACITY_NODE (gsk_render_node_types[GSK_OPACITY_NODE])
+#define GSK_TYPE_COLOR_MATRIX_NODE (gsk_render_node_types[GSK_COLOR_MATRIX_NODE])
+#define GSK_TYPE_REPEAT_NODE (gsk_render_node_types[GSK_REPEAT_NODE])
+#define GSK_TYPE_CLIP_NODE (gsk_render_node_types[GSK_CLIP_NODE])
+#define GSK_TYPE_ROUNDED_CLIP_NODE (gsk_render_node_types[GSK_ROUNDED_CLIP_NODE])
+#define GSK_TYPE_SHADOW_NODE (gsk_render_node_types[GSK_SHADOW_NODE])
+#define GSK_TYPE_BLEND_NODE (gsk_render_node_types[GSK_BLEND_NODE])
+#define GSK_TYPE_CROSS_FADE_NODE (gsk_render_node_types[GSK_CROSS_FADE_NODE])
+#define GSK_TYPE_TEXT_NODE (gsk_render_node_types[GSK_TEXT_NODE])
+#define GSK_TYPE_BLUR_NODE (gsk_render_node_types[GSK_BLUR_NODE])
+
+/*< private >*/
+GDK_EXTERN_VAR GType gsk_render_node_types[];
+
+typedef struct _GskDebugNode GskDebugNode;
+typedef struct _GskColorNode GskColorNode;
+typedef struct _GskTextureNode GskTextureNode;
+typedef struct _GskLinearGradientNode GskLinearGradientNode;
+typedef struct _GskRepeatingLinearGradientNode GskRepeatingLinearGradientNode;
+typedef struct _GskBorderNode GskBorderNode;
+typedef struct _GskInsetShadowNode GskInsetShadowNode;
+typedef struct _GskOutsetShadowNode GskOutsetShadowNode;
+typedef struct _GskCairoNode GskCairoNode;
+typedef struct _GskContainerNode GskContainerNode;
+typedef struct _GskTransformNode GskTransformNode;
+typedef struct _GskOpacityNode GskOpacityNode;
+typedef struct _GskColorMatrixNode GskColorMatrixNode;
+typedef struct _GskRepeatNode GskRepeatNode;
+typedef struct _GskClipNode GskClipNode;
+typedef struct _GskRoundedClipNode GskRoundedClipNode;
+typedef struct _GskShadowNode GskShadowNode;
+typedef struct _GskBlendNode GskBlendNode;
+typedef struct _GskCrossFadeNode GskCrossFadeNode;
+typedef struct _GskTextNode GskTextNode;
+typedef struct _GskBlurNode GskBlurNode;
+
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_debug_node_new (GskRenderNode *child,
char *message);
@@ -132,7 +179,8 @@ const graphene_point_t * gsk_linear_gradient_node_peek_end (GskRenderNo
GDK_AVAILABLE_IN_ALL
gsize gsk_linear_gradient_node_get_n_color_stops (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
-const GskColorStop * gsk_linear_gradient_node_peek_color_stops (GskRenderNode *node);
+const GskColorStop * gsk_linear_gradient_node_peek_color_stops (GskRenderNode *node,
+ gsize *n_stops);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_repeating_linear_gradient_node_new (const graphene_rect_t *bounds,
@@ -152,7 +200,6 @@ const float * gsk_border_node_peek_widths (GskRenderNode
GDK_AVAILABLE_IN_ALL
const GdkRGBA * gsk_border_node_peek_colors (GskRenderNode *node);
-
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_inset_shadow_node_new (const GskRoundedRect *outline,
const GdkRGBA *color,
@@ -254,7 +301,6 @@ GskRenderNode * gsk_clip_node_get_child (GskRenderNode
GDK_AVAILABLE_IN_ALL
const graphene_rect_t * gsk_clip_node_peek_clip (GskRenderNode *node);
-
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_rounded_clip_node_new (GskRenderNode *child,
const GskRoundedRect *clip);
@@ -308,7 +354,8 @@ gboolean gsk_text_node_has_color_glyphs (GskRenderNode
GDK_AVAILABLE_IN_ALL
guint gsk_text_node_get_num_glyphs (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
-const PangoGlyphInfo *gsk_text_node_peek_glyphs (GskRenderNode *node);
+const PangoGlyphInfo *gsk_text_node_peek_glyphs (GskRenderNode *node,
+ guint *n_glyphs);
GDK_AVAILABLE_IN_ALL
const GdkRGBA * gsk_text_node_peek_color (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index aad1fa59ef..48219c5758 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -30,6 +30,8 @@
#include "gdk/gdktextureprivate.h"
#include <cairo-ft.h>
+GType gsk_render_node_types[GSK_RENDER_NODE_TYPE_N_TYPES];
+
static inline void
gsk_cairo_rectangle (cairo_t *cr,
const graphene_rect_t *rect)
@@ -49,17 +51,8 @@ rectangle_init_from_graphene (cairo_rectangle_int_t *cairo,
cairo->height = ceilf (graphene->origin.y + graphene->size.height) - cairo->y;
}
-static gboolean
-gsk_render_node_can_diff_true (const GskRenderNode *node1,
- const GskRenderNode *node2)
-{
- return TRUE;
-}
-
/*** GSK_COLOR_NODE ***/
-typedef struct _GskColorNode GskColorNode;
-
struct _GskColorNode
{
GskRenderNode render_node;
@@ -68,11 +61,6 @@ struct _GskColorNode
};
static void
-gsk_color_node_finalize (GskRenderNode *node)
-{
-}
-
-static void
gsk_color_node_draw (GskRenderNode *node,
cairo_t *cr)
{
@@ -99,55 +87,55 @@ gsk_color_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
-static const GskRenderNodeClass GSK_COLOR_NODE_CLASS = {
- GSK_COLOR_NODE,
- sizeof (GskColorNode),
- "GskColorNode",
- gsk_color_node_finalize,
- gsk_color_node_draw,
- gsk_render_node_can_diff_true,
- gsk_color_node_diff,
-};
-
+/**
+ * gsk_color_node_peek_color:
+ * @node: (type GskColorNode): a #GskColorNode
+ *
+ * Retrieves the color of the given @node.
+ *
+ * Returns: (transfer none): the color of the node
+ */
const GdkRGBA *
gsk_color_node_peek_color (GskRenderNode *node)
{
GskColorNode *self = (GskColorNode *) node;
+ g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_COLOR_NODE), NULL);
+
return &self->color;
}
/**
- * gsk_color_node_new:
+ * gsk_color_node_new:
* @rgba: a #GdkRGBA specifying a color
* @bounds: the rectangle to render the color into
*
* Creates a #GskRenderNode that will render the color specified by @rgba into
* the area given by @bounds.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_color_node_new (const GdkRGBA *rgba,
const graphene_rect_t *bounds)
{
GskColorNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (rgba != NULL, NULL);
g_return_val_if_fail (bounds != NULL, NULL);
- self = (GskColorNode *) gsk_render_node_new (&GSK_COLOR_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_COLOR_NODE);
+ node = (GskRenderNode *) self;
self->color = *rgba;
- graphene_rect_init_from_rect (&self->render_node.bounds, bounds);
+ graphene_rect_init_from_rect (&node->bounds, bounds);
- return &self->render_node;
+ return node;
}
/*** GSK_LINEAR_GRADIENT_NODE ***/
-typedef struct _GskLinearGradientNode GskLinearGradientNode;
-
struct _GskLinearGradientNode
{
GskRenderNode render_node;
@@ -156,12 +144,18 @@ struct _GskLinearGradientNode
graphene_point_t end;
gsize n_stops;
- GskColorStop stops[];
+ GskColorStop *stops;
};
static void
gsk_linear_gradient_node_finalize (GskRenderNode *node)
{
+ GskLinearGradientNode *self = (GskLinearGradientNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_LINEAR_GRADIENT_NODE));
+
+ g_free (self->stops);
+
+ parent_class->finalize (node);
}
static void
@@ -228,26 +222,6 @@ gsk_linear_gradient_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
-static const GskRenderNodeClass GSK_LINEAR_GRADIENT_NODE_CLASS = {
- GSK_LINEAR_GRADIENT_NODE,
- sizeof (GskLinearGradientNode),
- "GskLinearGradientNode",
- gsk_linear_gradient_node_finalize,
- gsk_linear_gradient_node_draw,
- gsk_render_node_can_diff_true,
- gsk_linear_gradient_node_diff,
-};
-
-static const GskRenderNodeClass GSK_REPEATING_LINEAR_GRADIENT_NODE_CLASS = {
- GSK_REPEATING_LINEAR_GRADIENT_NODE,
- sizeof (GskLinearGradientNode),
- "GskRepeatingLinearGradientNode",
- gsk_linear_gradient_node_finalize,
- gsk_linear_gradient_node_draw,
- gsk_render_node_can_diff_true,
- gsk_linear_gradient_node_diff,
-};
-
/**
* gsk_linear_gradient_node_new:
* @bounds: the rectangle to render the linear gradient into
@@ -259,7 +233,7 @@ static const GskRenderNodeClass GSK_REPEATING_LINEAR_GRADIENT_NODE_CLASS = {
* Creates a #GskRenderNode that will create a linear gradient from the given
* points and color stops, and render that into the area given by @bounds.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_linear_gradient_node_new (const graphene_rect_t *bounds,
@@ -269,6 +243,7 @@ gsk_linear_gradient_node_new (const graphene_rect_t *bounds,
gsize n_color_stops)
{
GskLinearGradientNode *self;
+ GskRenderNode *node;
gsize i;
g_return_val_if_fail (bounds != NULL, NULL);
@@ -278,19 +253,21 @@ gsk_linear_gradient_node_new (const graphene_rect_t *bounds,
g_return_val_if_fail (n_color_stops >= 2, NULL);
g_return_val_if_fail (color_stops[0].offset >= 0, NULL);
for (i = 1; i < n_color_stops; i++)
- g_return_val_if_fail (color_stops[i].offset >= color_stops[i-1].offset, NULL);
+ g_return_val_if_fail (color_stops[i].offset >= color_stops[i - 1].offset, NULL);
g_return_val_if_fail (color_stops[n_color_stops - 1].offset <= 1, NULL);
- self = (GskLinearGradientNode *) gsk_render_node_new (&GSK_LINEAR_GRADIENT_NODE_CLASS, sizeof (GskColorStop) * n_color_stops);
+ self = gsk_render_node_alloc (GSK_LINEAR_GRADIENT_NODE);
+ node = (GskRenderNode *) self;
- graphene_rect_init_from_rect (&self->render_node.bounds, bounds);
+ graphene_rect_init_from_rect (&node->bounds, bounds);
graphene_point_init_from_point (&self->start, start);
graphene_point_init_from_point (&self->end, end);
- memcpy (&self->stops, color_stops, sizeof (GskColorStop) * n_color_stops);
self->n_stops = n_color_stops;
+ self->stops = g_malloc_n (n_color_stops, sizeof (GskColorStop));
+ memcpy (self->stops, color_stops, n_color_stops * sizeof (GskColorStop));
- return &self->render_node;
+ return node;
}
/**
@@ -305,7 +282,7 @@ gsk_linear_gradient_node_new (const graphene_rect_t *bounds,
* from the given points and color stops, and render that into the area
* given by @bounds.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_repeating_linear_gradient_node_new (const graphene_rect_t *bounds,
@@ -315,6 +292,7 @@ gsk_repeating_linear_gradient_node_new (const graphene_rect_t *bounds,
gsize n_color_stops)
{
GskLinearGradientNode *self;
+ GskRenderNode *node;
gsize i;
g_return_val_if_fail (bounds != NULL, NULL);
@@ -324,21 +302,31 @@ gsk_repeating_linear_gradient_node_new (const graphene_rect_t *bounds,
g_return_val_if_fail (n_color_stops >= 2, NULL);
g_return_val_if_fail (color_stops[0].offset >= 0, NULL);
for (i = 1; i < n_color_stops; i++)
- g_return_val_if_fail (color_stops[i].offset >= color_stops[i-1].offset, NULL);
+ g_return_val_if_fail (color_stops[i].offset >= color_stops[i - 1].offset, NULL);
g_return_val_if_fail (color_stops[n_color_stops - 1].offset <= 1, NULL);
- self = (GskLinearGradientNode *) gsk_render_node_new (&GSK_REPEATING_LINEAR_GRADIENT_NODE_CLASS, sizeof (GskColorStop) * n_color_stops);
+ self = gsk_render_node_alloc (GSK_REPEATING_LINEAR_GRADIENT_NODE);
+ node = (GskRenderNode *) self;
- graphene_rect_init_from_rect (&self->render_node.bounds, bounds);
+ graphene_rect_init_from_rect (&node->bounds, bounds);
graphene_point_init_from_point (&self->start, start);
graphene_point_init_from_point (&self->end, end);
- memcpy (&self->stops, color_stops, sizeof (GskColorStop) * n_color_stops);
+ self->stops = g_malloc_n (n_color_stops, sizeof (GskColorStop));
+ memcpy (self->stops, color_stops, n_color_stops * sizeof (GskColorStop));
self->n_stops = n_color_stops;
- return &self->render_node;
+ return node;
}
+/**
+ * gsk_linear_gradient_node_peek_start:
+ * @node: (type GskLinearGradientNode): a #GskRenderNode for a linear gradient
+ *
+ * Retrieves the initial point of the linear gradient.
+ *
+ * Returns: (transfer none): the initial point
+ */
const graphene_point_t *
gsk_linear_gradient_node_peek_start (GskRenderNode *node)
{
@@ -347,6 +335,14 @@ gsk_linear_gradient_node_peek_start (GskRenderNode *node)
return &self->start;
}
+/**
+ * gsk_linear_gradient_node_peek_end:
+ * @node: (type GskLinearGradientNode): a #GskRenderNode for a linear gradient
+ *
+ * Retrieves the final point of the linear gradient.
+ *
+ * Returns: (transfer none): the final point
+ */
const graphene_point_t *
gsk_linear_gradient_node_peek_end (GskRenderNode *node)
{
@@ -355,6 +351,14 @@ gsk_linear_gradient_node_peek_end (GskRenderNode *node)
return &self->end;
}
+/**
+ * gsk_linear_gradient_node_get_n_color_stops:
+ * @node: (type GskLinearGradientNode): a #GskRenderNode for a linear gradient
+ *
+ * Retrieves the number of color stops in the gradient.
+ *
+ * Returns: the number of color stops
+ */
gsize
gsk_linear_gradient_node_get_n_color_stops (GskRenderNode *node)
{
@@ -363,18 +367,29 @@ gsk_linear_gradient_node_get_n_color_stops (GskRenderNode *node)
return self->n_stops;
}
+/**
+ * gsk_linear_gradient_node_peek_color_stops:
+ * @node: (type GskLinearGradientNode): a #GskRenderNode for a linear gradient
+ * @n_stops: (out) (optional): the number of color stops in the returned array
+ *
+ * Retrievs the color stops in the gradient.
+ *
+ * Returns: (array length=n_stops): the color stops in the gradient
+ */
const GskColorStop *
-gsk_linear_gradient_node_peek_color_stops (GskRenderNode *node)
+gsk_linear_gradient_node_peek_color_stops (GskRenderNode *node,
+ gsize *n_stops)
{
GskLinearGradientNode *self = (GskLinearGradientNode *) node;
+ if (n_stops != NULL)
+ *n_stops = self->n_stops;
+
return self->stops;
}
/*** GSK_BORDER_NODE ***/
-typedef struct _GskBorderNode GskBorderNode;
-
struct _GskBorderNode
{
GskRenderNode render_node;
@@ -385,11 +400,6 @@ struct _GskBorderNode
};
static void
-gsk_border_node_finalize (GskRenderNode *node)
-{
-}
-
-static void
gsk_border_node_mesh_add_patch (cairo_pattern_t *pattern,
const GdkRGBA *color,
double x0,
@@ -547,16 +557,6 @@ gsk_border_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
-static const GskRenderNodeClass GSK_BORDER_NODE_CLASS = {
- GSK_BORDER_NODE,
- sizeof (GskBorderNode),
- "GskBorderNode",
- gsk_border_node_finalize,
- gsk_border_node_draw,
- gsk_render_node_can_diff_true,
- gsk_border_node_diff,
-};
-
const GskRoundedRect *
gsk_border_node_peek_outline (GskRenderNode *node)
{
@@ -593,7 +593,7 @@ gsk_border_node_peek_colors (GskRenderNode *node)
* given @outline. The 4 sides of the border can have different widths and
* colors.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_border_node_new (const GskRoundedRect *outline,
@@ -601,26 +601,26 @@ gsk_border_node_new (const GskRoundedRect *outline,
const GdkRGBA border_color[4])
{
GskBorderNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (outline != NULL, NULL);
g_return_val_if_fail (border_width != NULL, NULL);
g_return_val_if_fail (border_color != NULL, NULL);
- self = (GskBorderNode *) gsk_render_node_new (&GSK_BORDER_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_BORDER_NODE);
+ node = (GskRenderNode *) self;
gsk_rounded_rect_init_copy (&self->outline, outline);
memcpy (self->border_width, border_width, sizeof (self->border_width));
memcpy (self->border_color, border_color, sizeof (self->border_color));
- graphene_rect_init_from_rect (&self->render_node.bounds, &self->outline.bounds);
+ graphene_rect_init_from_rect (&node->bounds, &self->outline.bounds);
- return &self->render_node;
+ return node;
}
/*** GSK_TEXTURE_NODE ***/
-typedef struct _GskTextureNode GskTextureNode;
-
struct _GskTextureNode
{
GskRenderNode render_node;
@@ -632,8 +632,11 @@ static void
gsk_texture_node_finalize (GskRenderNode *node)
{
GskTextureNode *self = (GskTextureNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_TEXTURE_NODE));
- g_object_unref (self->texture);
+ g_clear_object (&self->texture);
+
+ parent_class->finalize (node);
}
static void
@@ -680,19 +683,11 @@ gsk_texture_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
-static const GskRenderNodeClass GSK_TEXTURE_NODE_CLASS = {
- GSK_TEXTURE_NODE,
- sizeof (GskTextureNode),
- "GskTextureNode",
- gsk_texture_node_finalize,
- gsk_texture_node_draw,
- gsk_render_node_can_diff_true,
- gsk_texture_node_diff,
-};
-
/**
* gsk_texture_node_get_texture:
- * @node: a #GskRenderNode
+ * @node: (type GskTextureNode): a #GskRenderNode of type %GSK_TEXTURE_NODE
+ *
+ * Retrieves the #GdkTexture used when creating this #GskRenderNode.
*
* Returns: (transfer none): the #GdkTexture
*/
@@ -714,29 +709,29 @@ gsk_texture_node_get_texture (GskRenderNode *node)
* Creates a #GskRenderNode that will render the given
* @texture into the area given by @bounds.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_texture_node_new (GdkTexture *texture,
const graphene_rect_t *bounds)
{
GskTextureNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
g_return_val_if_fail (bounds != NULL, NULL);
- self = (GskTextureNode *) gsk_render_node_new (&GSK_TEXTURE_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_TEXTURE_NODE);
+ node = (GskRenderNode *) self;
self->texture = g_object_ref (texture);
- graphene_rect_init_from_rect (&self->render_node.bounds, bounds);
+ graphene_rect_init_from_rect (&node->bounds, bounds);
- return &self->render_node;
+ return node;
}
/*** GSK_INSET_SHADOW_NODE ***/
-typedef struct _GskInsetShadowNode GskInsetShadowNode;
-
struct _GskInsetShadowNode
{
GskRenderNode render_node;
@@ -749,11 +744,6 @@ struct _GskInsetShadowNode
float blur_radius;
};
-static void
-gsk_inset_shadow_node_finalize (GskRenderNode *node)
-{
-}
-
static gboolean
has_empty_clip (cairo_t *cr)
{
@@ -1148,18 +1138,8 @@ gsk_inset_shadow_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
-static const GskRenderNodeClass GSK_INSET_SHADOW_NODE_CLASS = {
- GSK_INSET_SHADOW_NODE,
- sizeof (GskInsetShadowNode),
- "GskInsetShadowNode",
- gsk_inset_shadow_node_finalize,
- gsk_inset_shadow_node_draw,
- gsk_render_node_can_diff_true,
- gsk_inset_shadow_node_diff,
-};
-
/**
- * gsk_inset_shadow_node_new:
+ * gsk_inset_shadow_node_new:
* @outline: outline of the region containing the shadow
* @color: color of the shadow
* @dx: horizontal offset of shadow
@@ -1170,7 +1150,7 @@ static const GskRenderNodeClass GSK_INSET_SHADOW_NODE_CLASS = {
* Creates a #GskRenderNode that will render an inset shadow
* into the box given by @outline.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_inset_shadow_node_new (const GskRoundedRect *outline,
@@ -1181,11 +1161,13 @@ gsk_inset_shadow_node_new (const GskRoundedRect *outline,
float blur_radius)
{
GskInsetShadowNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (outline != NULL, NULL);
g_return_val_if_fail (color != NULL, NULL);
- self = (GskInsetShadowNode *) gsk_render_node_new (&GSK_INSET_SHADOW_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_INSET_SHADOW_NODE);
+ node = (GskRenderNode *) self;
gsk_rounded_rect_init_copy (&self->outline, outline);
self->color = *color;
@@ -1194,11 +1176,19 @@ gsk_inset_shadow_node_new (const GskRoundedRect *outline,
self->spread = spread;
self->blur_radius = blur_radius;
- graphene_rect_init_from_rect (&self->render_node.bounds, &self->outline.bounds);
+ graphene_rect_init_from_rect (&node->bounds, &self->outline.bounds);
- return &self->render_node;
+ return node;
}
+/**
+ * gsk_inset_shadow_node_peek_outline:
+ * @node: (type GskInsetShadowNode): a #GskRenderNode for an inset shadow
+ *
+ * Retrieves the outline rectangle of the inset shadow.
+ *
+ * Returns: (transfer none): a rounded rectangle
+ */
const GskRoundedRect *
gsk_inset_shadow_node_peek_outline (GskRenderNode *node)
{
@@ -1209,6 +1199,14 @@ gsk_inset_shadow_node_peek_outline (GskRenderNode *node)
return &self->outline;
}
+/**
+ * gsk_inset_shadow_node_peek_color:
+ * @node: (type GskInsetShadowNode): a #GskRenderNode for an inset shadow
+ *
+ * Retrieves the color of the inset shadow.
+ *
+ * Returns: (transfer none): the color of the shadow
+ */
const GdkRGBA *
gsk_inset_shadow_node_peek_color (GskRenderNode *node)
{
@@ -1219,6 +1217,14 @@ gsk_inset_shadow_node_peek_color (GskRenderNode *node)
return &self->color;
}
+/**
+ * gsk_inset_shadow_node_get_dx:
+ * @node: (type GskInsetShadowNode): a #GskRenderNode for an inset shadow
+ *
+ * Retrieves the horizontal offset of the inset shadow.
+ *
+ * Returns: an offset, in pixels
+ */
float
gsk_inset_shadow_node_get_dx (GskRenderNode *node)
{
@@ -1229,6 +1235,14 @@ gsk_inset_shadow_node_get_dx (GskRenderNode *node)
return self->dx;
}
+/**
+ * gsk_inset_shadow_node_get_dy:
+ * @node: (type GskInsetShadowNode): a #GskRenderNode for an inset shadow
+ *
+ * Retrieves the vertical offset of the inset shadow.
+ *
+ * Returns: an offset, in pixels
+ */
float
gsk_inset_shadow_node_get_dy (GskRenderNode *node)
{
@@ -1239,6 +1253,14 @@ gsk_inset_shadow_node_get_dy (GskRenderNode *node)
return self->dy;
}
+/**
+ * gsk_inset_shadow_node_get_spread:
+ * @node: (type GskInsetShadowNode): a #GskRenderNode for an inset shadow
+ *
+ * Retrieves how much the shadow spreads inwards.
+ *
+ * Returns: the size of the shadow, in pixels
+ */
float
gsk_inset_shadow_node_get_spread (GskRenderNode *node)
{
@@ -1249,6 +1271,14 @@ gsk_inset_shadow_node_get_spread (GskRenderNode *node)
return self->spread;
}
+/**
+ * gsk_inset_shadow_node_get_blur_radius:
+ * @node: (type GskInsetShadowNode): a #GskRenderNode for an inset shadow
+ *
+ * Retrieves the blur radius to apply to the shadow.
+ *
+ * Returns: the blur radius, in pixels
+ */
float
gsk_inset_shadow_node_get_blur_radius (GskRenderNode *node)
{
@@ -1261,8 +1291,6 @@ gsk_inset_shadow_node_get_blur_radius (GskRenderNode *node)
/*** GSK_OUTSET_SHADOW_NODE ***/
-typedef struct _GskOutsetShadowNode GskOutsetShadowNode;
-
struct _GskOutsetShadowNode
{
GskRenderNode render_node;
@@ -1276,11 +1304,6 @@ struct _GskOutsetShadowNode
};
static void
-gsk_outset_shadow_node_finalize (GskRenderNode *node)
-{
-}
-
-static void
gsk_outset_shadow_get_extents (GskOutsetShadowNode *self,
float *top,
float *right,
@@ -1417,18 +1440,8 @@ gsk_outset_shadow_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
-static const GskRenderNodeClass GSK_OUTSET_SHADOW_NODE_CLASS = {
- GSK_OUTSET_SHADOW_NODE,
- sizeof (GskOutsetShadowNode),
- "GskOutsetShadowNode",
- gsk_outset_shadow_node_finalize,
- gsk_outset_shadow_node_draw,
- gsk_render_node_can_diff_true,
- gsk_outset_shadow_node_diff,
-};
-
/**
- * gsk_outset_shadow_node_new:
+ * gsk_outset_shadow_node_new:
* @outline: outline of the region surrounded by shadow
* @color: color of the shadow
* @dx: horizontal offset of shadow
@@ -1439,7 +1452,7 @@ static const GskRenderNodeClass GSK_OUTSET_SHADOW_NODE_CLASS = {
* Creates a #GskRenderNode that will render an outset shadow
* around the box given by @outline.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_outset_shadow_node_new (const GskRoundedRect *outline,
@@ -1450,12 +1463,14 @@ gsk_outset_shadow_node_new (const GskRoundedRect *outline,
float blur_radius)
{
GskOutsetShadowNode *self;
+ GskRenderNode *node;
float top, right, bottom, left;
g_return_val_if_fail (outline != NULL, NULL);
g_return_val_if_fail (color != NULL, NULL);
- self = (GskOutsetShadowNode *) gsk_render_node_new (&GSK_OUTSET_SHADOW_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_OUTSET_SHADOW_NODE);
+ node = (GskRenderNode *) self;
gsk_rounded_rect_init_copy (&self->outline, outline);
self->color = *color;
@@ -1466,16 +1481,23 @@ gsk_outset_shadow_node_new (const GskRoundedRect *outline,
gsk_outset_shadow_get_extents (self, &top, &right, &bottom, &left);
- graphene_rect_init_from_rect (&self->render_node.bounds, &self->outline.bounds);
+ graphene_rect_init_from_rect (&node->bounds, &self->outline.bounds);
+ node->bounds.origin.x -= left;
+ node->bounds.origin.y -= top;
+ node->bounds.size.width += left + right;
+ node->bounds.size.height += top + bottom;
- self->render_node.bounds.origin.x -= left;
- self->render_node.bounds.origin.y -= top;
- self->render_node.bounds.size.width += left + right;
- self->render_node.bounds.size.height += top + bottom;
-
- return &self->render_node;
+ return node;
}
+/**
+ * gsk_outset_shadow_node_peek_outline:
+ * @node: (type GskOutsetShadowNode): a #GskRenderNode for an outset shadow
+ *
+ * Retrieves the outline rectangle of the outset shadow.
+ *
+ * Returns: (transfer none): a rounded rectangle
+ */
const GskRoundedRect *
gsk_outset_shadow_node_peek_outline (GskRenderNode *node)
{
@@ -1486,6 +1508,14 @@ gsk_outset_shadow_node_peek_outline (GskRenderNode *node)
return &self->outline;
}
+/**
+ * gsk_outset_shadow_node_peek_color:
+ * @node: (type GskOutsetShadowNode): a #GskRenderNode for an outset shadow
+ *
+ * Retrieves the color of the outset shadow.
+ *
+ * Returns: (transfer none): a color
+ */
const GdkRGBA *
gsk_outset_shadow_node_peek_color (GskRenderNode *node)
{
@@ -1496,6 +1526,14 @@ gsk_outset_shadow_node_peek_color (GskRenderNode *node)
return &self->color;
}
+/**
+ * gsk_outset_shadow_node_get_dx:
+ * @node: (type GskOutsetShadowNode): a #GskRenderNode for an outset shadow
+ *
+ * Retrieves the horizontal offset of the outset shadow.
+ *
+ * Returns: an offset, in pixels
+ */
float
gsk_outset_shadow_node_get_dx (GskRenderNode *node)
{
@@ -1506,6 +1544,14 @@ gsk_outset_shadow_node_get_dx (GskRenderNode *node)
return self->dx;
}
+/**
+ * gsk_outset_shadow_node_get_dy:
+ * @node: (type GskOutsetShadowNode): a #GskRenderNode for an outset shadow
+ *
+ * Retrieves the vertical offset of the outset shadow.
+ *
+ * Returns: an offset, in pixels
+ */
float
gsk_outset_shadow_node_get_dy (GskRenderNode *node)
{
@@ -1516,6 +1562,14 @@ gsk_outset_shadow_node_get_dy (GskRenderNode *node)
return self->dy;
}
+/**
+ * gsk_outset_shadow_node_get_spread:
+ * @node: (type GskOutsetShadowNode): a #GskRenderNode for an outset shadow
+ *
+ * Retrieves how much the shadow spreads outwards.
+ *
+ * Returns: the size of the shadow, in pixels
+ */
float
gsk_outset_shadow_node_get_spread (GskRenderNode *node)
{
@@ -1526,6 +1580,14 @@ gsk_outset_shadow_node_get_spread (GskRenderNode *node)
return self->spread;
}
+/**
+ * gsk_outset_shadow_node_get_blur_radius:
+ * @node: (type GskOutsetShadowNode): a #GskRenderNode for an outset shadow
+ *
+ * Retrieves the blur radius of the shadow.
+ *
+ * Returns: the blur radius, in pixels
+ */
float
gsk_outset_shadow_node_get_blur_radius (GskRenderNode *node)
{
@@ -1538,8 +1600,6 @@ gsk_outset_shadow_node_get_blur_radius (GskRenderNode *node)
/*** GSK_CAIRO_NODE ***/
-typedef struct _GskCairoNode GskCairoNode;
-
struct _GskCairoNode
{
GskRenderNode render_node;
@@ -1569,16 +1629,14 @@ gsk_cairo_node_draw (GskRenderNode *node,
cairo_paint (cr);
}
-static const GskRenderNodeClass GSK_CAIRO_NODE_CLASS = {
- GSK_CAIRO_NODE,
- sizeof (GskCairoNode),
- "GskCairoNode",
- gsk_cairo_node_finalize,
- gsk_cairo_node_draw,
- gsk_render_node_can_diff_true,
- gsk_render_node_diff_impossible,
-};
-
+/**
+ * gsk_cairo_node_peek_surface:
+ * @node: (type GskCairoNode): a #GskRenderNode for a Cairo surface
+ *
+ * Retrieves the Cairo surface used by the render node.
+ *
+ * Returns: (transfer none): a Cairo surface
+ */
cairo_surface_t *
gsk_cairo_node_peek_surface (GskRenderNode *node)
{
@@ -1590,35 +1648,38 @@ gsk_cairo_node_peek_surface (GskRenderNode *node)
}
/**
- * gsk_cairo_node_new:
+ * gsk_cairo_node_new:
* @bounds: the rectangle to render to
*
* Creates a #GskRenderNode that will render a cairo surface
* into the area given by @bounds. You can draw to the cairo
* surface using gsk_cairo_node_get_draw_context()
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_cairo_node_new (const graphene_rect_t *bounds)
{
GskCairoNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (bounds != NULL, NULL);
- self = (GskCairoNode *) gsk_render_node_new (&GSK_CAIRO_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_CAIRO_NODE);
+ node = (GskRenderNode *) self;
- graphene_rect_init_from_rect (&self->render_node.bounds, bounds);
+ graphene_rect_init_from_rect (&node->bounds, bounds);
- return &self->render_node;
+ return node;
}
/**
* gsk_cairo_node_get_draw_context:
- * @node: a cairo #GskRenderNode
+ * @node: (type GskCairoNode): a #GskRenderNode for a Cairo surface
*
* Creates a Cairo context for drawing using the surface associated
* to the render node.
+ *
* If no surface exists yet, a surface will be created optimized for
* rendering to @renderer.
*
@@ -1667,24 +1728,26 @@ gsk_cairo_node_get_draw_context (GskRenderNode *node)
/**** GSK_CONTAINER_NODE ***/
-typedef struct _GskContainerNode GskContainerNode;
-
struct _GskContainerNode
{
GskRenderNode render_node;
guint n_children;
- GskRenderNode *children[];
+ GskRenderNode **children;
};
static void
gsk_container_node_finalize (GskRenderNode *node)
{
GskContainerNode *container = (GskContainerNode *) node;
- guint i;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_CONTAINER_NODE));
- for (i = 0; i < container->n_children; i++)
+ for (guint i = 0; i < container->n_children; i++)
gsk_render_node_unref (container->children[i]);
+
+ g_free (container->children);
+
+ parent_class->finalize (node);
}
static void
@@ -1700,13 +1763,6 @@ gsk_container_node_draw (GskRenderNode *node,
}
}
-static gboolean
-gsk_container_node_can_diff (const GskRenderNode *node1,
- const GskRenderNode *node2)
-{
- return TRUE;
-}
-
static void
gsk_render_node_add_to_region (GskRenderNode *node,
cairo_region_t *region)
@@ -1771,16 +1827,6 @@ gsk_container_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
-static const GskRenderNodeClass GSK_CONTAINER_NODE_CLASS = {
- GSK_CONTAINER_NODE,
- sizeof (GskContainerNode),
- "GskContainerNode",
- gsk_container_node_finalize,
- gsk_container_node_draw,
- gsk_container_node_can_diff,
- gsk_container_node_diff,
-};
-
/**
* gsk_container_node_new:
* @children: (array length=n_children) (transfer none): The children of the node
@@ -1795,38 +1841,42 @@ GskRenderNode *
gsk_container_node_new (GskRenderNode **children,
guint n_children)
{
- GskContainerNode *container;
- guint i;
+ GskContainerNode *self;
+ GskRenderNode *node;
- container = (GskContainerNode *) gsk_render_node_new (&GSK_CONTAINER_NODE_CLASS, sizeof (GskRenderNode *) * n_children);
+ self = gsk_render_node_alloc (GSK_CONTAINER_NODE);
+ node = (GskRenderNode *) self;
- container->n_children = n_children;
+ self->n_children = n_children;
if (n_children == 0)
{
- graphene_rect_init_from_rect (&container->render_node.bounds, graphene_rect_zero());
+ graphene_rect_init_from_rect (&node->bounds, graphene_rect_zero ());
}
else
{
graphene_rect_t bounds;
- container->children[0] = gsk_render_node_ref (children[0]);
- graphene_rect_init_from_rect (&bounds, &container->children[0]->bounds);
- for (i = 1; i < n_children; i++)
+ self->children = g_malloc_n (n_children, sizeof (GskRenderNode *));
+
+ self->children[0] = gsk_render_node_ref (children[0]);
+ graphene_rect_init_from_rect (&bounds, &(children[0]->bounds));
+
+ for (guint i = 1; i < n_children; i++)
{
- container->children[i] = gsk_render_node_ref (children[i]);
- graphene_rect_union (&bounds, &children[i]->bounds, &bounds);
+ self->children[i] = gsk_render_node_ref (children[i]);
+ graphene_rect_union (&bounds, &(children[i]->bounds), &bounds);
}
- graphene_rect_init_from_rect (&container->render_node.bounds, &bounds);
+ graphene_rect_init_from_rect (&node->bounds, &bounds);
}
- return &container->render_node;
+ return node;
}
/**
* gsk_container_node_get_n_children:
- * @node: a container #GskRenderNode
+ * @node: (type GskContainerNode): a container #GskRenderNode
*
* Retrieves the number of direct children of @node.
*
@@ -1835,38 +1885,36 @@ gsk_container_node_new (GskRenderNode **children,
guint
gsk_container_node_get_n_children (GskRenderNode *node)
{
- GskContainerNode *container = (GskContainerNode *) node;
+ GskContainerNode *self = (GskContainerNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_CONTAINER_NODE), 0);
- return container->n_children;
+ return self->n_children;
}
/**
* gsk_container_node_get_child:
- * @node: a container #GskRenderNode
+ * @node: (type GskContainerNode): a container #GskRenderNode
* @idx: the position of the child to get
*
* Gets one of the children of @container.
*
- * Returns: the @idx'th child of @container
+ * Returns: (transfer none): the @idx'th child of @container
*/
GskRenderNode *
gsk_container_node_get_child (GskRenderNode *node,
guint idx)
{
- GskContainerNode *container = (GskContainerNode *) node;
+ GskContainerNode *self = (GskContainerNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_CONTAINER_NODE), NULL);
- g_return_val_if_fail (idx < container->n_children, 0);
+ g_return_val_if_fail (idx < self->n_children, 0);
- return container->children[idx];
+ return self->children[idx];
}
/*** GSK_TRANSFORM_NODE ***/
-typedef struct _GskTransformNode GskTransformNode;
-
struct _GskTransformNode
{
GskRenderNode render_node;
@@ -1879,9 +1927,12 @@ static void
gsk_transform_node_finalize (GskRenderNode *node)
{
GskTransformNode *self = (GskTransformNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_TRANSFORM_NODE));
gsk_render_node_unref (self->child);
gsk_transform_unref (self->transform);
+
+ parent_class->finalize (node);
}
static void
@@ -1986,55 +2037,47 @@ gsk_transform_node_diff (GskRenderNode *node1,
}
}
-static const GskRenderNodeClass GSK_TRANSFORM_NODE_CLASS = {
- GSK_TRANSFORM_NODE,
- sizeof (GskTransformNode),
- "GskTransformNode",
- gsk_transform_node_finalize,
- gsk_transform_node_draw,
- gsk_transform_node_can_diff,
- gsk_transform_node_diff,
-};
-
/**
- * gsk_transform_node_new:
+ * gsk_transform_node_new:
* @child: The node to transform
* @transform: (transfer none): The transform to apply
*
* Creates a #GskRenderNode that will transform the given @child
* with the given @transform.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_transform_node_new (GskRenderNode *child,
GskTransform *transform)
{
GskTransformNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
g_return_val_if_fail (transform != NULL, NULL);
- self = (GskTransformNode *) gsk_render_node_new (&GSK_TRANSFORM_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_TRANSFORM_NODE);
+ node = (GskRenderNode *) self;
self->child = gsk_render_node_ref (child);
self->transform = gsk_transform_ref (transform);
gsk_transform_transform_bounds (self->transform,
&child->bounds,
- &self->render_node.bounds);
+ &node->bounds);
- return &self->render_node;
+ return node;
}
/**
* gsk_transform_node_get_child:
- * @node: a transform @GskRenderNode
+ * @node: (type GskTransformNode): a #GskRenderNode for a transform
*
* Gets the child node that is getting transformed by the given @node.
*
* Returns: (transfer none): The child that is getting transformed
- **/
+ */
GskRenderNode *
gsk_transform_node_get_child (GskRenderNode *node)
{
@@ -2045,6 +2088,14 @@ gsk_transform_node_get_child (GskRenderNode *node)
return self->child;
}
+/**
+ * gsk_transform_node_get_transform:
+ * @node: (type GskTransformNode): a #GskRenderNode for a transform
+ *
+ * Retrieves the #GskTransform used by the @node.
+ *
+ * Returns: (transfer none): a #GskTransform
+ */
GskTransform *
gsk_transform_node_get_transform (GskRenderNode *node)
{
@@ -2055,137 +2106,8 @@ gsk_transform_node_get_transform (GskRenderNode *node)
return self->transform;
}
-/*** GSK_DEBUG_NODE ***/
-
-typedef struct _GskDebugNode GskDebugNode;
-
-struct _GskDebugNode
-{
- GskRenderNode render_node;
-
- GskRenderNode *child;
- char *message;
-};
-
-static void
-gsk_debug_node_finalize (GskRenderNode *node)
-{
- GskDebugNode *self = (GskDebugNode *) node;
-
- gsk_render_node_unref (self->child);
- g_free (self->message);
-}
-
-static void
-gsk_debug_node_draw (GskRenderNode *node,
- cairo_t *cr)
-{
- GskDebugNode *self = (GskDebugNode *) node;
-
- gsk_render_node_draw (self->child, cr);
-}
-
-static gboolean
-gsk_debug_node_can_diff (const GskRenderNode *node1,
- const GskRenderNode *node2)
-{
- GskDebugNode *self1 = (GskDebugNode *) node1;
- GskDebugNode *self2 = (GskDebugNode *) node2;
-
- return gsk_render_node_can_diff (self1->child, self2->child);
-}
-
-static void
-gsk_debug_node_diff (GskRenderNode *node1,
- GskRenderNode *node2,
- cairo_region_t *region)
-{
- GskDebugNode *self1 = (GskDebugNode *) node1;
- GskDebugNode *self2 = (GskDebugNode *) node2;
-
- gsk_render_node_diff (self1->child, self2->child, region);
-}
-
-static const GskRenderNodeClass GSK_DEBUG_NODE_CLASS = {
- GSK_DEBUG_NODE,
- sizeof (GskDebugNode),
- "GskDebugNode",
- gsk_debug_node_finalize,
- gsk_debug_node_draw,
- gsk_debug_node_can_diff,
- gsk_debug_node_diff,
-};
-
-/**
- * gsk_debug_node_new:
- * @child: The child to add debug info for
- * @message: (transfer full): The debug message
- *
- * Creates a #GskRenderNode that will add debug information about
- * the given @child.
- *
- * Adding this node has no visual effect.
- *
- * Returns: A new #GskRenderNode
- */
-GskRenderNode *
-gsk_debug_node_new (GskRenderNode *child,
- char *message)
-{
- GskDebugNode *self;
-
- g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
-
- self = (GskDebugNode *) gsk_render_node_new (&GSK_DEBUG_NODE_CLASS, 0);
-
- self->child = gsk_render_node_ref (child);
- self->message = message;
-
- graphene_rect_init_from_rect (&self->render_node.bounds, &child->bounds);
-
- return &self->render_node;
-}
-
-/**
- * gsk_debug_node_get_child:
- * @node: a debug @GskRenderNode
- *
- * Gets the child node that is getting debug by the given @node.
- *
- * Returns: (transfer none): The child that is getting debug
- **/
-GskRenderNode *
-gsk_debug_node_get_child (GskRenderNode *node)
-{
- GskDebugNode *self = (GskDebugNode *) node;
-
- g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_DEBUG_NODE), NULL);
-
- return self->child;
-}
-
-/**
- * gsk_debug_node_get_message:
- * @node: a debug #GskRenderNode
- *
- * Gets the debug message that was set on this node
- *
- * Returns: (transfer none): The debug message
- **/
-const char *
-gsk_debug_node_get_message (GskRenderNode *node)
-{
- GskDebugNode *self = (GskDebugNode *) node;
-
- g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_DEBUG_NODE), "You run broken code!");
-
- return self->message;
-}
-
/*** GSK_OPACITY_NODE ***/
-typedef struct _GskOpacityNode GskOpacityNode;
-
struct _GskOpacityNode
{
GskRenderNode render_node;
@@ -2198,8 +2120,11 @@ static void
gsk_opacity_node_finalize (GskRenderNode *node)
{
GskOpacityNode *self = (GskOpacityNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_OPACITY_NODE));
gsk_render_node_unref (self->child);
+
+ parent_class->finalize (node);
}
static void
@@ -2238,52 +2163,44 @@ gsk_opacity_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
-static const GskRenderNodeClass GSK_OPACITY_NODE_CLASS = {
- GSK_OPACITY_NODE,
- sizeof (GskOpacityNode),
- "GskOpacityNode",
- gsk_opacity_node_finalize,
- gsk_opacity_node_draw,
- gsk_render_node_can_diff_true,
- gsk_opacity_node_diff,
-};
-
/**
- * gsk_opacity_node_new:
+ * gsk_opacity_node_new:
* @child: The node to draw
* @opacity: The opacity to apply
*
* Creates a #GskRenderNode that will drawn the @child with reduced
* @opacity.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_opacity_node_new (GskRenderNode *child,
float opacity)
{
GskOpacityNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
- self = (GskOpacityNode *) gsk_render_node_new (&GSK_OPACITY_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_OPACITY_NODE);
+ node = (GskRenderNode *) self;
self->child = gsk_render_node_ref (child);
self->opacity = CLAMP (opacity, 0.0, 1.0);
- graphene_rect_init_from_rect (&self->render_node.bounds, &child->bounds);
+ graphene_rect_init_from_rect (&node->bounds, &child->bounds);
- return &self->render_node;
+ return node;
}
/**
* gsk_opacity_node_get_child:
- * @node: an opacity @GskRenderNode
+ * @node: (type GskOpacityNode): a #GskRenderNode for an opacity
*
* Gets the child node that is getting opacityed by the given @node.
*
* Returns: (transfer none): The child that is getting opacityed
- **/
+ */
GskRenderNode *
gsk_opacity_node_get_child (GskRenderNode *node)
{
@@ -2294,6 +2211,14 @@ gsk_opacity_node_get_child (GskRenderNode *node)
return self->child;
}
+/**
+ * gsk_opacity_node_get_opacity:
+ * @node: (type GskOpacityNode): a #GskRenderNode for an opacity
+ *
+ * Gets the transparency factor for an opacity node.
+ *
+ * Returns: the opacity factor
+ */
float
gsk_opacity_node_get_opacity (GskRenderNode *node)
{
@@ -2306,8 +2231,6 @@ gsk_opacity_node_get_opacity (GskRenderNode *node)
/*** GSK_COLOR_MATRIX_NODE ***/
-typedef struct _GskColorMatrixNode GskColorMatrixNode;
-
struct _GskColorMatrixNode
{
GskRenderNode render_node;
@@ -2321,8 +2244,11 @@ static void
gsk_color_matrix_node_finalize (GskRenderNode *node)
{
GskColorMatrixNode *self = (GskColorMatrixNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_COLOR_MATRIX_NODE));
gsk_render_node_unref (self->child);
+
+ parent_class->finalize (node);
}
static void
@@ -2407,18 +2333,8 @@ gsk_color_matrix_node_draw (GskRenderNode *node,
cairo_pattern_destroy (pattern);
}
-static const GskRenderNodeClass GSK_COLOR_MATRIX_NODE_CLASS = {
- GSK_COLOR_MATRIX_NODE,
- sizeof (GskColorMatrixNode),
- "GskColorMatrixNode",
- gsk_color_matrix_node_finalize,
- gsk_color_matrix_node_draw,
- gsk_render_node_can_diff_true,
- gsk_render_node_diff_impossible,
-};
-
/**
- * gsk_color_matrix_node_new:
+ * gsk_color_matrix_node_new:
* @child: The node to draw
* @color_matrix: The matrix to apply
* @color_offset: Values to add to the color
@@ -2427,10 +2343,14 @@ static const GskRenderNodeClass GSK_COLOR_MATRIX_NODE_CLASS = {
* @color_matrix.
*
* In particular, the node will transform the operation
+ *
+ * |[<!-- language="plain" -->
* pixel = color_matrix * pixel + color_offset
+ * ]|
+ *
* for every pixel.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_color_matrix_node_new (GskRenderNode *child,
@@ -2438,23 +2358,25 @@ gsk_color_matrix_node_new (GskRenderNode *child,
const graphene_vec4_t *color_offset)
{
GskColorMatrixNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
- self = (GskColorMatrixNode *) gsk_render_node_new (&GSK_COLOR_MATRIX_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_COLOR_MATRIX_NODE);
+ node = (GskRenderNode *) self;
self->child = gsk_render_node_ref (child);
graphene_matrix_init_from_matrix (&self->color_matrix, color_matrix);
graphene_vec4_init_from_vec4 (&self->color_offset, color_offset);
- graphene_rect_init_from_rect (&self->render_node.bounds, &child->bounds);
+ graphene_rect_init_from_rect (&node->bounds, &child->bounds);
- return &self->render_node;
+ return node;
}
/**
* gsk_color_matrix_node_get_child:
- * @node: a color matrix @GskRenderNode
+ * @node: (type GskColorMatrixNode): a color matrix #GskRenderNode
*
* Gets the child node that is getting its colors modified by the given @node.
*
@@ -2470,6 +2392,14 @@ gsk_color_matrix_node_get_child (GskRenderNode *node)
return self->child;
}
+/**
+ * gsk_color_matrix_node_peek_color_matrix:
+ * @node: (type GskColorMatrixNode): a color matrix #GskRenderNode
+ *
+ * Retrieves the color matrix used by the @node.
+ *
+ * Returns: a 4x4 color matrix
+ */
const graphene_matrix_t *
gsk_color_matrix_node_peek_color_matrix (GskRenderNode *node)
{
@@ -2480,6 +2410,14 @@ gsk_color_matrix_node_peek_color_matrix (GskRenderNode *node)
return &self->color_matrix;
}
+/**
+ * gsk_color_matrix_node_peek_color_offset:
+ * @node: (type GskColorMatrixNode): a color matrix #GskRenderNode
+ *
+ * Retrieves the color offset used by the @node.
+ *
+ * Returns: a color vector
+ */
const graphene_vec4_t *
gsk_color_matrix_node_peek_color_offset (GskRenderNode *node)
{
@@ -2492,8 +2430,6 @@ gsk_color_matrix_node_peek_color_offset (GskRenderNode *node)
/*** GSK_REPEAT_NODE ***/
-typedef struct _GskRepeatNode GskRepeatNode;
-
struct _GskRepeatNode
{
GskRenderNode render_node;
@@ -2506,8 +2442,11 @@ static void
gsk_repeat_node_finalize (GskRenderNode *node)
{
GskRepeatNode *self = (GskRepeatNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_REPEAT_NODE));
gsk_render_node_unref (self->child);
+
+ parent_class->finalize (node);
}
static void
@@ -2547,18 +2486,8 @@ gsk_repeat_node_draw (GskRenderNode *node,
cairo_fill (cr);
}
-static const GskRenderNodeClass GSK_REPEAT_NODE_CLASS = {
- GSK_REPEAT_NODE,
- sizeof (GskRepeatNode),
- "GskRepeatNode",
- gsk_repeat_node_finalize,
- gsk_repeat_node_draw,
- gsk_render_node_can_diff_true,
- gsk_render_node_diff_impossible,
-};
-
/**
- * gsk_repeat_node_new:
+ * gsk_repeat_node_new:
* @bounds: The bounds of the area to be painted
* @child: The child to repeat
* @child_bounds: (allow-none): The area of the child to repeat or %NULL to
@@ -2567,7 +2496,7 @@ static const GskRenderNodeClass GSK_REPEAT_NODE_CLASS = {
* Creates a #GskRenderNode that will repeat the drawing of @child across
* the given @bounds.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_repeat_node_new (const graphene_rect_t *bounds,
@@ -2575,22 +2504,34 @@ gsk_repeat_node_new (const graphene_rect_t *bounds,
const graphene_rect_t *child_bounds)
{
GskRepeatNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (bounds != NULL, NULL);
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
- self = (GskRepeatNode *) gsk_render_node_new (&GSK_REPEAT_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_REPEAT_NODE);
+ node = (GskRenderNode *) self;
+
+ graphene_rect_init_from_rect (&node->bounds, bounds);
- graphene_rect_init_from_rect (&self->render_node.bounds, bounds);
self->child = gsk_render_node_ref (child);
+
if (child_bounds)
graphene_rect_init_from_rect (&self->child_bounds, child_bounds);
else
graphene_rect_init_from_rect (&self->child_bounds, &child->bounds);
- return &self->render_node;
+ return node;
}
+/**
+ * gsk_repeat_node_get_child:
+ * @node: (type GskRepeatNode): a repeat #GskRenderNode
+ *
+ * Retrieves the child of @node.
+ *
+ * Returns: (transfer none): a #GskRenderNode
+ */
GskRenderNode *
gsk_repeat_node_get_child (GskRenderNode *node)
{
@@ -2601,6 +2542,14 @@ gsk_repeat_node_get_child (GskRenderNode *node)
return self->child;
}
+/**
+ * gsk_repeat_node_peek_child_bounds:
+ * @node: (type GskRepeatNode): a repeat #GskRenderNode
+ *
+ * Retrieves the bounding rectangle of the child of @node.
+ *
+ * Returns: (transfer none): a bounding rectangle
+ */
const graphene_rect_t *
gsk_repeat_node_peek_child_bounds (GskRenderNode *node)
{
@@ -2613,8 +2562,6 @@ gsk_repeat_node_peek_child_bounds (GskRenderNode *node)
/*** GSK_CLIP_NODE ***/
-typedef struct _GskClipNode GskClipNode;
-
struct _GskClipNode
{
GskRenderNode render_node;
@@ -2627,8 +2574,11 @@ static void
gsk_clip_node_finalize (GskRenderNode *node)
{
GskClipNode *self = (GskClipNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_CLIP_NODE));
gsk_render_node_unref (self->child);
+
+ parent_class->finalize (node);
}
static void
@@ -2673,48 +2623,40 @@ gsk_clip_node_diff (GskRenderNode *node1,
}
}
-static const GskRenderNodeClass GSK_CLIP_NODE_CLASS = {
- GSK_CLIP_NODE,
- sizeof (GskClipNode),
- "GskClipNode",
- gsk_clip_node_finalize,
- gsk_clip_node_draw,
- gsk_render_node_can_diff_true,
- gsk_clip_node_diff,
-};
-
/**
- * gsk_clip_node_new:
+ * gsk_clip_node_new:
* @child: The node to draw
* @clip: The clip to apply
*
* Creates a #GskRenderNode that will clip the @child to the area
* given by @clip.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_clip_node_new (GskRenderNode *child,
const graphene_rect_t *clip)
{
GskClipNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
g_return_val_if_fail (clip != NULL, NULL);
- self = (GskClipNode *) gsk_render_node_new (&GSK_CLIP_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_CLIP_NODE);
+ node = (GskRenderNode *) self;
self->child = gsk_render_node_ref (child);
graphene_rect_normalize_r (clip, &self->clip);
- graphene_rect_intersection (&self->clip, &child->bounds, &self->render_node.bounds);
+ graphene_rect_intersection (&self->clip, &child->bounds, &node->bounds);
- return &self->render_node;
+ return node;
}
/**
* gsk_clip_node_get_child:
- * @node: a clip @GskRenderNode
+ * @node: (type GskClipNode): a clip @GskRenderNode
*
* Gets the child node that is getting clipped by the given @node.
*
@@ -2730,6 +2672,14 @@ gsk_clip_node_get_child (GskRenderNode *node)
return self->child;
}
+/**
+ * gsk_clip_node_peek_clip:
+ * @node: (type GskClipNode): a #GskClipNode
+ *
+ * Retrieves the clip rectangle for @node.
+ *
+ * Returns: a clip rectangle
+ */
const graphene_rect_t *
gsk_clip_node_peek_clip (GskRenderNode *node)
{
@@ -2742,8 +2692,6 @@ gsk_clip_node_peek_clip (GskRenderNode *node)
/*** GSK_ROUNDED_CLIP_NODE ***/
-typedef struct _GskRoundedClipNode GskRoundedClipNode;
-
struct _GskRoundedClipNode
{
GskRenderNode render_node;
@@ -2756,8 +2704,11 @@ static void
gsk_rounded_clip_node_finalize (GskRenderNode *node)
{
GskRoundedClipNode *self = (GskRoundedClipNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_ROUNDED_CLIP_NODE));
gsk_render_node_unref (self->child);
+
+ parent_class->finalize (node);
}
static void
@@ -2802,48 +2753,40 @@ gsk_rounded_clip_node_diff (GskRenderNode *node1,
}
}
-static const GskRenderNodeClass GSK_ROUNDED_CLIP_NODE_CLASS = {
- GSK_ROUNDED_CLIP_NODE,
- sizeof (GskRoundedClipNode),
- "GskRoundedClipNode",
- gsk_rounded_clip_node_finalize,
- gsk_rounded_clip_node_draw,
- gsk_render_node_can_diff_true,
- gsk_rounded_clip_node_diff,
-};
-
/**
- * gsk_rounded_clip_node_new:
+ * gsk_rounded_clip_node_new:
* @child: The node to draw
* @clip: The clip to apply
*
* Creates a #GskRenderNode that will clip the @child to the area
* given by @clip.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer none): A new #GskRenderNode
*/
GskRenderNode *
gsk_rounded_clip_node_new (GskRenderNode *child,
const GskRoundedRect *clip)
{
GskRoundedClipNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
g_return_val_if_fail (clip != NULL, NULL);
- self = (GskRoundedClipNode *) gsk_render_node_new (&GSK_ROUNDED_CLIP_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_ROUNDED_CLIP_NODE);
+ node = (GskRenderNode *) self;
self->child = gsk_render_node_ref (child);
gsk_rounded_rect_init_copy (&self->clip, clip);
- graphene_rect_intersection (&self->clip.bounds, &child->bounds, &self->render_node.bounds);
+ graphene_rect_intersection (&self->clip.bounds, &child->bounds, &node->bounds);
- return &self->render_node;
+ return node;
}
/**
* gsk_rounded_clip_node_get_child:
- * @node: a clip @GskRenderNode
+ * @node: (type GskRoundedClipNode): a rounded clip #GskRenderNode
*
* Gets the child node that is getting clipped by the given @node.
*
@@ -2859,6 +2802,14 @@ gsk_rounded_clip_node_get_child (GskRenderNode *node)
return self->child;
}
+/**
+ * gsk_rounded_clip_node_peek_clip:
+ * @node: (type GskRoundedClipNode): a rounded clip #GskRenderNode
+ *
+ * Retrievs the rounded rectangle used to clip the contents of the @node.
+ *
+ * Returns: (transfer none): a rounded rectangle
+ */
const GskRoundedRect *
gsk_rounded_clip_node_peek_clip (GskRenderNode *node)
{
@@ -2871,8 +2822,6 @@ gsk_rounded_clip_node_peek_clip (GskRenderNode *node)
/*** GSK_SHADOW_NODE ***/
-typedef struct _GskShadowNode GskShadowNode;
-
struct _GskShadowNode
{
GskRenderNode render_node;
@@ -2880,15 +2829,19 @@ struct _GskShadowNode
GskRenderNode *child;
gsize n_shadows;
- GskShadow shadows[];
+ GskShadow *shadows;
};
static void
gsk_shadow_node_finalize (GskRenderNode *node)
{
GskShadowNode *self = (GskShadowNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_SHADOW_NODE));
gsk_render_node_unref (self->child);
+ g_free (self->shadows);
+
+ parent_class->finalize (node);
}
static void
@@ -3013,18 +2966,8 @@ gsk_shadow_node_get_bounds (GskShadowNode *self,
bounds->size.height += top + bottom;
}
-static const GskRenderNodeClass GSK_SHADOW_NODE_CLASS = {
- GSK_SHADOW_NODE,
- sizeof (GskShadowNode),
- "GskShadowNode",
- gsk_shadow_node_finalize,
- gsk_shadow_node_draw,
- gsk_render_node_can_diff_true,
- gsk_shadow_node_diff,
-};
-
/**
- * gsk_shadow_node_new:
+ * gsk_shadow_node_new:
* @child: The node to draw
* @shadows: (array length=n_shadows): The shadows to apply
* @n_shadows: number of entries in the @shadows array
@@ -3032,30 +2975,41 @@ static const GskRenderNodeClass GSK_SHADOW_NODE_CLASS = {
* Creates a #GskRenderNode that will draw a @child with the given
* @shadows below it.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
-gsk_shadow_node_new (GskRenderNode *child,
- const GskShadow *shadows,
- gsize n_shadows)
+gsk_shadow_node_new (GskRenderNode *child,
+ const GskShadow *shadows,
+ gsize n_shadows)
{
GskShadowNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
g_return_val_if_fail (shadows != NULL, NULL);
g_return_val_if_fail (n_shadows > 0, NULL);
- self = (GskShadowNode *) gsk_render_node_new (&GSK_SHADOW_NODE_CLASS, n_shadows * sizeof (GskShadow));
+ self = gsk_render_node_alloc (GSK_SHADOW_NODE);
+ node = (GskRenderNode *) self;
self->child = gsk_render_node_ref (child);
- memcpy (&self->shadows, shadows, n_shadows * sizeof (GskShadow));
self->n_shadows = n_shadows;
+ self->shadows = g_malloc_n (n_shadows, sizeof (GskShadow));
+ memcpy (self->shadows, shadows, n_shadows * sizeof (GskShadow));
- gsk_shadow_node_get_bounds (self, &self->render_node.bounds);
+ gsk_shadow_node_get_bounds (self, &node->bounds);
- return &self->render_node;
+ return node;
}
+/**
+ * gsk_shadow_node_get_child:
+ * @node: (type GskShadowNode): a shadow #GskRenderNode
+ *
+ * Retrieves the child #GskRenderNode of the shadow @node.
+ *
+ * Returns: (transfer none): the child render node
+ */
GskRenderNode *
gsk_shadow_node_get_child (GskRenderNode *node)
{
@@ -3066,6 +3020,14 @@ gsk_shadow_node_get_child (GskRenderNode *node)
return self->child;
}
+/**
+ * gsk_shadow_node_peek_shadow:
+ * @node: (type GskShadowNode): a shadow #GskRenderNode
+ *
+ * Retrieves the shadow data at the given index @i.
+ *
+ * Returns: (transfer none): the shadow data
+ */
const GskShadow *
gsk_shadow_node_peek_shadow (GskRenderNode *node,
gsize i)
@@ -3078,6 +3040,14 @@ gsk_shadow_node_peek_shadow (GskRenderNode *node,
return &self->shadows[i];
}
+/**
+ * gsk_shadow_node_get_n_shadows:
+ * @node: (type GskShadowNode): a shadow #GskRenderNode
+ *
+ * Retrieves the number of shadows in the @node.
+ *
+ * Returns: the number of shadows.
+ */
gsize
gsk_shadow_node_get_n_shadows (GskRenderNode *node)
{
@@ -3090,8 +3060,6 @@ gsk_shadow_node_get_n_shadows (GskRenderNode *node)
/*** GSK_BLEND_NODE ***/
-typedef struct _GskBlendNode GskBlendNode;
-
struct _GskBlendNode
{
GskRenderNode render_node;
@@ -3147,9 +3115,12 @@ static void
gsk_blend_node_finalize (GskRenderNode *node)
{
GskBlendNode *self = (GskBlendNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_BLEND_NODE));
gsk_render_node_unref (self->bottom);
gsk_render_node_unref (self->top);
+
+ parent_class->finalize (node);
}
static void
@@ -3191,18 +3162,8 @@ gsk_blend_node_diff (GskRenderNode *node1,
}
}
-static const GskRenderNodeClass GSK_BLEND_NODE_CLASS = {
- GSK_BLEND_NODE,
- sizeof (GskBlendNode),
- "GskBlendNode",
- gsk_blend_node_finalize,
- gsk_blend_node_draw,
- gsk_render_node_can_diff_true,
- gsk_blend_node_diff,
-};
-
/**
- * gsk_blend_node_new:
+ * gsk_blend_node_new:
* @bottom: The bottom node to be drawn
* @top: The node to be blended onto the @bottom node
* @blend_mode: The blend mode to use
@@ -3210,7 +3171,7 @@ static const GskRenderNodeClass GSK_BLEND_NODE_CLASS = {
* Creates a #GskRenderNode that will use @blend_mode to blend the @top
* node onto the @bottom node.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_blend_node_new (GskRenderNode *bottom,
@@ -3218,21 +3179,31 @@ gsk_blend_node_new (GskRenderNode *bottom,
GskBlendMode blend_mode)
{
GskBlendNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (GSK_IS_RENDER_NODE (bottom), NULL);
g_return_val_if_fail (GSK_IS_RENDER_NODE (top), NULL);
- self = (GskBlendNode *) gsk_render_node_new (&GSK_BLEND_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_BLEND_NODE);
+ node = (GskRenderNode *) self;
self->bottom = gsk_render_node_ref (bottom);
self->top = gsk_render_node_ref (top);
self->blend_mode = blend_mode;
- graphene_rect_union (&bottom->bounds, &top->bounds, &self->render_node.bounds);
+ graphene_rect_union (&bottom->bounds, &top->bounds, &node->bounds);
- return &self->render_node;
+ return node;
}
+/**
+ * gsk_blend_node_get_bottom_child:
+ * @node: (type GskBlendNode): a blending #GskRenderNode
+ *
+ * Retrieves the bottom #GskRenderNode child of the @node.
+ *
+ * Returns: (transfer none): the bottom child node
+ */
GskRenderNode *
gsk_blend_node_get_bottom_child (GskRenderNode *node)
{
@@ -3243,6 +3214,14 @@ gsk_blend_node_get_bottom_child (GskRenderNode *node)
return self->bottom;
}
+/**
+ * gsk_blend_node_get_top_child:
+ * @node: (type GskBlendNode): a blending #GskRenderNode
+ *
+ * Retrieves the top #GskRenderNode child of the @node.
+ *
+ * Returns: (transfer none): the top child node
+ */
GskRenderNode *
gsk_blend_node_get_top_child (GskRenderNode *node)
{
@@ -3253,6 +3232,14 @@ gsk_blend_node_get_top_child (GskRenderNode *node)
return self->top;
}
+/**
+ * gsk_blend_node_get_blend_mode:
+ * @node: (type GskBlendNode): a blending #GskRenderNode
+ *
+ * Retrieves the blend mode used by @node.
+ *
+ * Returns: the blend mode
+ */
GskBlendMode
gsk_blend_node_get_blend_mode (GskRenderNode *node)
{
@@ -3265,8 +3252,6 @@ gsk_blend_node_get_blend_mode (GskRenderNode *node)
/*** GSK_CROSS_FADE_NODE ***/
-typedef struct _GskCrossFadeNode GskCrossFadeNode;
-
struct _GskCrossFadeNode
{
GskRenderNode render_node;
@@ -3280,9 +3265,12 @@ static void
gsk_cross_fade_node_finalize (GskRenderNode *node)
{
GskCrossFadeNode *self = (GskCrossFadeNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_CROSS_FADE_NODE));
gsk_render_node_unref (self->start);
gsk_render_node_unref (self->end);
+
+ parent_class->finalize (node);
}
static void
@@ -3323,18 +3311,8 @@ gsk_cross_fade_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
-static const GskRenderNodeClass GSK_CROSS_FADE_NODE_CLASS = {
- GSK_CROSS_FADE_NODE,
- sizeof (GskCrossFadeNode),
- "GskCrossFadeNode",
- gsk_cross_fade_node_finalize,
- gsk_cross_fade_node_draw,
- gsk_render_node_can_diff_true,
- gsk_cross_fade_node_diff,
-};
-
/**
- * gsk_cross_fade_node_new:
+ * gsk_cross_fade_node_new:
* @start: The start node to be drawn
* @end: The node to be cross_fadeed onto the @start node
* @progress: How far the fade has progressed from start to end. The value will
@@ -3342,7 +3320,7 @@ static const GskRenderNodeClass GSK_CROSS_FADE_NODE_CLASS = {
*
* Creates a #GskRenderNode that will do a cross-fade between @start and @end.
*
- * Returns: A new #GskRenderNode
+ * Returns: (transfer full): A new #GskRenderNode
*/
GskRenderNode *
gsk_cross_fade_node_new (GskRenderNode *start,
@@ -3350,21 +3328,31 @@ gsk_cross_fade_node_new (GskRenderNode *start,
float progress)
{
GskCrossFadeNode *self;
+ GskRenderNode *node;
g_return_val_if_fail (GSK_IS_RENDER_NODE (start), NULL);
g_return_val_if_fail (GSK_IS_RENDER_NODE (end), NULL);
- self = (GskCrossFadeNode *) gsk_render_node_new (&GSK_CROSS_FADE_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_CROSS_FADE_NODE);
+ node = (GskRenderNode *) self;
self->start = gsk_render_node_ref (start);
self->end = gsk_render_node_ref (end);
self->progress = CLAMP (progress, 0.0, 1.0);
- graphene_rect_union (&start->bounds, &end->bounds, &self->render_node.bounds);
+ graphene_rect_union (&start->bounds, &end->bounds, &node->bounds);
- return &self->render_node;
+ return node;
}
+/**
+ * gsk_cross_fade_node_get_start_child:
+ * @node: (type GskCrossFadeNode): a cross-fading #GskRenderNode
+ *
+ * Retrieves the child #GskRenderNode at the beginning of the cross-fade.
+ *
+ * Returns: (transfer none): a #GskRenderNode
+ */
GskRenderNode *
gsk_cross_fade_node_get_start_child (GskRenderNode *node)
{
@@ -3375,6 +3363,14 @@ gsk_cross_fade_node_get_start_child (GskRenderNode *node)
return self->start;
}
+/**
+ * gsk_cross_fade_node_get_end_child:
+ * @node: (type GskCrossFadeNode): a cross-fading #GskRenderNode
+ *
+ * Retrieves the child #GskRenderNode at the end of the cross-fade.
+ *
+ * Returns: (transfer none): a #GskRenderNode
+ */
GskRenderNode *
gsk_cross_fade_node_get_end_child (GskRenderNode *node)
{
@@ -3385,6 +3381,14 @@ gsk_cross_fade_node_get_end_child (GskRenderNode *node)
return self->end;
}
+/**
+ * gsk_cross_fade_node_get_progress:
+ * @node: (type GskCrossFadeNode): a cross-fading #GskRenderNode
+ *
+ * Retrieves the progress value of the cross fade.
+ *
+ * Returns: the progress value, between 0 and 1
+ */
float
gsk_cross_fade_node_get_progress (GskRenderNode *node)
{
@@ -3397,8 +3401,6 @@ gsk_cross_fade_node_get_progress (GskRenderNode *node)
/*** GSK_TEXT_NODE ***/
-typedef struct _GskTextNode GskTextNode;
-
struct _GskTextNode
{
GskRenderNode render_node;
@@ -3410,15 +3412,19 @@ struct _GskTextNode
graphene_point_t offset;
guint num_glyphs;
- PangoGlyphInfo glyphs[];
+ PangoGlyphInfo *glyphs;
};
static void
gsk_text_node_finalize (GskRenderNode *node)
{
GskTextNode *self = (GskTextNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_TEXT_NODE));
g_object_unref (self->font);
+ g_free (self->glyphs);
+
+ parent_class->finalize (node);
}
static void
@@ -3478,16 +3484,6 @@ gsk_text_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
-static const GskRenderNodeClass GSK_TEXT_NODE_CLASS = {
- GSK_TEXT_NODE,
- sizeof (GskTextNode),
- "GskTextNode",
- gsk_text_node_finalize,
- gsk_text_node_draw,
- gsk_render_node_can_diff_true,
- gsk_text_node_diff,
-};
-
static gboolean
font_has_color_glyphs (const PangoFont *font)
{
@@ -3506,7 +3502,7 @@ font_has_color_glyphs (const PangoFont *font)
}
/**
- * gsk_text_node_new:
+ * gsk_text_node_new:
* @font: the #PangoFont containing the glyphs
* @glyphs: the #PangoGlyphString to render
* @color: the foreground color to render with
@@ -3516,7 +3512,7 @@ font_has_color_glyphs (const PangoFont *font)
* Note that @color may not be used if the font contains
* color glyphs.
*
- * Returns: (nullable): a new text node, or %NULL
+ * Returns: (nullable) (transfer full): a new text node, or %NULL
*/
GskRenderNode *
gsk_text_node_new (PangoFont *font,
@@ -3525,6 +3521,7 @@ gsk_text_node_new (PangoFont *font,
const graphene_point_t *offset)
{
GskTextNode *self;
+ GskRenderNode *node;
PangoRectangle ink_rect;
pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
@@ -3534,24 +3531,34 @@ gsk_text_node_new (PangoFont *font,
if (ink_rect.width == 0 || ink_rect.height == 0)
return NULL;
- self = (GskTextNode *) gsk_render_node_new (&GSK_TEXT_NODE_CLASS, sizeof (PangoGlyphInfo) * glyphs->num_glyphs);
+ self = gsk_render_node_alloc (GSK_TEXT_NODE);
+ node = (GskRenderNode *) self;
self->font = g_object_ref (font);
self->has_color_glyphs = font_has_color_glyphs (font);
self->color = *color;
self->offset = *offset;
self->num_glyphs = glyphs->num_glyphs;
- memcpy (self->glyphs, glyphs->glyphs, sizeof (PangoGlyphInfo) * glyphs->num_glyphs);
+ self->glyphs = g_malloc_n (glyphs->num_glyphs, sizeof (PangoGlyphInfo));
+ memcpy (self->glyphs, glyphs->glyphs, glyphs->num_glyphs * sizeof (PangoGlyphInfo));
- graphene_rect_init (&self->render_node.bounds,
+ graphene_rect_init (&node->bounds,
offset->x + ink_rect.x - 1,
offset->y + ink_rect.y - 1,
ink_rect.width + 2,
ink_rect.height + 2);
- return &self->render_node;
+ return node;
}
+/**
+ * gsk_text_node_peek_color:
+ * @node: (type GskTextNode): a text #GskRenderNode
+ *
+ * Retrieves the color used by the text @node.
+ *
+ * Returns: (transfer none): the text color
+ */
const GdkRGBA *
gsk_text_node_peek_color (GskRenderNode *node)
{
@@ -3566,9 +3573,9 @@ gsk_text_node_peek_color (GskRenderNode *node)
* gsk_text_node_peek_font:
* @node: The #GskRenderNode
*
- * Returns the font used by the text node.
+ * Returns the font used by the text @node.
*
- * Returns: (transfer none): The used #PangoFont.
+ * Returns: (transfer none): the font
*/
PangoFont *
gsk_text_node_peek_font (GskRenderNode *node)
@@ -3580,6 +3587,14 @@ gsk_text_node_peek_font (GskRenderNode *node)
return self->font;
}
+/**
+ * gsk_text_node_has_color_glyphs:
+ * @node: (type GskTextNode): a text #GskRenderNode
+ *
+ * Checks whether the text @node has color glyphs.
+ *
+ * Returns: %TRUE if the text node has color glyphs
+ */
gboolean
gsk_text_node_has_color_glyphs (GskRenderNode *node)
{
@@ -3600,16 +3615,37 @@ gsk_text_node_get_num_glyphs (GskRenderNode *node)
return self->num_glyphs;
}
+/**
+ * gsk_text_node_peek_glyphs:
+ * @node: (type GskTextNode): a text #GskRenderNode
+ * @n_glyphs: (out) (optional): the number of glyphs returned
+ *
+ * Retrieves the glyph information in the @node.
+ *
+ * Returns: (transfer none) (array length=n_glyphs): the glyph information
+ */
const PangoGlyphInfo *
-gsk_text_node_peek_glyphs (GskRenderNode *node)
+gsk_text_node_peek_glyphs (GskRenderNode *node,
+ guint *n_glyphs)
{
GskTextNode *self = (GskTextNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_TEXT_NODE), NULL);
+ if (n_glyphs != NULL)
+ *n_glyphs = self->num_glyphs;
+
return self->glyphs;
}
+/**
+ * gsk_text_node_get_offset:
+ * @node: (type GskTextNode): a text #GskRenderNode
+ *
+ * Retrieves the offset applied to the text.
+ *
+ * Returns: (transfer none): a point with the horizontal and vertical offsets
+ */
const graphene_point_t *
gsk_text_node_get_offset (GskRenderNode *node)
{
@@ -3622,8 +3658,6 @@ gsk_text_node_get_offset (GskRenderNode *node)
/*** GSK_BLUR_NODE ***/
-typedef struct _GskBlurNode GskBlurNode;
-
struct _GskBlurNode
{
GskRenderNode render_node;
@@ -3636,8 +3670,11 @@ static void
gsk_blur_node_finalize (GskRenderNode *node)
{
GskBlurNode *self = (GskBlurNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_BLUR_NODE));
gsk_render_node_unref (self->child);
+
+ parent_class->finalize (node);
}
static void
@@ -3860,44 +3897,49 @@ gsk_blur_node_diff (GskRenderNode *node1,
}
}
-static const GskRenderNodeClass GSK_BLUR_NODE_CLASS = {
- GSK_BLUR_NODE,
- sizeof (GskBlurNode),
- "GskBlurNode",
- gsk_blur_node_finalize,
- gsk_blur_node_draw,
- gsk_render_node_can_diff_true,
- gsk_blur_node_diff,
-};
-
/**
- * gsk_blur_node_new:
+ * gsk_blur_node_new:
* @child: the child node to blur
* @radius: the blur radius
*
* Creates a render node that blurs the child.
+ *
+ * Returns: (transfer full): a new #GskRenderNode
*/
GskRenderNode *
gsk_blur_node_new (GskRenderNode *child,
float radius)
{
GskBlurNode *self;
- float clip_radius = gsk_cairo_blur_compute_pixels (radius);
+ GskRenderNode *node;
+ float clip_radius;
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
- self = (GskBlurNode *) gsk_render_node_new (&GSK_BLUR_NODE_CLASS, 0);
+ self = gsk_render_node_alloc (GSK_BLUR_NODE);
+ node = (GskRenderNode *) self;
self->child = gsk_render_node_ref (child);
self->radius = radius;
- graphene_rect_init_from_rect (&self->render_node.bounds, &child->bounds);
+ clip_radius = gsk_cairo_blur_compute_pixels (radius);
+
+ graphene_rect_init_from_rect (&node->bounds, &child->bounds);
graphene_rect_inset (&self->render_node.bounds,
- - clip_radius, - clip_radius);
+ - clip_radius,
+ - clip_radius);
- return &self->render_node;
+ return node;
}
+/**
+ * gsk_blur_node_get_child:
+ * @node: (type GskBlurNode): a blur #GskRenderNode
+ *
+ * Retrieves the child #GskRenderNode of the blur @node.
+ *
+ * Returns: (transfer none): the blurred child node
+ */
GskRenderNode *
gsk_blur_node_get_child (GskRenderNode *node)
{
@@ -3908,6 +3950,14 @@ gsk_blur_node_get_child (GskRenderNode *node)
return self->child;
}
+/**
+ * gsk_blur_node_get_radius:
+ * @node: (type GskBlurNode): a blur #GskRenderNode
+ *
+ * Retrieves the blur radius of the @node.
+ *
+ * Returns: the blur radius
+ */
float
gsk_blur_node_get_radius (GskRenderNode *node)
{
@@ -3917,3 +3967,493 @@ gsk_blur_node_get_radius (GskRenderNode *node)
return self->radius;
}
+
+/*** GSK_DEBUG_NODE ***/
+
+struct _GskDebugNode
+{
+ GskRenderNode render_node;
+
+ GskRenderNode *child;
+ char *message;
+};
+
+static void
+gsk_debug_node_finalize (GskRenderNode *node)
+{
+ GskDebugNode *self = (GskDebugNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_DEBUG_NODE));
+
+ gsk_render_node_unref (self->child);
+ g_free (self->message);
+
+ parent_class->finalize (node);
+}
+
+static void
+gsk_debug_node_draw (GskRenderNode *node,
+ cairo_t *cr)
+{
+ GskDebugNode *self = (GskDebugNode *) node;
+
+ gsk_render_node_draw (self->child, cr);
+}
+
+static gboolean
+gsk_debug_node_can_diff (const GskRenderNode *node1,
+ const GskRenderNode *node2)
+{
+ GskDebugNode *self1 = (GskDebugNode *) node1;
+ GskDebugNode *self2 = (GskDebugNode *) node2;
+
+ return gsk_render_node_can_diff (self1->child, self2->child);
+}
+
+static void
+gsk_debug_node_diff (GskRenderNode *node1,
+ GskRenderNode *node2,
+ cairo_region_t *region)
+{
+ GskDebugNode *self1 = (GskDebugNode *) node1;
+ GskDebugNode *self2 = (GskDebugNode *) node2;
+
+ gsk_render_node_diff (self1->child, self2->child, region);
+}
+
+/**
+ * gsk_debug_node_new:
+ * @child: The child to add debug info for
+ * @message: (transfer full): The debug message
+ *
+ * Creates a #GskRenderNode that will add debug information about
+ * the given @child.
+ *
+ * Adding this node has no visual effect.
+ *
+ * Returns: (transfer full): A new #GskRenderNode
+ */
+GskRenderNode *
+gsk_debug_node_new (GskRenderNode *child,
+ char *message)
+{
+ GskDebugNode *self;
+ GskRenderNode *node;
+
+ g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
+
+ self = gsk_render_node_alloc (GSK_DEBUG_NODE);
+ node = (GskRenderNode *) self;
+
+ self->child = gsk_render_node_ref (child);
+ self->message = message;
+
+ graphene_rect_init_from_rect (&node->bounds, &child->bounds);
+
+ return node;
+}
+
+/**
+ * gsk_debug_node_get_child:
+ * @node: (type GskDebugNode): a debug #GskRenderNode
+ *
+ * Gets the child node that is getting drawn by the given @node.
+ *
+ * Returns: (transfer none): the child #GskRenderNode
+ **/
+GskRenderNode *
+gsk_debug_node_get_child (GskRenderNode *node)
+{
+ GskDebugNode *self = (GskDebugNode *) node;
+
+ g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_DEBUG_NODE), NULL);
+
+ return self->child;
+}
+
+/**
+ * gsk_debug_node_get_message:
+ * @node: (type GskDebugNode): a debug #GskRenderNode
+ *
+ * Gets the debug message that was set on this node
+ *
+ * Returns: (transfer none): The debug message
+ **/
+const char *
+gsk_debug_node_get_message (GskRenderNode *node)
+{
+ GskDebugNode *self = (GskDebugNode *) node;
+
+ g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_DEBUG_NODE), "You run broken code!");
+
+ return self->message;
+}
+
+#ifndef I_
+# define I_(str) g_intern_static_string ((str))
+#endif
+
+/*< private >
+ * gsk_render_node_init_types:
+ *
+ * Initialize all the #GskRenderNode types provided by GSK.
+ */
+void
+gsk_render_node_init_types (void)
+{
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_CONTAINER_NODE,
+ sizeof (GskContainerNode),
+ NULL,
+ gsk_container_node_finalize,
+ gsk_container_node_draw,
+ NULL,
+ gsk_container_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskContainerNode"), &node_info);
+ gsk_render_node_types[GSK_CONTAINER_NODE] = node_type;
+ g_assert (GSK_TYPE_CONTAINER_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_CAIRO_NODE,
+ sizeof (GskCairoNode),
+ NULL,
+ gsk_cairo_node_finalize,
+ gsk_cairo_node_draw,
+ NULL,
+ NULL,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskCairoNode"), &node_info);
+ gsk_render_node_types[GSK_CAIRO_NODE] = node_type;
+ g_assert (GSK_TYPE_CAIRO_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_COLOR_NODE,
+ sizeof (GskColorNode),
+ NULL,
+ NULL,
+ gsk_color_node_draw,
+ NULL,
+ gsk_color_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskColorNode"), &node_info);
+ gsk_render_node_types[GSK_COLOR_NODE] = node_type;
+ g_assert (GSK_TYPE_COLOR_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_LINEAR_GRADIENT_NODE,
+ sizeof (GskLinearGradientNode),
+ NULL,
+ gsk_linear_gradient_node_finalize,
+ gsk_linear_gradient_node_draw,
+ NULL,
+ gsk_linear_gradient_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskLinearGradientNode"), &node_info);
+ gsk_render_node_types[GSK_LINEAR_GRADIENT_NODE] = node_type;
+ g_assert (GSK_TYPE_LINEAR_GRADIENT_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_REPEATING_LINEAR_GRADIENT_NODE,
+ sizeof (GskLinearGradientNode),
+ NULL,
+ gsk_linear_gradient_node_finalize,
+ gsk_linear_gradient_node_draw,
+ NULL,
+ gsk_linear_gradient_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskRepeatingLinearGradientNode"), &node_info);
+ gsk_render_node_types[GSK_REPEATING_LINEAR_GRADIENT_NODE] = node_type;
+ g_assert (GSK_TYPE_REPEATING_LINEAR_GRADIENT_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_BORDER_NODE,
+ sizeof (GskBorderNode),
+ NULL,
+ NULL,
+ gsk_border_node_draw,
+ NULL,
+ gsk_border_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskBorderNode"), &node_info);
+ gsk_render_node_types[GSK_BORDER_NODE] = node_type;
+ g_assert (GSK_TYPE_BORDER_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_TEXTURE_NODE,
+ sizeof (GskTextureNode),
+ NULL,
+ gsk_texture_node_finalize,
+ gsk_texture_node_draw,
+ NULL,
+ gsk_texture_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskTextureNode"), &node_info);
+ gsk_render_node_types[GSK_TEXTURE_NODE] = node_type;
+ g_assert (GSK_TYPE_TEXTURE_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_INSET_SHADOW_NODE,
+ sizeof (GskInsetShadowNode),
+ NULL,
+ NULL,
+ gsk_inset_shadow_node_draw,
+ NULL,
+ gsk_inset_shadow_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskInsetShadowNode"), &node_info);
+ gsk_render_node_types[GSK_INSET_SHADOW_NODE] = node_type;
+ g_assert (GSK_TYPE_INSET_SHADOW_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_OUTSET_SHADOW_NODE,
+ sizeof (GskOutsetShadowNode),
+ NULL,
+ NULL,
+ gsk_outset_shadow_node_draw,
+ NULL,
+ gsk_outset_shadow_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskOutsetShadowNode"), &node_info);
+ gsk_render_node_types[GSK_OUTSET_SHADOW_NODE] = node_type;
+ g_assert (GSK_TYPE_OUTSET_SHADOW_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_TRANSFORM_NODE,
+ sizeof (GskTransformNode),
+ NULL,
+ gsk_transform_node_finalize,
+ gsk_transform_node_draw,
+ gsk_transform_node_can_diff,
+ gsk_transform_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskTransformNode"), &node_info);
+ gsk_render_node_types[GSK_TRANSFORM_NODE] = node_type;
+ g_assert (GSK_TYPE_TRANSFORM_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_OPACITY_NODE,
+ sizeof (GskOpacityNode),
+ NULL,
+ gsk_opacity_node_finalize,
+ gsk_opacity_node_draw,
+ NULL,
+ gsk_opacity_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskOpacityNode"), &node_info);
+ gsk_render_node_types[GSK_OPACITY_NODE] = node_type;
+ g_assert (GSK_TYPE_OPACITY_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_COLOR_MATRIX_NODE,
+ sizeof (GskColorMatrixNode),
+ NULL,
+ gsk_color_matrix_node_finalize,
+ gsk_color_matrix_node_draw,
+ NULL,
+ NULL,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskColorMatrixNode"), &node_info);
+ gsk_render_node_types[GSK_COLOR_MATRIX_NODE] = node_type;
+ g_assert (GSK_TYPE_COLOR_MATRIX_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_REPEAT_NODE,
+ sizeof (GskRepeatNode),
+ NULL,
+ gsk_repeat_node_finalize,
+ gsk_repeat_node_draw,
+ NULL,
+ NULL,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskRepeatNode"), &node_info);
+ gsk_render_node_types[GSK_REPEAT_NODE] = node_type;
+ g_assert (GSK_TYPE_REPEAT_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_CLIP_NODE,
+ sizeof (GskClipNode),
+ NULL,
+ gsk_clip_node_finalize,
+ gsk_clip_node_draw,
+ NULL,
+ gsk_clip_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskClipNode"), &node_info);
+ gsk_render_node_types[GSK_CLIP_NODE] = node_type;
+ g_assert (GSK_TYPE_CLIP_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_ROUNDED_CLIP_NODE,
+ sizeof (GskRoundedClipNode),
+ NULL,
+ gsk_rounded_clip_node_finalize,
+ gsk_rounded_clip_node_draw,
+ NULL,
+ gsk_rounded_clip_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskRoundedClipNode"), &node_info);
+ gsk_render_node_types[GSK_ROUNDED_CLIP_NODE] = node_type;
+ g_assert (GSK_TYPE_ROUNDED_CLIP_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_SHADOW_NODE,
+ sizeof (GskShadowNode),
+ NULL,
+ gsk_shadow_node_finalize,
+ gsk_shadow_node_draw,
+ NULL,
+ gsk_shadow_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskShadowNode"), &node_info);
+ gsk_render_node_types[GSK_SHADOW_NODE] = node_type;
+ g_assert (GSK_TYPE_SHADOW_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_BLEND_NODE,
+ sizeof (GskBlendNode),
+ NULL,
+ gsk_blend_node_finalize,
+ gsk_blend_node_draw,
+ NULL,
+ gsk_blend_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskBlendNode"), &node_info);
+ gsk_render_node_types[GSK_BLEND_NODE] = node_type;
+ g_assert (GSK_TYPE_BLEND_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_CROSS_FADE_NODE,
+ sizeof (GskCrossFadeNode),
+ NULL,
+ gsk_cross_fade_node_finalize,
+ gsk_cross_fade_node_draw,
+ NULL,
+ gsk_cross_fade_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskCrossFadeNode"), &node_info);
+ gsk_render_node_types[GSK_CROSS_FADE_NODE] = node_type;
+ g_assert (GSK_TYPE_CROSS_FADE_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_TEXT_NODE,
+ sizeof (GskTextNode),
+ NULL,
+ gsk_text_node_finalize,
+ gsk_text_node_draw,
+ NULL,
+ gsk_text_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskTextNode"), &node_info);
+ gsk_render_node_types[GSK_TEXT_NODE] = node_type;
+ g_assert (GSK_TYPE_TEXT_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_BLUR_NODE,
+ sizeof (GskBlurNode),
+ NULL,
+ gsk_blur_node_finalize,
+ gsk_blur_node_draw,
+ NULL,
+ gsk_blur_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskBlurNode"), &node_info);
+ gsk_render_node_types[GSK_BLUR_NODE] = node_type;
+ g_assert (GSK_TYPE_BLUR_NODE == node_type);
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_DEBUG_NODE,
+ sizeof (GskDebugNode),
+ NULL,
+ gsk_debug_node_finalize,
+ gsk_debug_node_draw,
+ gsk_debug_node_can_diff,
+ gsk_debug_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskDebugNode"), &node_info);
+ gsk_render_node_types[GSK_DEBUG_NODE] = node_type;
+ g_assert (GSK_TYPE_DEBUG_NODE == node_type);
+ }
+}
diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c
index 02959bce93..fcacb8b888 100644
--- a/gsk/gskrendernodeparser.c
+++ b/gsk/gskrendernodeparser.c
@@ -1973,9 +1973,9 @@ render_node_print (Printer *p,
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_LINEAR_GRADIENT_NODE:
{
- const guint n_stops = gsk_linear_gradient_node_get_n_color_stops (node);
- const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node);
- int i;
+ const gsize n_stops = gsk_linear_gradient_node_get_n_color_stops (node);
+ const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node, NULL);
+ gsize i;
if (gsk_render_node_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE)
start_node (p, "repeating-linear-gradient");
@@ -2229,7 +2229,7 @@ render_node_print (Printer *p,
case GSK_TEXT_NODE:
{
const guint n_glyphs = gsk_text_node_get_num_glyphs (node);
- const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node);
+ const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node, NULL);
const graphene_point_t *offset = gsk_text_node_get_offset (node);
const GdkRGBA *color = gsk_text_node_peek_color (node);
PangoFont *font = gsk_text_node_peek_font (node);
@@ -2449,7 +2449,7 @@ render_node_print (Printer *p,
break;
default:
- g_error ("Unhandled node: %s", node->node_class->type_name);
+ g_error ("Unhandled node: %s", g_type_name_from_instance ((GTypeInstance *) node));
break;
}
}
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index 83d01740a5..2ca03419e5 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.h
@@ -8,22 +8,30 @@ G_BEGIN_DECLS
typedef struct _GskRenderNodeClass GskRenderNodeClass;
-#define GSK_IS_RENDER_NODE_TYPE(node,type) (GSK_IS_RENDER_NODE (node) && (node)->node_class->node_type == (type))
+/* Keep this in sync with the GskRenderNodeType enumeration.
+ *
+ * We don't add an "n-types" value to avoid having to handle
+ * it in every single switch.
+ */
+#define GSK_RENDER_NODE_TYPE_N_TYPES (GSK_DEBUG_NODE + 1)
+
+#define GSK_IS_RENDER_NODE_TYPE(node,type) \
+ (G_TYPE_INSTANCE_GET_CLASS ((node), GSK_TYPE_RENDER_NODE, GskRenderNodeClass)->node_type == (type))
struct _GskRenderNode
{
- const GskRenderNodeClass *node_class;
+ GTypeInstance parent_instance;
- volatile int ref_count;
+ gatomicrefcount ref_count;
graphene_rect_t bounds;
};
struct _GskRenderNodeClass
{
+ GTypeClass parent_class;
+
GskRenderNodeType node_type;
- gsize struct_size;
- const char *type_name;
void (* finalize) (GskRenderNode *node);
void (* draw) (GskRenderNode *node,
@@ -35,18 +43,54 @@ struct _GskRenderNodeClass
cairo_region_t *region);
};
-GskRenderNode * gsk_render_node_new (const GskRenderNodeClass *node_class,
- gsize extra_size);
+/*< private >
+ * GskRenderNodeTypeInfo:
+ * @node_type: the render node type in the #GskRenderNodeType enumeration
+ * @instance_size: the size of the render node instance
+ * @instance_init: (nullable): the instance initialization function
+ * @finalize: (nullable): the instance finalization function; must chain up to the
+ * implementation of the parent class
+ * @draw: the function called by gsk_render_node_draw()
+ * @can_diff: (nullable): the function called by gsk_render_node_can_diff(); if
+ * unset, gsk_render_node_can_diff_true() will be used
+ * @diff: (nullable): the function called by gsk_render_node_diff(); if unset,
+ * gsk_render_node_diff_impossible() will be used
+ *
+ * A struction that contains the type information for a #GskRenderNode subclass,
+ * to be used by gsk_render_node_type_register_static().
+ */
+typedef struct
+{
+ GskRenderNodeType node_type;
+
+ gsize instance_size;
+
+ void (* instance_init) (GskRenderNode *node);
+ void (* finalize) (GskRenderNode *node);
+ void (* draw) (GskRenderNode *node,
+ cairo_t *cr);
+ gboolean (* can_diff) (const GskRenderNode *node1,
+ const GskRenderNode *node2);
+ void (* diff) (GskRenderNode *node1,
+ GskRenderNode *node2,
+ cairo_region_t *region);
+} GskRenderNodeTypeInfo;
+
+void gsk_render_node_init_types (void);
+
+GType gsk_render_node_type_register_static (const char *node_name,
+ const GskRenderNodeTypeInfo *node_info);
-gboolean gsk_render_node_can_diff (const GskRenderNode *node1,
- const GskRenderNode *node2) G_GNUC_PURE;
-void gsk_render_node_diff (GskRenderNode *node1,
- GskRenderNode *node2,
- cairo_region_t *region);
-void gsk_render_node_diff_impossible (GskRenderNode *node1,
- GskRenderNode *node2,
- cairo_region_t *region);
+gpointer gsk_render_node_alloc (GskRenderNodeType node_type);
+gboolean gsk_render_node_can_diff (const GskRenderNode *node1,
+ const GskRenderNode *node2) G_GNUC_PURE;
+void gsk_render_node_diff (GskRenderNode *node1,
+ GskRenderNode *node2,
+ cairo_region_t *region);
+void gsk_render_node_diff_impossible (GskRenderNode *node1,
+ GskRenderNode *node2,
+ cairo_region_t *region);
G_END_DECLS
diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c
index fb19d8d04d..c622a3b14b 100644
--- a/gsk/vulkan/gskvulkanrenderpass.c
+++ b/gsk/vulkan/gskvulkanrenderpass.c
@@ -258,7 +258,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
return;
case GSK_SHADOW_NODE:
default:
- FALLBACK ("Unsupported node '%s'", node->node_class->type_name);
+ FALLBACK ("Unsupported node '%s'", g_type_name_from_instance ((GTypeInstance *) node));
case GSK_REPEAT_NODE:
if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
@@ -346,7 +346,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
case GSK_TEXT_NODE:
{
const PangoFont *font = gsk_text_node_peek_font (node);
- const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node);
+ const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node, NULL);
guint num_glyphs = gsk_text_node_get_num_glyphs (node);
gboolean has_color_glyphs = gsk_text_node_has_color_glyphs (node);
int i;
@@ -817,7 +817,7 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self,
g_message ("Upload op=%s, node %s[%p], bounds %gx%g",
op->type == GSK_VULKAN_OP_FALLBACK_CLIP ? "fallback-clip" :
(op->type == GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP ? "fallback-rounded-clip" : "fallback"),
- node->node_class->type_name, node,
+ g_type_name_from_instance ((GTypeInstance *) node), node,
ceil (node->bounds.size.width),
ceil (node->bounds.size.height)));
#ifdef G_ENABLE_DEBUG
@@ -1195,7 +1195,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
&op->text.node->bounds,
(PangoFont *)gsk_text_node_peek_font (op->text.node),
gsk_text_node_get_num_glyphs (op->text.node),
- gsk_text_node_peek_glyphs (op->text.node),
+ gsk_text_node_peek_glyphs (op->text.node, NULL),
gsk_text_node_peek_color (op->text.node),
gsk_text_node_get_offset (op->text.node),
op->text.start_glyph,
@@ -1214,7 +1214,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
&op->text.node->bounds,
(PangoFont *)gsk_text_node_peek_font (op->text.node),
gsk_text_node_get_num_glyphs (op->text.node),
- gsk_text_node_peek_glyphs (op->text.node),
+ gsk_text_node_peek_glyphs (op->text.node, NULL),
gsk_text_node_get_offset (op->text.node),
op->text.start_glyph,
op->text.num_glyphs,
@@ -1244,7 +1244,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
gsk_linear_gradient_node_peek_end (op->render.node),
gsk_render_node_get_node_type (op->render.node) == GSK_REPEATING_LINEAR_GRADIENT_NODE,
gsk_linear_gradient_node_get_n_color_stops (op->render.node),
- gsk_linear_gradient_node_peek_color_stops (op->render.node));
+ gsk_linear_gradient_node_peek_color_stops (op->render.node, NULL));
n_bytes += op->render.vertex_count;
}
break;