rendernodeparser: Add support for reusing textures
authorBenjamin Otte <otte@redhat.com>
Tue, 28 Mar 2023 19:54:26 +0000 (21:54 +0200)
committerBenjamin Otte <otte@redhat.com>
Wed, 29 Mar 2023 01:53:52 +0000 (03:53 +0200)
We extend the syntax for textures from just:
  <url>
to
  [<string>] <url>
  <string>
where the first defines a named texture while the second references a
texture.
Or to give an example:
  texture {
    bounds: 0 0 10 10;
    texture: "foo" url("foo.png");
  }
  texture {
    bounds: 20 0 10 10;
    texture: "foo";
  }
This will draw the texture "foo.png" twice, once at (0,0) and once at
(20,0).

The intended use for this is both shortening generated node files as
well as allowing to write tests that reuse textures, in particular when
mixing them in texture and texture-scale nodes.

gsk/gskrendernodeparser.c

index c67ab8114884e118d7de10c4900186447c4246fe..c74d16660a4a0e82df57badf784cce31ef8397e3 100644 (file)
@@ -115,8 +115,41 @@ parse_texture (GtkCssParser *parser,
 {
   GdkTexture *texture;
   GError *error = NULL;
+  const GtkCssToken *token;
   GtkCssLocation start_location;
-  char *url, *scheme;
+  char *url, *scheme, *texture_name;
+
+  token = gtk_css_parser_get_token (parser);
+  if (gtk_css_token_is (token, GTK_CSS_TOKEN_STRING))
+    {
+      texture_name = gtk_css_parser_consume_string (parser);
+
+      if (context->named_textures)
+        texture = g_hash_table_lookup (context->named_textures, texture_name);
+      else
+        texture = NULL;
+
+      if (texture)
+        {
+          *(GdkTexture **) out_data = g_object_ref (texture);
+          g_free (texture_name);
+          return TRUE;
+        }
+      else if (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF))
+        {
+          gtk_css_parser_error_value (parser, "No texture named \"%s\"", texture_name);
+          g_free (texture_name);
+          return FALSE;
+        }
+
+      if (context->named_textures && g_hash_table_lookup (context->named_textures, texture_name))
+        {
+          gtk_css_parser_error_value (parser, "A texture named \"%s\" already exists.", texture_name);
+          g_clear_pointer (&texture_name, g_free);
+        }
+    }
+  else
+    texture_name = NULL;
 
   start_location = *gtk_css_parser_get_start_location (parser);
   url = gtk_css_parser_consume_url (parser);
@@ -176,6 +209,14 @@ parse_texture (GtkCssParser *parser,
       return FALSE;
     }
 
+  if (texture_name)
+    {
+      if (context->named_textures == NULL)
+        context->named_textures = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                         g_free, g_object_unref);
+      g_hash_table_insert (context->named_textures, texture_name, g_object_ref (texture));
+    }
+
   *(GdkTexture **) out_data = texture;
   return TRUE;
 }