[gtk/wip/otte/lottie: 7/27] gsk: Add GskStrokeNode




commit 2bab0e62982050b75c6e9fe51f00c48459799709
Author: Benjamin Otte <otte redhat com>
Date:   Wed Nov 11 07:36:04 2020 +0100

    gsk: Add GskStrokeNode

 gsk/broadway/gskbroadwayrenderer.c |   2 +
 gsk/gl/gskglrenderer.c             |   1 +
 gsk/gsk.h                          |   1 +
 gsk/gskenums.h                     |   1 +
 gsk/gskrendernode.h                |  15 ++++
 gsk/gskrendernodeimpl.c            | 180 +++++++++++++++++++++++++++++++++++++
 gsk/gskrendernodeparser.c          |  22 ++++-
 gsk/gskstroke.c                    | 111 +++++++++++++++++++++++
 gsk/gskstroke.h                    |  56 ++++++++++++
 gsk/gskstrokeprivate.h             |  48 ++++++++++
 gsk/gsktypes.h                     |   1 +
 gsk/meson.build                    |   2 +
 gsk/vulkan/gskvulkanrenderpass.c   |   1 +
 gtk/inspector/recorder.c           |  25 ++++++
 14 files changed, 465 insertions(+), 1 deletion(-)
---
diff --git a/gsk/broadway/gskbroadwayrenderer.c b/gsk/broadway/gskbroadwayrenderer.c
index d45ea9b8e5..41e095f635 100644
--- a/gsk/broadway/gskbroadwayrenderer.c
+++ b/gsk/broadway/gskbroadwayrenderer.c
@@ -269,6 +269,7 @@ collect_reused_child_nodes (GskRenderer *renderer,
     case GSK_CROSS_FADE_NODE:
     case GSK_BLUR_NODE:
     case GSK_FILL_NODE:
+    case GSK_STROKE_NODE:
 
     default:
 
@@ -855,6 +856,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
     case GSK_BLUR_NODE:
     case GSK_GL_SHADER_NODE:
     case GSK_FILL_NODE:
+    case GSK_STROKE_NODE:
     default:
       break; /* Fallback */
     }
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index d92fa2984e..c9dae4f8b6 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -3724,6 +3724,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer   *self,
     case GSK_REPEATING_LINEAR_GRADIENT_NODE:
     case GSK_REPEATING_RADIAL_GRADIENT_NODE:
     case GSK_FILL_NODE:
