From 1f1e41bdaa202a81bb39d1e765cdbce7bbaee37a Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 13 Jun 2024 01:10:15 -0400 Subject: [PATCH] Introduce GskColorStop2 --- gsk/gskrendernode.h | 39 +++++- gsk/gskrendernodeimpl.c | 275 +++++++++++++++++++++++++++++++------- gsk/gskrendernodeparser.c | 114 ++++++---------- 3 files changed, 300 insertions(+), 128 deletions(-) diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h index 128b91ca94..20adc7f60d 100644 --- a/gsk/gskrendernode.h +++ b/gsk/gskrendernode.h @@ -36,6 +36,7 @@ G_BEGIN_DECLS #define GSK_SERIALIZATION_ERROR (gsk_serialization_error_quark ()) typedef struct _GskColorStop GskColorStop; +typedef struct _GskColorStop2 GskColorStop2; typedef struct _GskShadow GskShadow; /** @@ -51,6 +52,21 @@ struct _GskColorStop GdkRGBA color; }; +/** + * GskColorStop2: + * @offset: the offset of the color stop + * @color: the color at the given offset + * + * A color stop in a gradient node. + * + * Since: 4.16 + */ +struct _GskColorStop2 +{ + float offset; + GdkColor color; +}; + /** * GskShadow: * @color: the color of the shadow @@ -260,7 +276,7 @@ GskRenderNode * gsk_linear_gradient_node_new2 (const graph const graphene_point_t *end, GdkColorState *in, GskHueInterpolation hue_interp, - const GskColorStop *color_stops, + const GskColorStop2 *color_stops, gsize n_color_stops); GDK_AVAILABLE_IN_ALL @@ -273,6 +289,10 @@ GDK_AVAILABLE_IN_ALL const GskColorStop * gsk_linear_gradient_node_get_color_stops (const GskRenderNode *node, gsize *n_stops); +GDK_AVAILABLE_IN_4_16 +const GskColorStop2 * gsk_linear_gradient_node_get_color_stops2 (const GskRenderNode *node, + gsize *n_stops); + GDK_AVAILABLE_IN_4_16 GdkColorState * gsk_linear_gradient_node_get_color_state (const GskRenderNode *node) G_GNUC_PURE; GDK_AVAILABLE_IN_4_16 @@ -293,7 +313,7 @@ GskRenderNode * gsk_repeating_linear_gradient_node_new2 (const graphen const graphene_point_t *end, GdkColorState *in, GskHueInterpolation hue_interp, - const GskColorStop *color_stops, + const GskColorStop2 *color_stops, gsize n_color_stops); GDK_AVAILABLE_IN_ALL @@ -311,7 +331,7 @@ GskRenderNode * gsk_conic_gradient_node_new2 (const graph float rotation, GdkColorState *in, GskHueInterpolation hue_interp, - const GskColorStop *color_stops, + const GskColorStop2 *color_stops, gsize n_color_stops); GDK_AVAILABLE_IN_ALL @@ -326,6 +346,10 @@ GDK_AVAILABLE_IN_ALL const GskColorStop * gsk_conic_gradient_node_get_color_stops (const GskRenderNode *node, gsize *n_stops); +GDK_AVAILABLE_IN_4_16 +const GskColorStop2 * gsk_conic_gradient_node_get_color_stops2 (const GskRenderNode *node, + gsize *n_stops); + GDK_AVAILABLE_IN_4_16 GdkColorState * gsk_conic_gradient_node_get_color_state (const GskRenderNode *node) G_GNUC_PURE; GDK_AVAILABLE_IN_4_16 @@ -352,7 +376,7 @@ GskRenderNode * gsk_radial_gradient_node_new2 (const graphene_rect_t float end, GdkColorState *in, GskHueInterpolation hue_interp, - const GskColorStop *color_stops, + const GskColorStop2 *color_stops, gsize n_color_stops); GDK_AVAILABLE_IN_ALL @@ -360,6 +384,11 @@ gsize gsk_radial_gradient_node_get_n_color_stops (const GskRen GDK_AVAILABLE_IN_ALL const GskColorStop * gsk_radial_gradient_node_get_color_stops (const GskRenderNode *node, gsize *n_stops); + +GDK_AVAILABLE_IN_4_16 +const GskColorStop2 * gsk_radial_gradient_node_get_color_stops2 (const GskRenderNode *node, + gsize *n_stops); + GDK_AVAILABLE_IN_ALL const graphene_point_t *gsk_radial_gradient_node_get_center (const GskRenderNode *node) G_GNUC_PURE; GDK_AVAILABLE_IN_ALL @@ -397,7 +426,7 @@ GskRenderNode * gsk_repeating_radial_gradient_node_new2 (const graph float end, GdkColorState *in, GskHueInterpolation hue_interp, - const GskColorStop *color_stops, + const GskColorStop2 *color_stops, gsize n_color_stops); GDK_AVAILABLE_IN_ALL diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index 20a78aaeaf..b226b8e2fe 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -333,6 +333,7 @@ struct _GskLinearGradientNode gsize n_stops; GskColorStop *stops; + GskColorStop2 *stops2; }; static void @@ -342,7 +343,10 @@ gsk_linear_gradient_node_finalize (GskRenderNode *node) GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_LINEAR_GRADIENT_NODE)); gdk_color_state_unref (self->color_state); + for (int i = 0; i < self->n_stops; i++) + gdk_color_state_unref (self->stops2[i].color.color_state); g_free (self->stops); + g_free (self->stops2); parent_class->finalize (node); } @@ -429,11 +433,11 @@ gsk_linear_gradient_node_diff (GskRenderNode *node1, for (i = 0; i < self1->n_stops; i++) { - GskColorStop *stop1 = &self1->stops[i]; - GskColorStop *stop2 = &self2->stops[i]; + GskColorStop2 *stop1 = &self1->stops2[i]; + GskColorStop2 *stop2 = &self2->stops2[i]; if (stop1->offset == stop2->offset && - gdk_rgba_equal (&stop1->color, &stop2->color)) + gdk_color_equal (&stop1->color, &stop2->color)) continue; gsk_render_node_diff_impossible (node1, node2, data); @@ -495,11 +499,20 @@ gsk_linear_gradient_node_new (const graphene_rect_t *bounds, const GskColorStop *color_stops, gsize n_color_stops) { + GskColorStop2 *color_stops2; + + color_stops2 = g_newa (GskColorStop2, n_color_stops); + for (int i = 0; i < n_color_stops; i++) + { + color_stops2[i].offset = color_stops[i].offset; + gdk_color_init_from_rgba (&color_stops2[i].color, &color_stops[i].color); + } + return gsk_linear_gradient_node_new2 (bounds, start, end, GDK_COLOR_STATE_SRGB, GSK_HUE_INTERPOLATION_SHORTER, - color_stops, n_color_stops); + color_stops2, n_color_stops); } /** @@ -510,7 +523,7 @@ gsk_linear_gradient_node_new (const graphene_rect_t *bounds, * @color_state: the color state to interpolate in * @hue_interp: How to interpolate hue, in case @in is a polar color state * @color_stops: (array length=n_color_stops): a pointer to an array of - * `GskColorStop` defining the gradient. The offsets of all color stops + * `GskColorStop2` defining the gradient. The offsets of all color stops * 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 @@ -519,9 +532,7 @@ gsk_linear_gradient_node_new (const graphene_rect_t *bounds, * points and color stops, and render that into the area given by @bounds. * * This function is like [constructor@Gsk.LinearGradientNode.new], but - * additionally lets one specify the interpolation color state. The colors - * in the color stops are expected to be in that color state (despite being - * specified as GdkRGBA). + * additionally lets one specify the interpolation color state. * * Since: 4.16 * @@ -533,7 +544,7 @@ gsk_linear_gradient_node_new2 (const graphene_rect_t *bounds, const graphene_point_t *end, GdkColorState *color_state, GskHueInterpolation hue_interp, - const GskColorStop *color_stops, + const GskColorStop2 *color_stops, gsize n_color_stops) { GskLinearGradientNode *self; @@ -562,8 +573,10 @@ gsk_linear_gradient_node_new2 (const graphene_rect_t *bounds, graphene_point_init_from_point (&self->end, end); 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)); + self->stops2 = g_new (GskColorStop2, n_color_stops); + memcpy (self->stops2, color_stops, n_color_stops * sizeof (GskColorStop2)); + for (i = 0; i < n_color_stops; i++) + gdk_color_state_ref (self->stops2[i].color.color_state); self->color_state = gdk_color_state_ref (color_state); self->hue_interp = hue_interp; @@ -595,11 +608,20 @@ gsk_repeating_linear_gradient_node_new (const graphene_rect_t *bounds, const GskColorStop *color_stops, gsize n_color_stops) { + GskColorStop2 *color_stops2; + + color_stops2 = g_newa (GskColorStop2, n_color_stops); + for (int i = 0; i < n_color_stops; i++) + { + color_stops2[i].offset = color_stops[i].offset; + gdk_color_init_from_rgba (&color_stops2[i].color, &color_stops[i].color); + } + return gsk_repeating_linear_gradient_node_new2 (bounds, start, end, GDK_COLOR_STATE_SRGB, GSK_HUE_INTERPOLATION_SHORTER, - color_stops, n_color_stops); + color_stops2, n_color_stops); } /** @@ -610,7 +632,7 @@ gsk_repeating_linear_gradient_node_new (const graphene_rect_t *bounds, * @color_state: the color state to interpolate in * @hue_interp: How to interpolate hue, in case @in is a polar color state * @color_stops: (array length=n_color_stops): a pointer to an array of - * `GskColorStop` defining the gradient. The offsets of all color stops + * `GskColorStop2` defining the gradient. The offsets of all color stops * 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 @@ -620,9 +642,7 @@ gsk_repeating_linear_gradient_node_new (const graphene_rect_t *bounds, * given by @bounds. * * This function is like [constructor@Gsk.RepeatingLinearGradientNode.new], - * but additionally lets one specify the interpolation color state. The colors - * in the color stops are expected to be in that color state (despite being - * specified as GdkRGBA). + * but additionally lets one specify the interpolation color state. * * Since: 4.16 * @@ -634,7 +654,7 @@ gsk_repeating_linear_gradient_node_new2 (const graphene_rect_t *bounds, const graphene_point_t *end, GdkColorState *color_state, GskHueInterpolation hue_interp, - const GskColorStop *color_stops, + const GskColorStop2 *color_stops, gsize n_color_stops) { GskLinearGradientNode *self; @@ -661,9 +681,11 @@ gsk_repeating_linear_gradient_node_new2 (const graphene_rect_t *bounds, graphene_point_init_from_point (&self->start, start); graphene_point_init_from_point (&self->end, end); - self->stops = g_malloc_n (n_color_stops, sizeof (GskColorStop)); - memcpy (self->stops, color_stops, n_color_stops * sizeof (GskColorStop)); self->n_stops = n_color_stops; + self->stops2 = g_new (GskColorStop2, n_color_stops); + memcpy (self->stops2, color_stops, n_color_stops * sizeof (GskColorStop2)); + for (i = 0; i < n_color_stops; i++) + gdk_color_state_ref (self->stops2[i].color.color_state); self->color_state = gdk_color_state_ref (color_state); self->hue_interp = hue_interp; @@ -731,13 +753,53 @@ gsk_linear_gradient_node_get_n_color_stops (const GskRenderNode *node) const GskColorStop * gsk_linear_gradient_node_get_color_stops (const GskRenderNode *node, gsize *n_stops) +{ + GskLinearGradientNode *self = (GskLinearGradientNode *) node; + + if (n_stops != NULL) + *n_stops = self->n_stops; + + if (!self->stops) + { + self->stops = g_new (GskColorStop, self->n_stops); + for (int i = 0; i < self->n_stops; i++) + { + GdkColor color; + + gdk_color_convert (&color, GDK_COLOR_STATE_SRGB, &self->stops2[i].color); + + self->stops[i].color.red = color.values[0]; + self->stops[i].color.green = color.values[1]; + self->stops[i].color.blue = color.values[2]; + self->stops[i].color.alpha = color.values[3]; + self->stops[i].offset = self->stops2[i].offset; + } + } + + return self->stops; +} + +/** + * gsk_linear_gradient_node_get_color_stops2: + * @node: (type GskLinearGradientNode): a `GskRenderNode` for a linear 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 + * + * Since: 4.16 + */ +const GskColorStop2 * +gsk_linear_gradient_node_get_color_stops2 (const GskRenderNode *node, + gsize *n_stops) { const GskLinearGradientNode *self = (const GskLinearGradientNode *) node; if (n_stops != NULL) *n_stops = self->n_stops; - return self->stops; + return self->stops2; } /** @@ -806,6 +868,7 @@ struct _GskRadialGradientNode gsize n_stops; GskColorStop *stops; + GskColorStop2 *stops2; }; static void @@ -815,7 +878,10 @@ gsk_radial_gradient_node_finalize (GskRenderNode *node) GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_RADIAL_GRADIENT_NODE)); gdk_color_state_unref (self->color_state); + for (int i = 0; i < self->n_stops; i++) + gdk_color_state_unref (self->stops2[i].color.color_state); g_free (self->stops); + g_free (self->stops2); parent_class->finalize (node); } @@ -916,11 +982,11 @@ gsk_radial_gradient_node_diff (GskRenderNode *node1, for (i = 0; i < self1->n_stops; i++) { - GskColorStop *stop1 = &self1->stops[i]; - GskColorStop *stop2 = &self2->stops[i]; + GskColorStop2 *stop1 = &self1->stops2[i]; + GskColorStop2 *stop2 = &self2->stops2[i]; if (stop1->offset == stop2->offset && - gdk_rgba_equal (&stop1->color, &stop2->color)) + gdk_color_equal (&stop1->color, &stop2->color)) continue; gsk_render_node_diff_impossible (node1, node2, data); @@ -991,12 +1057,21 @@ gsk_radial_gradient_node_new (const graphene_rect_t *bounds, const GskColorStop *color_stops, gsize n_color_stops) { + GskColorStop2 *color_stops2; + + color_stops2 = g_newa (GskColorStop2, n_color_stops); + for (int i = 0; i < n_color_stops; i++) + { + color_stops2[i].offset = color_stops[i].offset; + gdk_color_init_from_rgba (&color_stops2[i].color, &color_stops[i].color); + } + return gsk_radial_gradient_node_new2 (bounds, center, hradius, vradius, start, end, GDK_COLOR_STATE_SRGB, GSK_HUE_INTERPOLATION_SHORTER, - color_stops, n_color_stops); + color_stops2, n_color_stops); } /** @@ -1010,7 +1085,7 @@ gsk_radial_gradient_node_new (const graphene_rect_t *bounds, * @color_state: the color state to interpolate in * @hue_interp: How to interpolate hue, in case @in is a polar color state * @color_stops: (array length=n_color_stops): a pointer to an array of - * `GskColorStop` defining the gradient. The offsets of all color stops + * `GskColorStop2` defining the gradient. The offsets of all color stops * 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 @@ -1022,9 +1097,7 @@ gsk_radial_gradient_node_new (const graphene_rect_t *bounds, * in horizontal orientation and by @vradius in vertical orientation. * * This function is like [constructor@Gsk.RadialGradientNode.new], but - * additionally lets one specify the interpolation color state. The colors - * in the color stops are expected to be in that color state (despite being - * specified as GdkRGBA). + * additionally lets one specify the interpolation color state. * * Since: 4.16 * @@ -1039,7 +1112,7 @@ gsk_radial_gradient_node_new2 (const graphene_rect_t *bounds, float end, GdkColorState *color_state, GskHueInterpolation hue_interp, - const GskColorStop *color_stops, + const GskColorStop2 *color_stops, gsize n_color_stops) { @@ -1076,8 +1149,10 @@ gsk_radial_gradient_node_new2 (const graphene_rect_t *bounds, self->end = end; 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)); + self->stops2 = g_new (GskColorStop2, n_color_stops); + memcpy (self->stops2, color_stops, n_color_stops * sizeof (GskColorStop2)); + for (i = 0; i < n_color_stops; i++) + gdk_color_state_ref (self->stops2[i].color.color_state); self->color_state = gdk_color_state_ref (color_state); self->hue_interp = hue_interp; @@ -1117,12 +1192,21 @@ gsk_repeating_radial_gradient_node_new (const graphene_rect_t *bounds, const GskColorStop *color_stops, gsize n_color_stops) { + GskColorStop2 *color_stops2; + + color_stops2 = g_newa (GskColorStop2, n_color_stops); + for (int i = 0; i < n_color_stops; i++) + { + color_stops2[i].offset = color_stops[i].offset; + gdk_color_init_from_rgba (&color_stops2[i].color, &color_stops[i].color); + } + return gsk_repeating_radial_gradient_node_new2 (bounds, center, hradius, vradius, start, end, GDK_COLOR_STATE_SRGB, GSK_HUE_INTERPOLATION_SHORTER, - color_stops, n_color_stops); + color_stops2, n_color_stops); } /** @@ -1136,7 +1220,7 @@ gsk_repeating_radial_gradient_node_new (const graphene_rect_t *bounds, * @color_state: the color state to interpolate in * @hue_interp: How to interpolate hue, in case @in is a polar color state * @color_stops: (array length=n_color_stops): a pointer to an array of - * `GskColorStop` defining the gradient. The offsets of all color stops + * `GskColorStop2` defining the gradient. The offsets of all color stops * 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 @@ -1148,9 +1232,7 @@ gsk_repeating_radial_gradient_node_new (const graphene_rect_t *bounds, * in vertical orientation. * * This function is like [constructor@Gsk.RepeatingRadialGradientNode.new], - * but additionally lets one specify the interpolation color state. The colors - * in the color stops are expected to be in that color state (despite being - * specified as GdkRGBA). + * but additionally lets one specify the interpolation color state. * * Since: 4.16 * @@ -1165,7 +1247,7 @@ gsk_repeating_radial_gradient_node_new2 (const graphene_rect_t *bounds, float end, GdkColorState *color_state, GskHueInterpolation hue_interp, - const GskColorStop *color_stops, + const GskColorStop2 *color_stops, gsize n_color_stops) { GskRadialGradientNode *self; @@ -1201,8 +1283,10 @@ gsk_repeating_radial_gradient_node_new2 (const graphene_rect_t *bounds, self->end = end; 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)); + self->stops2 = g_new (GskColorStop2, n_color_stops); + memcpy (self->stops2, color_stops, n_color_stops * sizeof (GskColorStop2)); + for (i = 0; i < n_color_stops; i++) + gdk_color_state_ref (self->stops2[i].color.color_state); self->color_state = gdk_color_state_ref (color_state); self->hue_interp = hue_interp; @@ -1238,13 +1322,53 @@ gsk_radial_gradient_node_get_n_color_stops (const GskRenderNode *node) const GskColorStop * gsk_radial_gradient_node_get_color_stops (const GskRenderNode *node, gsize *n_stops) +{ + GskRadialGradientNode *self = (GskRadialGradientNode *) node; + + if (n_stops != NULL) + *n_stops = self->n_stops; + + if (!self->stops) + { + self->stops = g_new (GskColorStop, self->n_stops); + for (int i = 0; i < self->n_stops; i++) + { + GdkColor color; + + gdk_color_convert (&color, GDK_COLOR_STATE_SRGB, &self->stops2[i].color); + + self->stops[i].color.red = color.values[0]; + self->stops[i].color.green = color.values[1]; + self->stops[i].color.blue = color.values[2]; + self->stops[i].color.alpha = color.values[3]; + self->stops[i].offset = self->stops2[i].offset; + } + } + + return self->stops; +} + +/** + * gsk_radial_gradient_node_get_color_stops2: + * @node: (type GskRadialGradientNode): a `GskRenderNode` for a radial 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 + * + * Since: 4.16 + */ +const GskColorStop2 * +gsk_radial_gradient_node_get_color_stops2 (const GskRenderNode *node, + gsize *n_stops) { const GskRadialGradientNode *self = (const GskRadialGradientNode *) node; if (n_stops != NULL) *n_stops = self->n_stops; - return self->stops; + return self->stops2; } /** @@ -1385,6 +1509,7 @@ struct _GskConicGradientNode gsize n_stops; GskColorStop *stops; + GskColorStop2 *stops2; }; static void @@ -1394,7 +1519,10 @@ gsk_conic_gradient_node_finalize (GskRenderNode *node) GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_CONIC_GRADIENT_NODE)); gdk_color_state_unref (self->color_state); + for (int i = 0; i < self->n_stops; i++) + gdk_color_state_unref (self->stops2[i].color.color_state); g_free (self->stops); + g_free (self->stops2); parent_class->finalize (node); } @@ -1604,11 +1732,20 @@ gsk_conic_gradient_node_new (const graphene_rect_t *bounds, const GskColorStop *color_stops, gsize n_color_stops) { + GskColorStop2 *color_stops2; + + color_stops2 = g_newa (GskColorStop2, n_color_stops); + for (int i = 0; i < n_color_stops; i++) + { + color_stops2[i].offset = color_stops[i].offset; + gdk_color_init_from_rgba (&color_stops2[i].color, &color_stops[i].color); + } + return gsk_conic_gradient_node_new2 (bounds, center, rotation, GDK_COLOR_STATE_SRGB, GSK_HUE_INTERPOLATION_SHORTER, - color_stops, n_color_stops); + color_stops2, n_color_stops); } /** @@ -1619,7 +1756,7 @@ gsk_conic_gradient_node_new (const graphene_rect_t *bounds, * @color_state: the color state to interpolate in * @hue_interp: How to interpolate hue, in case @in is a polar color state * @color_stops: (array length=n_color_stops): a pointer to an array of - * `GskColorStop` defining the gradient. The offsets of all color stops + * `GskColorStop2` defining the gradient. The offsets of all color stops * 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 @@ -1631,9 +1768,7 @@ gsk_conic_gradient_node_new (const graphene_rect_t *bounds, * that the gradient points up. Color stops are then added clockwise. * * This function is like [constructor@Gsk.ConicGradientNode.new], - * but additionally lets one specify the interpolation color state. The colors - * in the color stops are expected to be in that color state (despite being - * specified as GdkRGBA). + * but additionally lets one specify the interpolation color state. * * Since: 4.16 * @@ -1645,7 +1780,7 @@ gsk_conic_gradient_node_new2 (const graphene_rect_t *bounds, float rotation, GdkColorState *color_state, GskHueInterpolation hue_interp, - const GskColorStop *color_stops, + const GskColorStop2 *color_stops, gsize n_color_stops) { GskConicGradientNode *self; @@ -1673,8 +1808,10 @@ gsk_conic_gradient_node_new2 (const graphene_rect_t *bounds, 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)); + self->stops2 = g_new (GskColorStop2, n_color_stops); + memcpy (self->stops2, color_stops, n_color_stops * sizeof (GskColorStop2)); + for (i = 0; i < n_color_stops; i++) + gdk_color_state_ref (self->stops2[i].color.color_state); self->angle = 90.f - self->rotation; self->angle = G_PI * self->angle / 180.f; @@ -1716,13 +1853,53 @@ gsk_conic_gradient_node_get_n_color_stops (const GskRenderNode *node) const GskColorStop * gsk_conic_gradient_node_get_color_stops (const GskRenderNode *node, gsize *n_stops) +{ + GskConicGradientNode *self = (GskConicGradientNode *) node; + + if (n_stops != NULL) + *n_stops = self->n_stops; + + if (!self->stops) + { + self->stops = g_new (GskColorStop, self->n_stops); + for (int i = 0; i < self->n_stops; i++) + { + GdkColor color; + + gdk_color_convert (&color, GDK_COLOR_STATE_SRGB, &self->stops2[i].color); + + self->stops[i].color.red = color.values[0]; + self->stops[i].color.green = color.values[1]; + self->stops[i].color.blue = color.values[2]; + self->stops[i].color.alpha = color.values[3]; + self->stops[i].offset = self->stops2[i].offset; + } + } + + return self->stops; +} + +/** + * gsk_conic_gradient_node_get_color_stops2: + * @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 + * + * Since: 4.16 + */ +const GskColorStop2 * +gsk_conic_gradient_node_get_color_stops2 (const GskRenderNode *node, + gsize *n_stops) { const GskConicGradientNode *self = (const GskConicGradientNode *) node; if (n_stops != NULL) *n_stops = self->n_stops; - return self->stops; + return self->stops2; } /** diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c index c1c685b608..a5d51cb56e 100644 --- a/gsk/gskrendernodeparser.c +++ b/gsk/gskrendernodeparser.c @@ -606,9 +606,9 @@ parse_stops (GtkCssParser *parser, gpointer out_stops) { GArray *stops; - GskColorStop stop; + GskColorStop2 stop; - stops = g_array_new (FALSE, FALSE, sizeof (GskColorStop)); + stops = g_array_new (FALSE, FALSE, sizeof (GskColorStop2)); for (;;) { @@ -619,7 +619,7 @@ parse_stops (GtkCssParser *parser, stop.offset = dval; - if (!gdk_rgba_parser_parse (parser, &stop.color)) + if (!gdk_color_parser_parse (parser, &stop.color)) goto error; if (stops->len == 0 && stop.offset < 0) @@ -1590,27 +1590,6 @@ parse_hue_interpolation (GtkCssParser *parser, return parse_enum (parser, GSK_TYPE_HUE_INTERPOLATION, out_hue_interp); } -static void -convert_color_stops (GskColorStop *stops, - guint n_stops, - GdkColorState *color_state) -{ - if (!gdk_color_state_equal (color_state, gdk_color_state_get_srgb ())) - { - for (guint i = 0; i < n_stops; i++) - { - GdkColor col; - - gdk_color_convert_rgba (&col, color_state, &stops[i].color); - - stops[i].color.red = col.values[0]; - stops[i].color.green = col.values[1]; - stops[i].color.blue = col.values[2]; - stops[i].color.alpha = col.values[3]; - } - } -} - static GskRenderNode * parse_linear_gradient_node_internal (GtkCssParser *parser, Context *context, @@ -1635,10 +1614,14 @@ parse_linear_gradient_node_internal (GtkCssParser *parser, parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations)); if (stops == NULL) { - GskColorStop from = { 0.0, GDK_RGBA("AAFF00") }; - GskColorStop to = { 1.0, GDK_RGBA("FF00CC") }; + GskColorStop2 from, to; - stops = g_array_new (FALSE, FALSE, sizeof (GskColorStop)); + from.offset = 0; + to.offset = 1; + gdk_color_init_from_rgba (&from.color, &GDK_RGBA ("AAFF00")); + gdk_color_init_from_rgba (&to.color, &GDK_RGBA ("FF00CC")); + + stops = g_array_new (FALSE, FALSE, sizeof (GskColorStop2)); g_array_append_val (stops, from); g_array_append_val (stops, to); } @@ -1646,18 +1629,16 @@ parse_linear_gradient_node_internal (GtkCssParser *parser, if (color_state == NULL) color_state = gdk_color_state_get_srgb (); - convert_color_stops ((GskColorStop *) stops->data, stops->len, color_state); - if (repeating) result = gsk_repeating_linear_gradient_node_new2 (&bounds, &start, &end, color_state, hue_interp, - (GskColorStop *) stops->data, stops->len); + (GskColorStop2 *) stops->data, stops->len); else result = gsk_linear_gradient_node_new2 (&bounds, &start, &end, color_state, hue_interp, - (GskColorStop *) stops->data, stops->len); + (GskColorStop2 *) stops->data, stops->len); gdk_color_state_unref (color_state); g_array_free (stops, TRUE); @@ -1709,10 +1690,14 @@ parse_radial_gradient_node_internal (GtkCssParser *parser, parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations)); if (stops == NULL) { - GskColorStop from = { 0.0, GDK_RGBA("AAFF00") }; - GskColorStop to = { 1.0, GDK_RGBA("FF00CC") }; + GskColorStop2 from, to; - stops = g_array_new (FALSE, FALSE, sizeof (GskColorStop)); + from.offset = 0; + to.offset = 1; + gdk_color_init_from_rgba (&from.color, &GDK_RGBA ("AAFF00")); + gdk_color_init_from_rgba (&to.color, &GDK_RGBA ("FF00CC")); + + stops = g_array_new (FALSE, FALSE, sizeof (GskColorStop2)); g_array_append_val (stops, from); g_array_append_val (stops, to); } @@ -1720,20 +1705,18 @@ parse_radial_gradient_node_internal (GtkCssParser *parser, if (color_state == NULL) color_state = gdk_color_state_get_srgb (); - convert_color_stops ((GskColorStop *) stops->data, stops->len, color_state); - if (repeating) result = gsk_repeating_radial_gradient_node_new2 (&bounds, ¢er, hradius, vradius, start, end, color_state, hue_interp, - (GskColorStop *) stops->data, stops->len); + (GskColorStop2 *) stops->data, stops->len); else result = gsk_radial_gradient_node_new2 (&bounds, ¢er, hradius, vradius, start, end, color_state, hue_interp, - (GskColorStop *) stops->data, stops->len); + (GskColorStop2 *) stops->data, stops->len); gdk_color_state_unref (color_state); g_array_free (stops, TRUE); @@ -1778,10 +1761,14 @@ parse_conic_gradient_node (GtkCssParser *parser, parse_declarations (parser, context, declarations, G_N_ELEMENTS (declarations)); if (stops == NULL) { - GskColorStop from = { 0.0, GDK_RGBA("AAFF00") }; - GskColorStop to = { 1.0, GDK_RGBA("FF00CC") }; + GskColorStop2 from, to; - stops = g_array_new (FALSE, FALSE, sizeof (GskColorStop)); + from.offset = 0; + to.offset = 1; + gdk_color_init_from_rgba (&from.color, &GDK_RGBA ("AAFF00")); + gdk_color_init_from_rgba (&to.color, &GDK_RGBA ("FF00CC")); + + stops = g_array_new (FALSE, FALSE, sizeof (GskColorStop2)); g_array_append_val (stops, from); g_array_append_val (stops, to); } @@ -1789,11 +1776,9 @@ parse_conic_gradient_node (GtkCssParser *parser, if (color_state == NULL) color_state = gdk_color_state_get_srgb (); - convert_color_stops ((GskColorStop *) stops->data, stops->len, color_state); - result = gsk_conic_gradient_node_new2 (&bounds, ¢er, rotation, color_state, hue_interp, - (GskColorStop *) stops->data, stops->len); + (GskColorStop2 *) stops->data, stops->len); gdk_color_state_unref (color_state); g_array_free (stops, TRUE); @@ -3688,11 +3673,10 @@ append_node_param (Printer *p, } static void -append_stops_param (Printer *p, - const char *param_name, - const GskColorStop *stops, - gsize n_stops, - GdkColorState *color_state) +append_stops_param (Printer *p, + const char *param_name, + const GskColorStop2 *stops, + gsize n_stops) { gsize i; @@ -3702,27 +3686,12 @@ append_stops_param (Printer *p, for (i = 0; i < n_stops; i ++) { - GdkRGBA color = stops[i].color; - - if (!gdk_color_state_equal (color_state, gdk_color_state_get_srgb ())) - { - GdkColor col, col2; - - gdk_color_init (&col, color_state, - (float[4]) { color.red, color.green, color.blue, color.alpha }); - gdk_color_convert (&col2, gdk_color_state_get_srgb (), &col); - color.red = col2.values[0]; - color.green = col2.values[1]; - color.blue = col2.values[2]; - color.alpha = col2.values[3]; - } - if (i > 0) g_string_append (p->str, ", "); string_append_double (p->str, stops[i].offset); g_string_append_c (p->str, ' '); - gdk_rgba_print (&color, p->str); + gdk_color_print (&stops[i].color, p->str); } g_string_append (p->str, ";\n"); } @@ -4242,9 +4211,8 @@ render_node_print (Printer *p, append_point_param (p, "end", gsk_linear_gradient_node_get_end (node)); append_color_state (p, "color-state", gsk_linear_gradient_node_get_color_state (node)); append_hue_interpolation (p, "hue-interpolation", gsk_linear_gradient_node_get_hue_interpolation (node)); - append_stops_param (p, "stops", gsk_linear_gradient_node_get_color_stops (node, NULL), - gsk_linear_gradient_node_get_n_color_stops (node), - gsk_linear_gradient_node_get_color_state (node)); + append_stops_param (p, "stops", gsk_linear_gradient_node_get_color_stops2 (node, NULL), + gsk_linear_gradient_node_get_n_color_stops (node)); end_node (p); } @@ -4267,9 +4235,8 @@ render_node_print (Printer *p, append_color_state (p, "color-state", gsk_radial_gradient_node_get_color_state (node)); append_hue_interpolation (p, "hue-interpolation", gsk_radial_gradient_node_get_hue_interpolation (node)); - append_stops_param (p, "stops", gsk_radial_gradient_node_get_color_stops (node, NULL), - gsk_radial_gradient_node_get_n_color_stops (node), - gsk_radial_gradient_node_get_color_state (node)); + append_stops_param (p, "stops", gsk_radial_gradient_node_get_color_stops2 (node, NULL), + gsk_radial_gradient_node_get_n_color_stops (node)); end_node (p); } @@ -4285,9 +4252,8 @@ render_node_print (Printer *p, append_color_state (p, "color-state", gsk_conic_gradient_node_get_color_state (node)); append_hue_interpolation (p, "hue-interpolation", gsk_conic_gradient_node_get_hue_interpolation (node)); - append_stops_param (p, "stops", gsk_conic_gradient_node_get_color_stops (node, NULL), - gsk_conic_gradient_node_get_n_color_stops (node), - gsk_conic_gradient_node_get_color_state (node)); + append_stops_param (p, "stops", gsk_conic_gradient_node_get_color_stops2 (node, NULL), + gsk_conic_gradient_node_get_n_color_stops (node)); end_node (p); }