[gtk] rendernodeparser: Parse Cairo nodes



commit 928c85ccc390bcd0285609373ea7859cfe072f10
Author: Benjamin Otte <otte redhat com>
Date:   Sun May 26 00:50:13 2019 +0200

    rendernodeparser: Parse Cairo nodes
    
    We also print the script, but we don't parse it yet.

 gsk/gskrendernode.h                           |   2 +-
 gsk/gskrendernodeimpl.c                       |   2 +-
 gsk/gskrendernodeparser.c                     | 138 +++++++++++++++++++++-----
 testsuite/gsk/compare/empty-cairo.node        |   1 +
 testsuite/gsk/compare/empty-cairo.png         | Bin 0 -> 153 bytes
 testsuite/gsk/meson.build                     |   3 +
 testsuite/gsk/nodeparser/empty-cairo.node     |   1 +
 testsuite/gsk/nodeparser/empty-cairo.ref.node |   5 +
 8 files changed, 126 insertions(+), 26 deletions(-)
---
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index cdb59a46f4..79f0c6a059 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -189,7 +189,7 @@ GskRenderNode *         gsk_cairo_node_new                      (const graphene_
 GDK_AVAILABLE_IN_ALL
 cairo_t *               gsk_cairo_node_get_draw_context         (GskRenderNode            *node);
 GDK_AVAILABLE_IN_ALL
-const cairo_surface_t * gsk_cairo_node_peek_surface             (GskRenderNode            *node);
+cairo_surface_t *       gsk_cairo_node_peek_surface             (GskRenderNode            *node);
 
 GDK_AVAILABLE_IN_ALL
 GskRenderNode *         gsk_container_node_new                  (GskRenderNode           **children,
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index ec66c7f14b..32e5d57827 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -1582,7 +1582,7 @@ static const GskRenderNodeClass GSK_CAIRO_NODE_CLASS = {
   gsk_render_node_diff_impossible,
 };
 
-const cairo_surface_t *
+cairo_surface_t *
 gsk_cairo_node_peek_surface (GskRenderNode *node)
 {
   GskCairoNode *self = (GskCairoNode *) node;
diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c
index ab7b3bd2a8..937e7d796f 100644
--- a/gsk/gskrendernodeparser.c
+++ b/gsk/gskrendernodeparser.c
@@ -33,6 +33,10 @@
 #include "gtk/css/gtkcssdataurlprivate.h"
 #include "gtk/css/gtkcssparserprivate.h"
 
+#ifdef CAIRO_HAS_SCRIPT_SURFACE
+#include <cairo-script.h>
+#endif
+
 typedef struct _Declaration Declaration;
 
 struct _Declaration
@@ -768,6 +772,30 @@ parse_declarations (GtkCssParser      *parser,
   return parsed;
 }
 
+static GdkTexture *
+create_default_texture (void)
+{
+  static const guint32 pixels[100] = {
+    0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0,
+    0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0,
+    0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0,
+    0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0,
+    0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC,
+    0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC,
+    0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC,
+    0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC,
+    0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC };
+  GBytes *bytes;
+  GdkTexture *texture;
+
+  bytes = g_bytes_new_static ((guchar *) pixels, 400);
+  texture = gdk_memory_texture_new (10, 10, GDK_MEMORY_DEFAULT, bytes, 40);
+  g_bytes_unref (bytes);
+
+  return texture;
+}
+
 static GskRenderNode *
 create_default_render_node (void)
 {
@@ -873,23 +901,7 @@ parse_texture_node (GtkCssParser *parser)
   parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
 
   if (texture == NULL)
-    {
-      static const guint32 pixels[100] = {
-        0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0,
-        0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0,
-        0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0,
-        0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0,
-        0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC,
-        0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC,
-        0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC,
-        0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC,
-        0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC };
-      GBytes *bytes = g_bytes_new_static ((guchar *) pixels, 400);
-
-      texture = gdk_memory_texture_new (10, 10, GDK_MEMORY_DEFAULT, bytes, 40);
-      g_bytes_unref (bytes);
-    }
+    texture = create_default_texture ();
 
   node = gsk_texture_node_new (texture, &bounds);
   g_object_unref (texture);
@@ -897,6 +909,44 @@ parse_texture_node (GtkCssParser *parser)
   return node;
 }
 
+static GskRenderNode *
+parse_cairo_node (GtkCssParser *parser)
+{
+  graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
+  GdkTexture *pixels = NULL;
+  const Declaration declarations[] = {
+    { "bounds", parse_rect, NULL, &bounds },
+    { "pixels", parse_texture, clear_texture, &pixels }
+  };
+  GskRenderNode *node;
+  cairo_t *cr;
+
+  parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
+
+  node = gsk_cairo_node_new (&bounds);
+  
+  cr = gsk_cairo_node_get_draw_context (node);
+
+  if (pixels != NULL)
+    {
+      cairo_surface_t *surface;
+      surface = gdk_texture_download_surface (pixels);
+      cairo_set_source_surface (cr, surface, 0, 0);
+      cairo_paint (cr);
+      cairo_surface_destroy (surface);
+    }
+  else
+    {
+      gdk_cairo_set_source_rgba (cr, &GDK_RGBA ("FF00CC"));
+      cairo_paint (cr);
+    }
+
+  cairo_destroy (cr);
+  g_clear_object (&pixels);
+
+  return node;
+}
+
 static GskRenderNode *
 parse_outset_shadow_node (GtkCssParser *parser)
 {
@@ -1325,10 +1375,7 @@ parse_node (GtkCssParser *parser,
     { "debug", parse_debug_node },
     { "blend", parse_blend_node },
     { "repeat", parse_repeat_node },
-#if 0
     { "cairo", parse_cairo_node },
-#endif
-
   };
   GskRenderNode **node_p = out_node;
   guint i;
@@ -1696,9 +1743,9 @@ append_node_param (Printer       *p,
 }
 
 static cairo_status_t
-surface_write (void                *closure,
-               const unsigned char *data,
-               unsigned int         length)
+cairo_write_array (void                *closure,
+                   const unsigned char *data,
+                   unsigned int         length)
 {
   g_byte_array_append (closure, data, length);
 
@@ -1988,7 +2035,7 @@ render_node_print (Printer       *p,
 
         surface = gdk_texture_download_surface (texture);
         array = g_byte_array_new ();
-        cairo_surface_write_to_png_stream (surface, surface_write, array);
+        cairo_surface_write_to_png_stream (surface, cairo_write_array, array);
         b64 = g_base64_encode (array->data, array->len);
 
         _indent (p);
@@ -2170,6 +2217,49 @@ render_node_print (Printer       *p,
       break;
 
     case GSK_CAIRO_NODE:
+      {
+        cairo_surface_t *surface = gsk_cairo_node_peek_surface (node);
+        GByteArray *array;
+        char *b64;
+
+        start_node (p, "cairo");
+        append_rect_param (p, "bounds", &node->bounds);
+
+        array = g_byte_array_new ();
+        cairo_surface_write_to_png_stream (surface, cairo_write_array, array);
+        b64 = g_base64_encode (array->data, array->len);
+
+        _indent (p);
+        g_string_append_printf (p->str, "pixels: url(\"data:image/png;base64,%s\");\n", b64);
+
+        g_free (b64);
+        g_byte_array_free (array, TRUE);
+
+#ifdef CAIRO_HAS_SCRIPT_SURFACE
+        if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_RECORDING)
+          {
+            cairo_device_t *script;
+
+            array = g_byte_array_new ();
+            script = cairo_script_create_for_stream (cairo_write_array, array);
+
+            if (cairo_script_from_recording_surface (script, surface) == CAIRO_STATUS_SUCCESS)
+              {
+                b64 = g_base64_encode (array->data, array->len);
+                _indent (p);
+                g_string_append_printf (p->str, "script: url(\"data:;base64,%s\");\n", b64);
+                g_free (b64);
+              }
+
+          cairo_device_destroy (script);
+          g_byte_array_free (array, TRUE);
+        }
+#endif
+
+        end_node (p);
+      }
+      break;
+
     case GSK_REPEATING_LINEAR_GRADIENT_NODE:
     default:
       g_error ("Unhandled node: %s", node->node_class->type_name);
diff --git a/testsuite/gsk/compare/empty-cairo.node b/testsuite/gsk/compare/empty-cairo.node
new file mode 100644
index 0000000000..1987994306
--- /dev/null
+++ b/testsuite/gsk/compare/empty-cairo.node
@@ -0,0 +1 @@
+cairo { }
diff --git a/testsuite/gsk/compare/empty-cairo.png b/testsuite/gsk/compare/empty-cairo.png
new file mode 100644
index 0000000000..3a032a391b
Binary files /dev/null and b/testsuite/gsk/compare/empty-cairo.png differ
diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build
index 4751dfd537..4f469603a9 100644
--- a/testsuite/gsk/meson.build
+++ b/testsuite/gsk/meson.build
@@ -27,6 +27,7 @@ compare_render_tests = [
   'empty-blend',
   'empty-blur',
   'empty-border',
+  'empty-cairo',
   'empty-clip',
   'empty-color',
   'empty-color-matrix',
@@ -101,6 +102,8 @@ node_parser_tests = [
   'empty-blur.ref.node',
   'empty-border.node',
   'empty-border.ref.node',
+  'empty-cairo.node',
+  'empty-cairo.ref.node',
   'empty-clip.node',
   'empty-clip.ref.node',
   'empty-color.node',
diff --git a/testsuite/gsk/nodeparser/empty-cairo.node b/testsuite/gsk/nodeparser/empty-cairo.node
new file mode 100644
index 0000000000..1987994306
--- /dev/null
+++ b/testsuite/gsk/nodeparser/empty-cairo.node
@@ -0,0 +1 @@
+cairo { }
diff --git a/testsuite/gsk/nodeparser/empty-cairo.ref.node b/testsuite/gsk/nodeparser/empty-cairo.ref.node
new file mode 100644
index 0000000000..4dca846961
--- /dev/null
+++ b/testsuite/gsk/nodeparser/empty-cairo.ref.node
@@ -0,0 +1,5 @@
+cairo {
+  bounds: 0 0 50 50;
+  pixels: 
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAABmJLR0QA/wD/AP+gvaeTAAAATklEQVRYhe3OMQHAIADAMJh/aXgCA3t6wZEoyNxjjfd8twP/tAqtQqvQKrQKrUKr0Cq0Cq1Cq9AqtAqtQqvQKrQKrUKr0Cq0Cq1Cq9AqDsEHAi9RKkB7AAAAAElFTkSuQmCC");
+  script: 
url("data:;base64,JSFDYWlyb1NjcmlwdAo8PCAvY29udGVudCAvL0NPTE9SX0FMUEhBIC93aWR0aCA1MCAvaGVpZ2h0IDUwID4+IHN1cmZhY2UgY29udGV4dAoxIDAgMC44IHJnYiBzZXQtc291cmNlCnBhaW50CnBvcAo=");
+}


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