+    case GSK_STROKE_NODE:
     case GSK_CAIRO_NODE:
     default:
       {
diff --git a/gsk/gsk.h b/gsk/gsk.h
index 2adfa3aec0..a5b530f291 100644
--- a/gsk/gsk.h
+++ b/gsk/gsk.h
@@ -26,6 +26,7 @@
 #include <gsk/gskrenderer.h>
 #include <gsk/gskrendernode.h>
 #include <gsk/gskroundedrect.h>
+#include <gsk/gskstroke.h>
 #include <gsk/gsktransform.h>
 
 #include <gsk/gskcairorenderer.h>
diff --git a/gsk/gskenums.h b/gsk/gskenums.h
index f28cc0401c..98d5afd505 100644
--- a/gsk/gskenums.h
+++ b/gsk/gskenums.h
@@ -72,6 +72,7 @@ typedef enum {
   GSK_CLIP_NODE,
   GSK_ROUNDED_CLIP_NODE,
   GSK_FILL_NODE,
+  GSK_STROKE_NODE,
   GSK_SHADOW_NODE,
   GSK_BLEND_NODE,
   GSK_CROSS_FADE_NODE,
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index 3fdcb63e10..d98eec13d8 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -132,6 +132,7 @@ GskRenderNode *         gsk_render_node_deserialize             (GBytes
 #define GSK_TYPE_CLIP_NODE                      (gsk_clip_node_get_type())
 #define GSK_TYPE_ROUNDED_CLIP_NODE              (gsk_rounded_clip_node_get_type())
 #define GSK_TYPE_FILL_NODE                      (gsk_fill_node_get_type())
+#define GSK_TYPE_STROKE_NODE                    (gsk_stroke_node_get_type())
 #define GSK_TYPE_SHADOW_NODE                    (gsk_shadow_node_get_type())
 #define GSK_TYPE_BLEND_NODE                     (gsk_blend_node_get_type())
 #define GSK_TYPE_CROSS_FADE_NODE                (gsk_cross_fade_node_get_type())
@@ -158,6 +159,7 @@ typedef struct _GskRepeatNode                   GskRepeatNode;
 typedef struct _GskClipNode                     GskClipNode;
 typedef struct _GskRoundedClipNode              GskRoundedClipNode;
 typedef struct _GskFillNode                     GskFillNode;
+typedef struct _GskStrokeNode                   GskStrokeNode;
 typedef struct _GskShadowNode                   GskShadowNode;
 typedef struct _GskBlendNode                    GskBlendNode;
 typedef struct _GskCrossFadeNode                GskCrossFadeNode;
@@ -412,6 +414,19 @@ GskPath *               gsk_fill_node_get_path                  (GskRenderNode
 GDK_AVAILABLE_IN_ALL
 GskFillRule             gsk_fill_node_get_fill_rule             (GskRenderNode            *node);
 
+GDK_AVAILABLE_IN_ALL
+GType                   gsk_stroke_node_get_type                (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GskRenderNode *         gsk_stroke_node_new                     (GskRenderNode            *child,
+                                                                 GskPath                  *path,
+                                                                 const GskStroke          *stroke);
+GDK_AVAILABLE_IN_ALL
+GskRenderNode *         gsk_stroke_node_get_child               (GskRenderNode            *node);
+GDK_AVAILABLE_IN_ALL
+GskPath *               gsk_stroke_node_get_path                (GskRenderNode            *node);
+GDK_AVAILABLE_IN_ALL
+const GskStroke *       gsk_stroke_node_get_stroke              (GskRenderNode            *node);
+
 GDK_AVAILABLE_IN_ALL
 GType                   gsk_shadow_node_get_type                (void) G_GNUC_CONST;
 GDK_AVAILABLE_IN_ALL
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index 1586e49cfc..0fae26f198 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -26,6 +26,7 @@
 #include "gskpath.h"
 #include "gskrendererprivate.h"
 #include "gskroundedrectprivate.h"
+#include "gskstrokeprivate.h"
 #include "gsktransformprivate.h"
 
 #include "gdk/gdktextureprivate.h"
@@ -3423,6 +3424,168 @@ gsk_fill_node_get_fill_rule (GskRenderNode *node)
   return self->fill_rule;
 }
 
+/*** GSK_STROKE_NODE ***/
+
+struct _GskStrokeNode
+{
+  GskRenderNode render_node;
+
+  GskRenderNode *child;
+  GskPath *path;
+  GskStroke stroke;
+};
+
+static void
+gsk_stroke_node_finalize (GskRenderNode *node)
+{
+  GskStrokeNode *self = (GskStrokeNode *) node;
+  GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_STROKE_NODE));
+
+  gsk_render_node_unref (self->child);
+  gsk_path_unref (self->path);
+  gsk_stroke_clear (&self->stroke);
+
+  parent_class->finalize (node);
+}
+
+static void
+gsk_stroke_node_draw (GskRenderNode *node,
+                      cairo_t       *cr)
+{
+  GskStrokeNode *self = (GskStrokeNode *) node;
+
+  cairo_save (cr);
+
+  gsk_cairo_rectangle (cr, &self->child->bounds);
+  cairo_clip (cr);
+
+  cairo_push_group (cr);
+  gsk_render_node_draw (self->child, cr);
+  cairo_pop_group_to_source (cr);
+
+  cairo_set_line_width (cr, self->stroke.line_width);
+
+  gsk_path_to_cairo (self->path, cr);
+  cairo_stroke (cr);
+
+  cairo_restore (cr);
+}
+
+static void
+gsk_stroke_node_diff (GskRenderNode  *node1,
+                    GskRenderNode  *node2,
+                    cairo_region_t *region)
+{
+  GskStrokeNode *self1 = (GskStrokeNode *) node1;
+  GskStrokeNode *self2 = (GskStrokeNode *) node2;
+
+  if (self1->path == self2->path &&
+      gsk_stroke_equal (&self1->stroke, &self2->stroke))
+    {
+      cairo_region_t *sub;
+
+      sub = cairo_region_create();
+      gsk_render_node_diff (self1->child, self2->child, sub);
+      cairo_region_union (region, sub);
+      cairo_region_destroy (sub);
+    }
+  else
+    {
+      gsk_render_node_diff_impossible (node1, node2, region);
+    }
+}
+
+/**
+ * gsk_stroke_node_new:
+ * @child: The node to stroke the area with
+ * @path: (transfer none): The path describing the area to stroke
+ * @stroke: (transfer none): The stroke attributes to use
+ *
+ * Creates a #GskRenderNode that will stroke the @child along the given
+ * @path using the attributes defined in @stroke.
+ *
+ * Returns: (transfer none) (type GskStrokeNode): A new #GskRenderNode
+ */
+GskRenderNode *
+gsk_stroke_node_new (GskRenderNode   *child,
+                     GskPath         *path,
+                     const GskStroke *stroke)
+{
+  GskStrokeNode *self;
+  GskRenderNode *node;
+
+  g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
+  g_return_val_if_fail (path != NULL, NULL);
+  g_return_val_if_fail (stroke != NULL, NULL);
+
+  self = gsk_render_node_alloc (GSK_STROKE_NODE);
+  node = (GskRenderNode *) self;
+
+  self->child = gsk_render_node_ref (child);
+  self->path = gsk_path_ref (path);
+  gsk_stroke_init_copy (&self->stroke, stroke);
+
+  /* XXX: Figure out a way to compute bounds from the path */
+  graphene_rect_init_from_rect (&node->bounds, &child->bounds);
+
+  return node;
+}
+
+/**
+ * gsk_stroke_node_get_child:
+ * @node: (type GskStrokeNode): a stroke #GskRenderNode
+ *
+ * Gets the child node that is getting drawn by the given @node.
+ *
+ * Returns: (transfer none): The child that is getting drawn
+ **/
+GskRenderNode *
+gsk_stroke_node_get_child (GskRenderNode *node)
+{
+  GskStrokeNode *self = (GskStrokeNode *) node;
+
+  g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_STROKE_NODE), NULL);
+
+  return self->child;
+}
+
+/**
+ * gsk_stroke_node_get_path:
+ * @node: (type GskStrokeNode): a stroke #GskRenderNode
+ *
+ * Retrievs the path that will be stroked with the contents of
+ * the @node.
+ *
+ * Returns: (transfer none): a #GskPath
+ */
+GskPath *
+gsk_stroke_node_get_path (GskRenderNode *node)
+{
+  GskStrokeNode *self = (GskStrokeNode *) node;
+
+  g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_STROKE_NODE), NULL);
+
+  return self->path;
+}
+
+/**
+ * gsk_stroke_node_get_stroke:
+ * @node: (type GskStrokeNode): a stroke #GskRenderNode
+ *
+ * Retrievs the stroke attributes used in this @node.
+ *
+ * Returns: a #GskStroke
+ */
+const GskStroke *
+gsk_stroke_node_get_stroke (GskRenderNode *node)
+{
+  GskStrokeNode *self = (GskStrokeNode *) node;
+
+  g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_STROKE_NODE), NULL);
+
+  return &self->stroke;
+}
+
 /*** GSK_SHADOW_NODE ***/
 
 struct _GskShadowNode
