summaryrefslogtreecommitdiff
path: root/gsk/gskrendernodeparser.c
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2023-03-28 23:47:49 +0200
committerBenjamin Otte <otte@redhat.com>2023-03-29 03:53:52 +0200
commit0d6a6a5997ddc5c0b674c1c2c3414093ad57cc42 (patch)
treec0e79d3416165fb31d5e5b247f75611b528a6b8a /gsk/gskrendernodeparser.c
parent5a0c4de07f75d89e5b84f9dcade7b17c019433d8 (diff)
downloadgtk+-0d6a6a5997ddc5c0b674c1c2c3414093ad57cc42.tar.gz
rendernodeparser: Detect duplicates and print them by name
If we encounter a node or texture the 1st time and they are going to be used again, give them a name. Then, when encountering them again, print them by name instead of duplicating them.
Diffstat (limited to 'gsk/gskrendernodeparser.c')
-rw-r--r--gsk/gskrendernodeparser.c249
1 files changed, 219 insertions, 30 deletions
diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c
index 07825fd56e..522bacbf6e 100644
--- a/gsk/gskrendernodeparser.c
+++ b/gsk/gskrendernodeparser.c
@@ -2292,13 +2292,152 @@ typedef struct
{
int indentation_level;
GString *str;
+ GHashTable *named_nodes;
+ gsize named_node_counter;
+ GHashTable *named_textures;
+ gsize named_texture_counter;
} Printer;
static void
-printer_init (Printer *self)
+printer_init_check_texture (Printer *printer,
+ GdkTexture *texture)
+{
+ gpointer name;
+
+ if (!g_hash_table_lookup_extended (printer->named_textures, texture, NULL, &name))
+ g_hash_table_insert (printer->named_textures, texture, NULL);
+ else if (name == NULL)
+ g_hash_table_insert (printer->named_textures, texture, g_strdup (""));
+}
+
+static void
+printer_init_duplicates_for_node (Printer *printer,
+ GskRenderNode *node)
+{
+ gpointer name;
+
+ if (!g_hash_table_lookup_extended (printer->named_nodes, node, NULL, &name))
+ g_hash_table_insert (printer->named_nodes, node, NULL);
+ else if (name == NULL)
+ g_hash_table_insert (printer->named_nodes, node, g_strdup (""));
+
+ switch (gsk_render_node_get_node_type (node))
+ {
+ case GSK_CAIRO_NODE:
+ case GSK_TEXT_NODE:
+ case GSK_COLOR_NODE:
+ case GSK_LINEAR_GRADIENT_NODE:
+ case GSK_REPEATING_LINEAR_GRADIENT_NODE:
+ case GSK_RADIAL_GRADIENT_NODE:
+ case GSK_REPEATING_RADIAL_GRADIENT_NODE:
+ case GSK_CONIC_GRADIENT_NODE:
+ case GSK_BORDER_NODE:
+ case GSK_INSET_SHADOW_NODE:
+ case GSK_OUTSET_SHADOW_NODE:
+ /* no children */
+ break;
+
+ case GSK_TEXTURE_NODE:
+ printer_init_check_texture (printer, gsk_texture_node_get_texture (node));
+ break;
+
+ case GSK_TEXTURE_SCALE_NODE:
+ printer_init_check_texture (printer, gsk_texture_scale_node_get_texture (node));
+ break;
+
+ case GSK_TRANSFORM_NODE:
+ printer_init_duplicates_for_node (printer, gsk_transform_node_get_child (node));
+ break;
+
+ case GSK_OPACITY_NODE:
+ printer_init_duplicates_for_node (printer, gsk_opacity_node_get_child (node));
+ break;
+
+ case GSK_COLOR_MATRIX_NODE:
+ printer_init_duplicates_for_node (printer, gsk_color_matrix_node_get_child (node));
+ break;
+
+ case GSK_BLUR_NODE:
+ printer_init_duplicates_for_node (printer, gsk_blur_node_get_child (node));
+ break;
+
+ case GSK_REPEAT_NODE:
+ printer_init_duplicates_for_node (printer, gsk_repeat_node_get_child (node));
+ break;
+
+ case GSK_CLIP_NODE:
+ printer_init_duplicates_for_node (printer, gsk_clip_node_get_child (node));
+ break;
+
+ case GSK_ROUNDED_CLIP_NODE:
+ printer_init_duplicates_for_node (printer, gsk_rounded_clip_node_get_child (node));
+ break;
+
+ case GSK_SHADOW_NODE:
+ printer_init_duplicates_for_node (printer, gsk_shadow_node_get_child (node));
+ break;
+
+ case GSK_DEBUG_NODE:
+ printer_init_duplicates_for_node (printer, gsk_debug_node_get_child (node));
+ break;
+
+ case GSK_BLEND_NODE:
+ printer_init_duplicates_for_node (printer, gsk_blend_node_get_bottom_child (node));
+ printer_init_duplicates_for_node (printer, gsk_blend_node_get_top_child (node));
+ break;
+
+ case GSK_MASK_NODE:
+ printer_init_duplicates_for_node (printer, gsk_mask_node_get_source (node));
+ printer_init_duplicates_for_node (printer, gsk_mask_node_get_mask (node));
+ break;
+
+ case GSK_CROSS_FADE_NODE:
+ printer_init_duplicates_for_node (printer, gsk_cross_fade_node_get_start_child (node));
+ printer_init_duplicates_for_node (printer, gsk_cross_fade_node_get_end_child (node));
+ break;
+
+ case GSK_GL_SHADER_NODE:
+ {
+ guint i;
+
+ for (i = 0; i < gsk_gl_shader_node_get_n_children (node); i++)
+ {
+ printer_init_duplicates_for_node (printer, gsk_gl_shader_node_get_child (node, i));
+ }
+ }
+ break;
+
+ case GSK_CONTAINER_NODE:
+ {
+ guint i;
+
+ for (i = 0; i < gsk_container_node_get_n_children (node); i++)
+ {
+ printer_init_duplicates_for_node (printer, gsk_container_node_get_child (node, i));
+ }
+ }
+ break;
+
+ default:
+ case GSK_NOT_A_RENDER_NODE:
+ g_assert_not_reached ();
+ break;
+
+ }
+}
+
+static void
+printer_init (Printer *self,
+ GskRenderNode *node)
{
self->indentation_level = 0;
self->str = g_string_new (NULL);
+ self->named_nodes = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+ self->named_node_counter = 0;
+ self->named_textures = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+ self->named_texture_counter = 0;
+
+ printer_init_duplicates_for_node (self, node);
}
#define IDENT_LEVEL 2 /* Spaces per level */
@@ -2312,9 +2451,16 @@ _indent (Printer *self)
static void
start_node (Printer *self,
+ const char *node_type,
const char *node_name)
{
- g_string_append_printf (self->str, "%s {\n", node_name);
+ g_string_append_printf (self->str, "%s ", node_type);
+ if (node_name)
+ {
+ gtk_css_print_string (self->str, node_name, FALSE);
+ g_string_append_c (self->str, ' ');
+ }
+ g_string_append_printf (self->str, "{\n");
self->indentation_level ++;
}
@@ -2668,11 +2814,33 @@ append_texture_param (Printer *p,
{
GBytes *bytes;
char *b64;
+ const char *texture_name;
_indent (p);
g_string_append_printf (p->str, "%s: ", param_name);
+ texture_name = g_hash_table_lookup (p->named_textures, texture);
+ if (texture_name == NULL)
+ {
+ /* nothing to do here, texture is unique */
+ }
+ else if (texture_name[0])
+ {
+ /* texture has been named already */
+ gtk_css_print_string (p->str, texture_name, TRUE);
+ g_string_append (p->str, ";\n");
+ return;
+ }
+ else
+ {
+ /* texture needs a name */
+ char *new_name = g_strdup_printf ("texture%zu", ++p->named_texture_counter);
+ gtk_css_print_string (p->str, new_name, TRUE);
+ g_string_append_c (p->str, ' ');
+ g_hash_table_insert (p->named_textures, texture, new_name);
+ }
+
switch (gdk_texture_get_format (texture))
{
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
@@ -2801,6 +2969,27 @@ render_node_print (Printer *p,
GskRenderNode *node)
{
char *b64;
+ const char *node_name;
+
+ node_name = g_hash_table_lookup (p->named_nodes, node);
+ if (node_name == NULL)
+ {
+ /* nothing to do here, node is unique */
+ }
+ else if (node_name[0])
+ {
+ /* node has been named already */
+ gtk_css_print_string (p->str, node_name, TRUE);
+ g_string_append (p->str, ";\n");
+ return;
+ }
+ else
+ {
+ /* node needs a name */
+ char *new_name = g_strdup_printf ("node%zu", ++p->named_node_counter);
+ g_hash_table_insert (p->named_nodes, node, new_name);
+ node_name = new_name;
+ }
switch (gsk_render_node_get_node_type (node))
{
@@ -2808,7 +2997,7 @@ render_node_print (Printer *p,
{
guint i;
- start_node (p, "container");
+ start_node (p, "container", node_name);
for (i = 0; i < gsk_container_node_get_n_children (node); i ++)
{
GskRenderNode *child = gsk_container_node_get_child (node, i);
@@ -2823,7 +3012,7 @@ render_node_print (Printer *p,
case GSK_COLOR_NODE:
{
- start_node (p, "color");
+ start_node (p, "color", node_name);
append_rect_param (p, "bounds", &node->bounds);
append_rgba_param (p, "color", gsk_color_node_get_color (node));
end_node (p);
@@ -2832,7 +3021,7 @@ render_node_print (Printer *p,
case GSK_CROSS_FADE_NODE:
{
- start_node (p, "cross-fade");
+ start_node (p, "cross-fade", node_name);
append_float_param (p, "progress", gsk_cross_fade_node_get_progress (node), 0.5f);
append_node_param (p, "start", gsk_cross_fade_node_get_start_child (node));
@@ -2846,9 +3035,9 @@ render_node_print (Printer *p,
case GSK_LINEAR_GRADIENT_NODE:
{
if (gsk_render_node_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE)
- start_node (p, "repeating-linear-gradient");
+ start_node (p, "repeating-linear-gradient", node_name);
else
- start_node (p, "linear-gradient");
+ start_node (p, "linear-gradient", node_name);
append_rect_param (p, "bounds", &node->bounds);
append_point_param (p, "start", gsk_linear_gradient_node_get_start (node));
@@ -2864,9 +3053,9 @@ render_node_print (Printer *p,
case GSK_RADIAL_GRADIENT_NODE:
{
if (gsk_render_node_get_node_type (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE)
- start_node (p, "repeating-radial-gradient");
+ start_node (p, "repeating-radial-gradient", node_name);
else
- start_node (p, "radial-gradient");
+ start_node (p, "radial-gradient", node_name);
append_rect_param (p, "bounds", &node->bounds);
append_point_param (p, "center", gsk_radial_gradient_node_get_center (node));
@@ -2884,7 +3073,7 @@ render_node_print (Printer *p,
case GSK_CONIC_GRADIENT_NODE:
{
- start_node (p, "conic-gradient");
+ start_node (p, "conic-gradient", node_name);
append_rect_param (p, "bounds", &node->bounds);
append_point_param (p, "center", gsk_conic_gradient_node_get_center (node));
@@ -2899,7 +3088,7 @@ render_node_print (Printer *p,
case GSK_OPACITY_NODE:
{
- start_node (p, "opacity");
+ start_node (p, "opacity", node_name);
append_float_param (p, "opacity", gsk_opacity_node_get_opacity (node), 0.5f);
append_node_param (p, "child", gsk_opacity_node_get_child (node));
@@ -2912,7 +3101,7 @@ render_node_print (Printer *p,
{
const GdkRGBA *color = gsk_outset_shadow_node_get_color (node);
- start_node (p, "outset-shadow");
+ start_node (p, "outset-shadow", node_name);
append_float_param (p, "blur", gsk_outset_shadow_node_get_blur_radius (node), 0.0f);
if (!gdk_rgba_equal (color, &GDK_RGBA("000")))
@@ -2928,7 +3117,7 @@ render_node_print (Printer *p,
case GSK_CLIP_NODE:
{
- start_node (p, "clip");
+ start_node (p, "clip", node_name);
append_rect_param (p, "clip", gsk_clip_node_get_clip (node));
append_node_param (p, "child", gsk_clip_node_get_child (node));
@@ -2939,7 +3128,7 @@ render_node_print (Printer *p,
case GSK_ROUNDED_CLIP_NODE:
{
- start_node (p, "rounded-clip");
+ start_node (p, "rounded-clip", node_name);
append_rounded_rect_param (p, "clip", gsk_rounded_clip_node_get_clip (node));
append_node_param (p, "child", gsk_rounded_clip_node_get_child (node));
@@ -2952,7 +3141,7 @@ render_node_print (Printer *p,
case GSK_TRANSFORM_NODE:
{
GskTransform *transform = gsk_transform_node_get_transform (node);
- start_node (p, "transform");
+ start_node (p, "transform", node_name);
if (gsk_transform_get_category (transform) != GSK_TRANSFORM_CATEGORY_IDENTITY)
append_transform_param (p, "transform", transform);
@@ -2964,7 +3153,7 @@ render_node_print (Printer *p,
case GSK_COLOR_MATRIX_NODE:
{
- start_node (p, "color-matrix");
+ start_node (p, "color-matrix", node_name);
if (!graphene_matrix_is_identity (gsk_color_matrix_node_get_color_matrix (node)))
append_matrix_param (p, "matrix", gsk_color_matrix_node_get_color_matrix (node));
@@ -2981,7 +3170,7 @@ render_node_print (Printer *p,
const GdkRGBA *colors = gsk_border_node_get_colors (node);
const float *widths = gsk_border_node_get_widths (node);
guint i, n;
- start_node (p, "border");
+ start_node (p, "border", node_name);
if (!gdk_rgba_equal (&colors[3], &colors[1]))
n = 4;
@@ -3042,7 +3231,7 @@ render_node_print (Printer *p,
const guint n_shadows = gsk_shadow_node_get_n_shadows (node);
int i;
- start_node (p, "shadow");
+ start_node (p, "shadow", node_name);
_indent (p);
g_string_append (p->str, "shadows: ");
@@ -3080,7 +3269,7 @@ render_node_print (Printer *p,
case GSK_INSET_SHADOW_NODE:
{
const GdkRGBA *color = gsk_inset_shadow_node_get_color (node);
- start_node (p, "inset-shadow");
+ start_node (p, "inset-shadow", node_name);
append_float_param (p, "blur", gsk_inset_shadow_node_get_blur_radius (node), 0.0f);
if (!gdk_rgba_equal (color, &GDK_RGBA("000")))
@@ -3096,7 +3285,7 @@ render_node_print (Printer *p,
case GSK_TEXTURE_NODE:
{
- start_node (p, "texture");
+ start_node (p, "texture", node_name);
append_rect_param (p, "bounds", &node->bounds);
append_texture_param (p, "texture", gsk_texture_node_get_texture (node));
@@ -3109,7 +3298,7 @@ render_node_print (Printer *p,
{
GskScalingFilter filter = gsk_texture_scale_node_get_filter (node);
- start_node (p, "texture-scale");
+ start_node (p, "texture-scale", node_name);
append_rect_param (p, "bounds", &node->bounds);
if (filter != GSK_SCALING_FILTER_LINEAR)
@@ -3138,7 +3327,7 @@ render_node_print (Printer *p,
PangoFontDescription *desc;
char *font_name;
- start_node (p, "text");
+ start_node (p, "text", node_name);
if (!gdk_rgba_equal (color, &GDK_RGBA("000000")))
append_rgba_param (p, "color", color);
@@ -3169,7 +3358,7 @@ render_node_print (Printer *p,
{
const char *message = gsk_debug_node_get_message (node);
- start_node (p, "debug");
+ start_node (p, "debug", node_name);
/* TODO: We potentially need to escape certain characters in the message */
if (message)
@@ -3185,7 +3374,7 @@ render_node_print (Printer *p,
case GSK_BLUR_NODE:
{
- start_node (p, "blur");
+ start_node (p, "blur", node_name);
append_float_param (p, "blur", gsk_blur_node_get_radius (node), 1.0f);
append_node_param (p, "child", gsk_blur_node_get_child (node));
@@ -3199,7 +3388,7 @@ render_node_print (Printer *p,
GskGLShader *shader = gsk_gl_shader_node_get_shader (node);
GBytes *args = gsk_gl_shader_node_get_args (node);
- start_node (p, "glshader");
+ start_node (p, "glshader", node_name);
append_rect_param (p, "bounds", &node->bounds);
@@ -3317,7 +3506,7 @@ render_node_print (Printer *p,
GskRenderNode *child = gsk_repeat_node_get_child (node);
const graphene_rect_t *child_bounds = gsk_repeat_node_get_child_bounds (node);
- start_node (p, "repeat");
+ start_node (p, "repeat", node_name);
if (!graphene_rect_equal (&node->bounds, &child->bounds))
append_rect_param (p, "bounds", &node->bounds);
@@ -3333,7 +3522,7 @@ render_node_print (Printer *p,
{
GskBlendMode mode = gsk_blend_node_get_blend_mode (node);
- start_node (p, "blend");
+ start_node (p, "blend", node_name);
if (mode != GSK_BLEND_MODE_DEFAULT)
{
@@ -3351,7 +3540,7 @@ render_node_print (Printer *p,
{
GskMaskMode mode = gsk_mask_node_get_mask_mode (node);
- start_node (p, "mask");
+ start_node (p, "mask", node_name);
if (mode != GSK_MASK_MODE_ALPHA)
{
@@ -3374,7 +3563,7 @@ render_node_print (Printer *p,
cairo_surface_t *surface = gsk_cairo_node_get_surface (node);
GByteArray *array;
- start_node (p, "cairo");
+ start_node (p, "cairo", node_name);
append_rect_param (p, "bounds", &node->bounds);
if (surface != NULL)
@@ -3453,7 +3642,7 @@ gsk_render_node_serialize (GskRenderNode *node)
{
Printer p;
- printer_init (&p);
+ printer_init (&p, node);
if (gsk_render_node_get_node_type (node) == GSK_CONTAINER_NODE)
{