summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2020-12-03 00:47:54 +0100
committerBenjamin Otte <otte@redhat.com>2020-12-03 00:47:54 +0100
commit55a242bd816893e8b3c777b053a3c5fc0266b5d6 (patch)
treef37db07ad554e499ad7b5b0785e9af53751cc394
parent71cb7c2063a85d4f8d5424e466319f30be318913 (diff)
downloadgtk+-55a242bd816893e8b3c777b053a3c5fc0266b5d6.tar.gz
gsk: Add GskConicGradientNode
-rw-r--r--docs/reference/gsk/gsk4-sections.txt5
-rw-r--r--gsk/broadway/gskbroadwayrenderer.c2
-rw-r--r--gsk/gl/gskglrenderer.c1
-rw-r--r--gsk/gskenums.h2
-rw-r--r--gsk/gskrendernode.h20
-rw-r--r--gsk/gskrendernodeimpl.c338
-rw-r--r--gsk/gskrendernodeparser.c50
-rw-r--r--gsk/vulkan/gskvulkanrenderpass.c1
-rw-r--r--gtk/inspector/recorder.c42
9 files changed, 461 insertions, 0 deletions
diff --git a/docs/reference/gsk/gsk4-sections.txt b/docs/reference/gsk/gsk4-sections.txt
index f671732880..6cd1fa0d17 100644
--- a/docs/reference/gsk/gsk4-sections.txt
+++ b/docs/reference/gsk/gsk4-sections.txt
@@ -83,6 +83,11 @@ gsk_radial_gradient_node_get_hradius
gsk_radial_gradient_node_get_vradius
gsk_radial_gradient_node_get_center
gsk_repeating_radial_gradient_node_new
+gsk_conic_gradient_node_new
+gsk_conic_gradient_node_get_n_color_stops
+gsk_conic_gradient_node_get_color_stops
+gsk_conic_gradient_node_get_center
+gsk_conic_gradient_node_get_rotation
gsk_border_node_new
gsk_border_node_get_outline
gsk_border_node_get_widths
diff --git a/gsk/broadway/gskbroadwayrenderer.c b/gsk/broadway/gskbroadwayrenderer.c
index 80a3f84968..5ac62e7ee0 100644
--- a/gsk/broadway/gskbroadwayrenderer.c
+++ b/gsk/broadway/gskbroadwayrenderer.c
@@ -264,6 +264,7 @@ collect_reused_child_nodes (GskRenderer *renderer,
case GSK_RADIAL_GRADIENT_NODE:
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
+ case GSK_CONIC_GRADIENT_NODE:
case GSK_REPEAT_NODE:
case GSK_BLEND_NODE:
case GSK_CROSS_FADE_NODE:
@@ -848,6 +849,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
case GSK_RADIAL_GRADIENT_NODE:
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
+ case GSK_CONIC_GRADIENT_NODE:
case GSK_REPEAT_NODE:
case GSK_BLEND_NODE:
case GSK_CROSS_FADE_NODE:
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index cd93966d5c..bb09be8bdd 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -3723,6 +3723,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
+ case GSK_CONIC_GRADIENT_NODE:
case GSK_CAIRO_NODE:
default:
{
diff --git a/gsk/gskenums.h b/gsk/gskenums.h
index 0cd0c284fc..243ab67cc8 100644
--- a/gsk/gskenums.h
+++ b/gsk/gskenums.h
@@ -32,6 +32,7 @@
* @GSK_REPEATING_LINEAR_GRADIENT_NODE: A node drawing a repeating linear gradient
* @GSK_RADIAL_GRADIENT_NODE: A node drawing a radial gradient
* @GSK_REPEATING_RADIAL_GRADIENT_NODE: A node drawing a repeating radial gradient
+ * @GSK_CONIC_GRADIENT_NODE: A node drawing a conic gradient
* @GSK_BORDER_NODE: A node stroking a border around an area
* @GSK_TEXTURE_NODE: A node drawing a #GdkTexture
* @GSK_INSET_SHADOW_NODE: A node drawing an inset shadow
@@ -61,6 +62,7 @@ typedef enum {
GSK_REPEATING_LINEAR_GRADIENT_NODE,
GSK_RADIAL_GRADIENT_NODE,
GSK_REPEATING_RADIAL_GRADIENT_NODE,
+ GSK_CONIC_GRADIENT_NODE,
GSK_BORDER_NODE,
GSK_TEXTURE_NODE,
GSK_INSET_SHADOW_NODE,
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index dba436afda..76771a9d8e 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -120,6 +120,7 @@ GskRenderNode * gsk_render_node_deserialize (GBytes
#define GSK_TYPE_REPEATING_LINEAR_GRADIENT_NODE (gsk_repeating_linear_gradient_node_get_type())
#define GSK_TYPE_RADIAL_GRADIENT_NODE (gsk_radial_gradient_node_get_type())
#define GSK_TYPE_REPEATING_RADIAL_GRADIENT_NODE (gsk_repeating_radial_gradient_node_get_type())
+#define GSK_TYPE_CONIC_GRADIENT_NODE (gsk_conic_gradient_node_get_type())
#define GSK_TYPE_BORDER_NODE (gsk_border_node_get_type())
#define GSK_TYPE_INSET_SHADOW_NODE (gsk_inset_shadow_node_get_type())
#define GSK_TYPE_OUTSET_SHADOW_NODE (gsk_outset_shadow_node_get_type())
@@ -145,6 +146,7 @@ typedef struct _GskLinearGradientNode GskLinearGradientNode;
typedef struct _GskRepeatingLinearGradientNode GskRepeatingLinearGradientNode;
typedef struct _GskRadialGradientNode GskRadialGradientNode;
typedef struct _GskRepeatingRadialGradientNode GskRepeatingRadialGradientNode;
+typedef struct _GskConicGradientNode GskConicGradientNode;
typedef struct _GskBorderNode GskBorderNode;
typedef struct _GskInsetShadowNode GskInsetShadowNode;
typedef struct _GskOutsetShadowNode GskOutsetShadowNode;
@@ -217,6 +219,24 @@ GskRenderNode * gsk_repeating_linear_gradient_node_new (const graph
gsize n_color_stops);
GDK_AVAILABLE_IN_ALL
+GType gsk_conic_gradient_node_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GskRenderNode * gsk_conic_gradient_node_new (const graphene_rect_t *bounds,
+ const graphene_point_t *center,
+ float rotation,
+ const GskColorStop *color_stops,
+ gsize n_color_stops);
+GDK_AVAILABLE_IN_ALL
+const graphene_point_t * gsk_conic_gradient_node_get_center (GskRenderNode *node);
+GDK_AVAILABLE_IN_ALL
+float gsk_conic_gradient_node_get_rotation (GskRenderNode *node);
+GDK_AVAILABLE_IN_ALL
+gsize gsk_conic_gradient_node_get_n_color_stops (GskRenderNode *node);
+GDK_AVAILABLE_IN_ALL
+const GskColorStop * gsk_conic_gradient_node_get_color_stops (GskRenderNode *node,
+ gsize *n_stops);
+
+GDK_AVAILABLE_IN_ALL
GType gsk_radial_gradient_node_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_radial_gradient_node_new (const graphene_rect_t *bounds,
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index e5228d88c9..44fb918ddd 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -741,6 +741,327 @@ gsk_radial_gradient_node_get_end (GskRenderNode *node)
return self->end;
}
+/*** GSK_CONIC_GRADIENT_NODE ***/
+
+struct _GskConicGradientNode
+{
+ GskRenderNode render_node;
+
+ graphene_point_t center;
+ float rotation;
+
+ gsize n_stops;
+ GskColorStop *stops;
+};
+
+static void
+gsk_conic_gradient_node_finalize (GskRenderNode *node)
+{
+ GskConicGradientNode *self = (GskConicGradientNode *) node;
+ GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_CONIC_GRADIENT_NODE));
+
+ g_free (self->stops);
+
+ parent_class->finalize (node);
+}
+
+#define DEG_TO_RAD(x) ((x) * (G_PI / 180.f))
+
+static void
+_cairo_mesh_pattern_set_corner_rgba (cairo_pattern_t *pattern,
+ guint corner_num,
+ const GdkRGBA *rgba)
+{
+ cairo_mesh_pattern_set_corner_color_rgba (pattern, corner_num, rgba->red, rgba->green, rgba->blue, rgba->alpha);
+}
+
+static void
+project (double angle,
+ double radius,
+ double *x_out,
+ double *y_out)
+{
+ double x, y;
+
+ x = radius * cos (angle);
+ y = radius * sin (angle);
+ if (copysign (x, 1.0) > copysign (y, 1.0))
+ {
+ *x_out = copysign (radius, x);
+ *y_out = y * radius / copysign (x, 1.0);
+ }
+ else
+ {
+ *x_out = x * radius / copysign (y, 1.0);
+ *y_out = copysign (radius, y);
+ }
+}
+
+static void
+gsk_conic_gradient_node_add_patch (cairo_pattern_t *pattern,
+ float radius,
+ float start_angle,
+ const GdkRGBA *start_color,
+ float end_angle,
+ const GdkRGBA *end_color)
+{
+ double x, y;
+
+ cairo_mesh_pattern_begin_patch (pattern);
+
+ cairo_mesh_pattern_move_to (pattern, 0, 0);
+ project (start_angle, radius, &x, &y);
+ cairo_mesh_pattern_line_to (pattern, x, y);
+ project (end_angle, radius, &x, &y);
+ cairo_mesh_pattern_line_to (pattern, x, y);
+ cairo_mesh_pattern_line_to (pattern, 0, 0);
+
+ _cairo_mesh_pattern_set_corner_rgba (pattern, 0, start_color);
+ _cairo_mesh_pattern_set_corner_rgba (pattern, 1, start_color);
+ _cairo_mesh_pattern_set_corner_rgba (pattern, 2, end_color);
+ _cairo_mesh_pattern_set_corner_rgba (pattern, 3, end_color);
+
+ cairo_mesh_pattern_end_patch (pattern);
+}
+
+static void
+gdk_rgba_color_interpolate (GdkRGBA *dest,
+ const GdkRGBA *src1,
+ const GdkRGBA *src2,
+ double progress)
+{
+ double alpha = src1->alpha * (1.0 - progress) + src2->alpha * progress;
+
+ dest->alpha = alpha;
+ if (alpha == 0)
+ {
+ dest->red = src1->red * (1.0 - progress) + src2->red * progress;
+ dest->green = src1->green * (1.0 - progress) + src2->green * progress;
+ dest->blue = src1->blue * (1.0 - progress) + src2->blue * progress;
+ }
+ else
+ {
+ dest->red = (src1->red * src1->alpha * (1.0 - progress) + src2->red * src2->alpha * progress) / alpha;
+ dest->green = (src1->green * src1->alpha * (1.0 - progress) + src2->green * src2->alpha * progress) / alpha;
+ dest->blue = (src1->blue * src1->alpha * (1.0 - progress) + src2->blue * src2->alpha * progress) / alpha;
+ }
+}
+
+static void
+gsk_conic_gradient_node_draw (GskRenderNode *node,
+ cairo_t *cr)
+{
+ GskConicGradientNode *self = (GskConicGradientNode *) node;
+ cairo_pattern_t *pattern;
+ graphene_point_t corner;
+ float radius;
+ gsize i;
+
+ pattern = cairo_pattern_create_mesh ();
+ graphene_rect_get_top_right (&node->bounds, &corner);
+ radius = graphene_point_distance (&self->center, &corner, NULL, NULL);
+ graphene_rect_get_bottom_right (&node->bounds, &corner);
+ radius = MAX (radius, graphene_point_distance (&self->center, &corner, NULL, NULL));
+ graphene_rect_get_bottom_left (&node->bounds, &corner);
+ radius = MAX (radius, graphene_point_distance (&self->center, &corner, NULL, NULL));
+ graphene_rect_get_top_left (&node->bounds, &corner);
+ radius = MAX (radius, graphene_point_distance (&self->center, &corner, NULL, NULL));
+
+ for (i = 0; i <= self->n_stops; i++)
+ {
+ GskColorStop *stop1 = &self->stops[MAX (i, 1) - 1];
+ GskColorStop *stop2 = &self->stops[MIN (i, self->n_stops - 1)];
+ double offset1 = i > 0 ? stop1->offset : 0;
+ double offset2 = i < self->n_stops ? stop2->offset : 1;
+ double start_angle, end_angle;
+
+ offset1 = offset1 * 360 + self->rotation - 90;
+ offset2 = offset2 * 360 + self->rotation - 90;
+
+ for (start_angle = offset1; start_angle < offset2; start_angle = end_angle)
+ {
+ GdkRGBA start_color, end_color;
+ end_angle = (floor (start_angle / 45) + 1) * 45;
+ end_angle = MIN (end_angle, offset2);
+ gdk_rgba_color_interpolate (&start_color,
+ &stop1->color,
+ &stop2->color,
+ (start_angle - offset1) / (offset2 - offset1));
+ gdk_rgba_color_interpolate (&end_color,
+ &stop1->color,
+ &stop2->color,
+ (end_angle - offset1) / (offset2 - offset1));
+
+ gsk_conic_gradient_node_add_patch (pattern,
+ radius,
+ DEG_TO_RAD (start_angle),
+ &start_color,
+ DEG_TO_RAD (end_angle),
+ &end_color);
+ }
+ }
+
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
+
+ gsk_cairo_rectangle (cr, &node->bounds);
+ cairo_translate (cr, self->center.x, self->center.y);
+ cairo_set_source (cr, pattern);
+ cairo_fill (cr);
+
+ cairo_pattern_destroy (pattern);
+}
+
+static void
+gsk_conic_gradient_node_diff (GskRenderNode *node1,
+ GskRenderNode *node2,
+ cairo_region_t *region)
+{
+ GskConicGradientNode *self1 = (GskConicGradientNode *) node1;
+ GskConicGradientNode *self2 = (GskConicGradientNode *) node2;
+ gsize i;
+
+ if (!graphene_point_equal (&self1->center, &self2->center) ||
+ self1->rotation != self2->rotation ||
+ self1->n_stops != self2->n_stops)
+ {
+ gsk_render_node_diff_impossible (node1, node2, region);
+ return;
+ }
+
+ for (i = 0; i < self1->n_stops; i++)
+ {
+ GskColorStop *stop1 = &self1->stops[i];
+ GskColorStop *stop2 = &self2->stops[i];
+
+ if (stop1->offset != stop2->offset ||
+ !gdk_rgba_equal (&stop1->color, &stop2->color))
+ {
+ gsk_render_node_diff_impossible (node1, node2, region);
+ return;
+ }
+ }
+}
+
+/**
+ * gsk_conic_gradient_node_new:
+ * @bounds: the bounds of the node
+ * @center: the center of the gradient
+ * @rotation: the rotation of the gradient in degrees
+ * @color_stops: (array length=n_color_stops): a pointer to an array of #GskColorStop defining the gradient
+ * The offsets of all color steps must be increasing. The first stop's offset must be >= 0 and the last
+ * stop's offset must be <= 1.
+ * @n_color_stops: the number of elements in @color_stops
+ *
+ * Creates a #GskRenderNode that draws a conic gradient. The conic gradient
+ * starts around @center in the direction of @rotation. A rotation of 0 means
+ * that the gradient points up. Color stops are then added clockwise.
+ *
+ * Returns: (transfer full) (type GskConicGradientNode): A new #GskRenderNode
+ */
+GskRenderNode *
+gsk_conic_gradient_node_new (const graphene_rect_t *bounds,
+ const graphene_point_t *center,
+ float rotation,
+ const GskColorStop *color_stops,
+ gsize n_color_stops)
+{
+ GskConicGradientNode *self;
+ GskRenderNode *node;
+ gsize i;
+
+ g_return_val_if_fail (bounds != NULL, NULL);
+ g_return_val_if_fail (center != NULL, NULL);
+ g_return_val_if_fail (color_stops != NULL, NULL);
+ 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[n_color_stops - 1].offset <= 1, NULL);
+
+ self = gsk_render_node_alloc (GSK_CONIC_GRADIENT_NODE);
+ node = (GskRenderNode *) self;
+
+ graphene_rect_init_from_rect (&node->bounds, bounds);
+ graphene_point_init_from_point (&self->center, center);
+
+ self->rotation = rotation;
+
+ 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 node;
+}
+
+/**
+ * gsk_conic_gradient_node_get_n_color_stops:
+ * @node: (type GskConicGradientNode): a #GskRenderNode for a conic gradient
+ *
+ * Retrieves the number of color stops in the gradient.
+ *
+ * Returns: the number of color stops
+ */
+gsize
+gsk_conic_gradient_node_get_n_color_stops (GskRenderNode *node)
+{
+ GskConicGradientNode *self = (GskConicGradientNode *) node;
+
+ return self->n_stops;
+}
+
+/**
+ * gsk_conic_gradient_node_get_color_stops:
+ * @node: (type GskConicGradientNode): a #GskRenderNode for a conic gradient
+ * @n_stops: (out) (optional): the number of color stops in the returned array
+ *
+ * Retrieves the color stops in the gradient.
+ *
+ * Returns: (array length=n_stops): the color stops in the gradient
+ */
+const GskColorStop *
+gsk_conic_gradient_node_get_color_stops (GskRenderNode *node,
+ gsize *n_stops)
+{
+ GskConicGradientNode *self = (GskConicGradientNode *) node;
+
+ if (n_stops != NULL)
+ *n_stops = self->n_stops;
+
+ return self->stops;
+}
+
+/**
+ * gsk_conic_gradient_node_get_center:
+ * @node: (type GskConicGradientNode): a #GskRenderNode for a conic gradient
+ *
+ * Retrieves the center pointer for the gradient.
+ *
+ * Returns: the center point for the gradient
+ */
+const graphene_point_t *
+gsk_conic_gradient_node_get_center (GskRenderNode *node)
+{
+ GskConicGradientNode *self = (GskConicGradientNode *) node;
+
+ return &self->center;
+}
+
+/**
+ * gsk_conic_gradient_node_get_rotation:
+ * @node: (type GskConicGradientNode): a #GskRenderNode for a conic gradient
+ *
+ * Retrieves the rotation for the gradient in degrees.
+ *
+ * Returns: the rotation for the gradient
+ */
+float
+gsk_conic_gradient_node_get_rotation (GskRenderNode *node)
+{
+ GskConicGradientNode *self = (GskConicGradientNode *) node;
+
+ return self->rotation;
+}
+
/*** GSK_BORDER_NODE ***/
struct _GskBorderNode
@@ -4752,6 +5073,7 @@ GSK_DEFINE_RENDER_NODE_TYPE (gsk_linear_gradient_node, GSK_LINEAR_GRADIENT_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_repeating_linear_gradient_node, GSK_REPEATING_LINEAR_GRADIENT_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_radial_gradient_node, GSK_RADIAL_GRADIENT_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_repeating_radial_gradient_node, GSK_REPEATING_RADIAL_GRADIENT_NODE)
+GSK_DEFINE_RENDER_NODE_TYPE (gsk_conic_gradient_node, GSK_CONIC_GRADIENT_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_border_node, GSK_BORDER_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_texture_node, GSK_TEXTURE_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_inset_shadow_node, GSK_INSET_SHADOW_NODE)
@@ -4888,6 +5210,22 @@ gsk_render_node_init_types_once (void)
{
const GskRenderNodeTypeInfo node_info =
{
+ GSK_REPEATING_RADIAL_GRADIENT_NODE,
+ sizeof (GskRadialGradientNode),
+ NULL,
+ gsk_conic_gradient_node_finalize,
+ gsk_conic_gradient_node_draw,
+ NULL,
+ gsk_conic_gradient_node_diff,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskConicGradientNode"), &node_info);
+ gsk_render_node_types[GSK_CONIC_GRADIENT_NODE] = node_type;
+ }
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
GSK_BORDER_NODE,
sizeof (GskBorderNode),
NULL,
diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c
index 61f94853a1..756147adb2 100644
--- a/gsk/gskrendernodeparser.c
+++ b/gsk/gskrendernodeparser.c
@@ -1071,6 +1071,40 @@ parse_repeating_radial_gradient_node (GtkCssParser *parser)
}
static GskRenderNode *
+parse_conic_gradient_node (GtkCssParser *parser)
+{
+ graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
+ graphene_point_t center = GRAPHENE_POINT_INIT (25, 25);
+ double rotation = 0.0;
+ GArray *stops = NULL;
+ const Declaration declarations[] = {
+ { "bounds", parse_rect, NULL, &bounds },
+ { "center", parse_point, NULL, &center },
+ { "rotation", parse_double, NULL, &rotation },
+ { "stops", parse_stops, clear_stops, &stops },
+ };
+ GskRenderNode *result;
+
+ parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
+ if (stops == NULL)
+ {
+ GskColorStop from = { 0.0, GDK_RGBA("AAFF00") };
+ GskColorStop to = { 1.0, GDK_RGBA("FF00CC") };
+
+ stops = g_array_new (FALSE, FALSE, sizeof (GskColorStop));
+ g_array_append_val (stops, from);
+ g_array_append_val (stops, to);
+ }
+
+ result = gsk_conic_gradient_node_new (&bounds, &center, rotation,
+ (GskColorStop *) stops->data, stops->len);
+
+ g_array_free (stops, TRUE);
+
+ return result;
+}
+
+static GskRenderNode *
parse_inset_shadow_node (GtkCssParser *parser)
{
GskRoundedRect outline = GSK_ROUNDED_RECT_INIT (0, 0, 50, 50);
@@ -1797,6 +1831,7 @@ parse_node (GtkCssParser *parser,
{ "inset-shadow", parse_inset_shadow_node },
{ "linear-gradient", parse_linear_gradient_node },
{ "radial-gradient", parse_radial_gradient_node },
+ { "conic-gradient", parse_conic_gradient_node },
{ "opacity", parse_opacity_node },
{ "outset-shadow", parse_outset_shadow_node },
{ "repeat", parse_repeat_node },
@@ -2355,6 +2390,21 @@ render_node_print (Printer *p,
}
break;
+ case GSK_CONIC_GRADIENT_NODE:
+ {
+ start_node (p, "conic-gradient");
+
+ append_rect_param (p, "bounds", &node->bounds);
+ append_point_param (p, "center", gsk_conic_gradient_node_get_center (node));
+ append_float_param (p, "rotation", gsk_conic_gradient_node_get_rotation (node), 0.0f);
+
+ append_stops_param (p, "stops", gsk_conic_gradient_node_get_color_stops (node, NULL),
+ gsk_conic_gradient_node_get_n_color_stops (node));
+
+ end_node (p);
+ }
+ break;
+
case GSK_OPACITY_NODE:
{
start_node (p, "opacity");
diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c
index 103412487f..d81d38fa33 100644
--- a/gsk/vulkan/gskvulkanrenderpass.c
+++ b/gsk/vulkan/gskvulkanrenderpass.c
@@ -259,6 +259,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
case GSK_SHADOW_NODE:
case GSK_RADIAL_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
+ case GSK_CONIC_GRADIENT_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 dd9a1de67e..7e07e4413a 100644
--- a/gtk/inspector/recorder.c
+++ b/gtk/inspector/recorder.c
@@ -133,6 +133,7 @@ create_list_model_for_render_node (GskRenderNode *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:
@@ -259,6 +260,8 @@ node_type_name (GskRenderNodeType type)
return "Radial Gradient";
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
return "Repeating Radial Gradient";
+ case GSK_CONIC_GRADIENT_NODE:
+ return "Conic Gradient";
case GSK_BORDER_NODE:
return "Border";
case GSK_TEXTURE_NODE:
@@ -308,6 +311,7 @@ node_name (GskRenderNode *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:
@@ -729,6 +733,44 @@ populate_render_node_properties (GtkListStore *store,
}
break;
+ case GSK_CONIC_GRADIENT_NODE:
+ {
+ const graphene_point_t *center = gsk_conic_gradient_node_get_center (node);
+ const float rotation = gsk_conic_gradient_node_get_rotation (node);
+ const gsize n_stops = gsk_conic_gradient_node_get_n_color_stops (node);
+ const GskColorStop *stops = gsk_conic_gradient_node_get_color_stops (node, NULL);
+ gsize i;
+ GString *s;
+ GdkTexture *texture;
+
+ tmp = g_strdup_printf ("%.2f, %.2f", center->x, center->y);
+ add_text_row (store, "Center", tmp);
+ g_free (tmp);
+
+ tmp = g_strdup_printf ("%.2f", rotation);
+ add_text_row (store, "Rotation", tmp);
+ g_free (tmp);
+
+ s = g_string_new ("");
+ for (i = 0; i < n_stops; i++)
+ {
+ tmp = gdk_rgba_to_string (&stops[i].color);
+ g_string_append_printf (s, "%.2f, %s\n", stops[i].offset, tmp);
+ g_free (tmp);
+ }
+
+ texture = get_linear_gradient_texture (n_stops, stops);
+ gtk_list_store_insert_with_values (store, NULL, -1,
+ 0, "Color Stops",
+ 1, s->str,
+ 2, TRUE,
+ 3, texture,
+ -1);
+ g_string_free (s, TRUE);
+ g_object_unref (texture);
+ }
+ break;
+
case GSK_TEXT_NODE:
{
const PangoFont *font = gsk_text_node_get_font (node);