@@ -4935,6 +5098,7 @@ GSK_DEFINE_RENDER_NODE_TYPE (gsk_repeat_node, GSK_REPEAT_NODE)
 GSK_DEFINE_RENDER_NODE_TYPE (gsk_clip_node, GSK_CLIP_NODE)
 GSK_DEFINE_RENDER_NODE_TYPE (gsk_rounded_clip_node, GSK_ROUNDED_CLIP_NODE)
 GSK_DEFINE_RENDER_NODE_TYPE (gsk_fill_node, GSK_FILL_NODE)
+GSK_DEFINE_RENDER_NODE_TYPE (gsk_stroke_node, GSK_STROKE_NODE)
 GSK_DEFINE_RENDER_NODE_TYPE (gsk_shadow_node, GSK_SHADOW_NODE)
 GSK_DEFINE_RENDER_NODE_TYPE (gsk_blend_node, GSK_BLEND_NODE)
 GSK_DEFINE_RENDER_NODE_TYPE (gsk_cross_fade_node, GSK_CROSS_FADE_NODE)
@@ -5234,6 +5398,22 @@ gsk_render_node_init_types_once (void)
     gsk_render_node_types[GSK_FILL_NODE] = node_type;
   }
 
+  {
+    const GskRenderNodeTypeInfo node_info =
+    {
+      GSK_STROKE_NODE,
+      sizeof (GskStrokeNode),
+      NULL,
+      gsk_stroke_node_finalize,
+      gsk_stroke_node_draw,
+      NULL,
+      gsk_stroke_node_diff,
+    };
+
+    GType node_type = gsk_render_node_type_register_static (I_("GskStrokeNode"), &node_info);
+    gsk_render_node_types[GSK_STROKE_NODE] = node_type;
+  }
+
   {
     const GskRenderNodeTypeInfo node_info =
     {
diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c
index ed565f8e53..804976d2a5 100644
--- a/gsk/gskrendernodeparser.c
+++ b/gsk/gskrendernodeparser.c
@@ -26,6 +26,7 @@
 #include "gskpath.h"
 #include "gskroundedrectprivate.h"
 #include "gskrendernodeprivate.h"
+#include "gskstroke.h"
 #include "gsktransformprivate.h"
 
 #include "gdk/gdkrgbaprivate.h"
@@ -2060,7 +2061,7 @@ append_float_param (Printer    *p,
                     float       value,
                     float       default_value)
 {
-  /* Don't approximate-compare here, better be topo verbose */
+  /* Don't approximate-compare here, better be too verbose */
   if (value == default_value)
     return;
 
@@ -2427,6 +2428,25 @@ render_node_print (Printer       *p,
       }
       break;
 
+    case GSK_STROKE_NODE:
+      {
+        const GskStroke *stroke;
+        char *path_str;
+
+        start_node (p, "stroke");
+
+        append_node_param (p, "child", gsk_stroke_node_get_child (node));
+        path_str = gsk_path_to_string (gsk_stroke_node_get_path (node));
+        append_string_param (p, "path", path_str);
+        g_free (path_str);
+
+        stroke = gsk_stroke_node_get_stroke (node);
+        append_float_param (p, "line-width", gsk_stroke_get_line_width (stroke), 0.0);
+
+        end_node (p);
+      }
+      break;
+
     case GSK_TRANSFORM_NODE:
       {
         GskTransform *transform = gsk_transform_node_get_transform (node);
diff --git a/gsk/gskstroke.c b/gsk/gskstroke.c
new file mode 100644
index 0000000000..755c9cdfe8
--- /dev/null
+++ b/gsk/gskstroke.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2020 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include "gskstrokeprivate.h"
+
+/**
+ * SECTION:gskstroke
+ * @Title: Stroke
+ * @Short_description: Properties of a stroke operation
+ * @See_also: #GskPath, gsk_stroke_node_new()
+ *
+ * This section describes the #GskStroke structure that is used to
+ * describe lines and curves that are more complex than simple rectangles.
+ *
+ * #GskStroke is an immutable struct. After creation, you cannot change
+ * the types it represents. Instead, new #GskStroke have to be created.
+ * The #GskStrokeBuilder structure is meant to help in this endeavor.
+ */
+
+/**
+ * GskStroke:
+ *
+ * A #GskStroke struct is an opaque struct that should be copied
+ * on use.
+ */
+
+G_DEFINE_BOXED_TYPE (GskStroke, gsk_stroke,
+                     gsk_stroke_copy,
+                     gsk_stroke_free)
+
+
+GskStroke *
+gsk_stroke_new (float line_width)
+{
+  GskStroke *self;
+
+  g_return_val_if_fail (line_width > 0, NULL);
+
+  self = g_new0 (GskStroke, 1);
+
+  self->line_width = line_width;
+
+  return self;
+}
+
+GskStroke *
+gsk_stroke_copy (const GskStroke *other)
+{
+  GskStroke *self;
+
+  g_return_val_if_fail (other != NULL, NULL);
+
+  self = g_new (GskStroke, 1);
+
+  gsk_stroke_init_copy (self, other);
+
+  return self;
+}
+
+void
+gsk_stroke_free (GskStroke *self)
+{
+  if (self == NULL)
+    return;
+
+  gsk_stroke_clear (self);
+
+  g_free (self);
+}
+
+gboolean
+gsk_stroke_equal (gconstpointer stroke1,
+                  gconstpointer stroke2)
+{
+  const GskStroke *self1 = stroke1;
+  const GskStroke *self2 = stroke2;
+
+  return self1->line_width == self2->line_width;
+}
+
+void
+gsk_stroke_set_line_width (GskStroke *self,
+                           float      line_width)
+{
+  self->line_width = line_width;
+}
+
+float
+gsk_stroke_get_line_width (const GskStroke *self)
+{
+  return self->line_width;
+}
+
diff --git a/gsk/gskstroke.h b/gsk/gskstroke.h
new file mode 100644
index 0000000000..3650325606
--- /dev/null
+++ b/gsk/gskstroke.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2020 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#ifndef __GSK_STROKE_H__
+#define __GSK_STROKE_H__
+
+#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gsk/gsk.h> can be included directly."
+#endif
+
+
+#include <gsk/gsktypes.h>
+
+G_BEGIN_DECLS
+
+#define GSK_TYPE_STROKE (gsk_stroke_get_type ())
+
+GDK_AVAILABLE_IN_ALL
+GType                   gsk_stroke_get_type                     (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GskStroke *             gsk_stroke_new                          (float                   line_width);
+GDK_AVAILABLE_IN_ALL
+GskStroke *             gsk_stroke_copy                         (const GskStroke        *other);
+GDK_AVAILABLE_IN_ALL
+void                    gsk_stroke_free                         (GskStroke              *self);
+
+GDK_AVAILABLE_IN_ALL
+gboolean                gsk_stroke_equal                        (gconstpointer           stroke1,
+                                                                 gconstpointer           stroke2);
+
+GDK_AVAILABLE_IN_ALL
+void                    gsk_stroke_set_line_width               (GskStroke              *self,
+                                                                 float                   line_width);
+GDK_AVAILABLE_IN_ALL
+float                   gsk_stroke_get_line_width               (const GskStroke        *self);
+
+
+G_END_DECLS
+
+#endif /* __GSK_STROKE_H__ */
diff --git a/gsk/gskstrokeprivate.h b/gsk/gskstrokeprivate.h
new file mode 100644
index 0000000000..aa77b88b12
--- /dev/null
+++ b/gsk/gskstrokeprivate.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2020 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+
+#ifndef __GSK_STROKE_PRIVATE_H__
+#define __GSK_STROKE_PRIVATE_H__
+
+#include "gskstroke.h"
+
+G_BEGIN_DECLS
+
+struct _GskStroke
+{
+  float line_width;
+};
+
+static inline void
+gsk_stroke_init_copy (GskStroke       *stroke,
+                      const GskStroke *other)
+{
+  *stroke = *other;
+}
+
+static inline void
+gsk_stroke_clear (GskStroke *stroke)
+{
+}
+
+G_END_DECLS
+
+#endif /* __GSK_STROKE_PRIVATE_H__ */
+
diff --git a/gsk/gsktypes.h b/gsk/gsktypes.h
index 863ef651c2..fdf06b5ffc 100644
--- a/gsk/gsktypes.h
+++ b/gsk/gsktypes.h
@@ -28,6 +28,7 @@
 
 typedef struct _GskPath                 GskPath;
 typedef struct _GskRenderer             GskRenderer;
+typedef struct _GskStroke               GskStroke;
 typedef struct _GskTransform            GskTransform;
 
 #endif /* __GSK_TYPES_H__ */
diff --git a/gsk/meson.build b/gsk/meson.build
index f37c5d06f4..5be795d0c3 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -29,6 +29,7 @@ gsk_public_sources = files([
   'gskrendernodeimpl.c',
   'gskrendernodeparser.c',
   'gskroundedrect.c',
+  'gskstroke.c',
   'gsktransform.c',
   'gl/gskglrenderer.c',
 ])
@@ -58,6 +59,7 @@ gsk_public_headers = files([
   'gskrenderer.h',
   'gskrendernode.h',
   'gskroundedrect.h',
+  'gskstroke.h',
   'gsktransform.h',
   'gsktypes.h',
   'gsk-autocleanup.h',
diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c
index d20f2a2306..8a749d0378 100644
--- a/gsk/vulkan/gskvulkanrenderpass.c
+++ b/gsk/vulkan/gskvulkanrenderpass.c
@@ -260,6 +260,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
     case GSK_RADIAL_GRADIENT_NODE:
     case GSK_REPEATING_RADIAL_GRADIENT_NODE:
     case GSK_FILL_NODE:
+    case GSK_STROKE_NODE:
     default:
       FALLBACK ("Unsupported node '%s'", g_type_name_from_instance ((GTypeInstance *) node));
 
diff --git a/gtk/inspector/recorder.c b/gtk/inspector/recorder.c
index 9a8fb39b0a..4bf094a38c 100644
--- a/gtk/inspector/recorder.c
+++ b/gtk/inspector/recorder.c
@@ -163,6 +163,9 @@ create_list_model_for_render_node (GskRenderNode *node)
     case GSK_FILL_NODE:
       return create_render_node_list_model ((GskRenderNode *[1]) { gsk_fill_node_get_child (node) }, 1);
 
+    case GSK_STROKE_NODE:
+      return create_render_node_list_model ((GskRenderNode *[1]) { gsk_stroke_node_get_child (node) }, 1);
+
     case GSK_SHADOW_NODE:
       return create_render_node_list_model ((GskRenderNode *[1]) { gsk_shadow_node_get_child (node) }, 1);
 
@@ -284,6 +287,8 @@ node_type_name (GskRenderNodeType type)
       return "Rounded Clip";
     case GSK_FILL_NODE:
       return "Fill";
+    case GSK_STROKE_NODE:
+      return "Stroke";
     case GSK_SHADOW_NODE:
       return "Shadow";
     case GSK_BLEND_NODE:
@@ -323,6 +328,7 @@ node_name (GskRenderNode *node)
     case GSK_CLIP_NODE:
     case GSK_ROUNDED_CLIP_NODE:
     case GSK_FILL_NODE:
+    case GSK_STROKE_NODE:
     case GSK_SHADOW_NODE:
     case GSK_BLEND_NODE:
     case GSK_CROSS_FADE_NODE:
@@ -1047,6 +1053,25 @@ populate_render_node_properties (GtkListStore  *store,
         tmp = gsk_path_to_string (path);
         add_text_row (store, "Path", tmp);
         g_free (tmp);
+
+        tmp = g_enum_to_string (GSK_TYPE_FILL_RULE, gsk_fill_node_get_fill_rule (node));
+        add_text_row (store, "Fill rule", tmp);
+        g_free (tmp);
+      }
+      break;
+
+    case GSK_STROKE_NODE:
+      {
+        GskPath *path = gsk_stroke_node_get_path (node);
+        const GskStroke *stroke = gsk_stroke_node_get_stroke (node);
+
+        tmp = gsk_path_to_string (path);
+        add_text_row (store, "Path", tmp);
+        g_free (tmp);
+
+        tmp = g_strdup_printf ("%.2f", gsk_stroke_get_line_width (stroke));
+        add_text_row (store, "Line width", tmp);
+        g_free (tmp);
       }
       break;
 


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