gsk: Add private border node api

Add a constructor that takes GdkColors, and a getter for those.

To support the existing api, we convert the colors to GdkRGBA
as needed.
This commit is contained in:
Matthias Clasen 2024-08-01 22:58:17 -04:00
parent f3ffa99f6a
commit bd3d1f7715
2 changed files with 117 additions and 27 deletions

View File

@ -61,6 +61,11 @@
*/
#define MAX_RECTS_IN_DIFF 30
/* This lock protects all on-demand created legacy rgba data of
* render nodes.
*/
G_LOCK_DEFINE_STATIC (rgba);
static gboolean
gsk_color_stops_are_opaque (const GskColorStop *stops,
gsize n_stops)
@ -1438,13 +1443,28 @@ struct _GskBorderNode
bool uniform_color: 1;
GskRoundedRect outline;
float border_width[4];
GdkRGBA border_color[4];
GdkColor border_color[4];
GdkRGBA *border_rgba;
};
static void
gsk_border_node_finalize (GskRenderNode *node)
{
GskBorderNode *self = (GskBorderNode *) node;
GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_BORDER_NODE));
for (int i = 0; i < 4; i++)
gdk_color_finish (&self->border_color[i]);
g_free (self->border_rgba);
parent_class->finalize (node);
}
static void
gsk_border_node_mesh_add_patch (cairo_pattern_t *pattern,
GdkColorState *ccs,
const GdkRGBA *rgba,
const GdkColor *color,
double x0,
double y0,
double x1,
@ -1454,18 +1474,19 @@ gsk_border_node_mesh_add_patch (cairo_pattern_t *pattern,
double x3,
double y3)
{
float color[4];
float values[4];
gdk_color_to_float (color, ccs, values);
gdk_color_state_from_rgba (ccs, rgba, color);
cairo_mesh_pattern_begin_patch (pattern);
cairo_mesh_pattern_move_to (pattern, x0, y0);
cairo_mesh_pattern_line_to (pattern, x1, y1);
cairo_mesh_pattern_line_to (pattern, x2, y2);
cairo_mesh_pattern_line_to (pattern, x3, y3);
cairo_mesh_pattern_set_corner_color_rgba (pattern, 0, color[0], color[1], color[2], color[3]);
cairo_mesh_pattern_set_corner_color_rgba (pattern, 1, color[0], color[1], color[2], color[3]);
cairo_mesh_pattern_set_corner_color_rgba (pattern, 2, color[0], color[1], color[2], color[3]);
cairo_mesh_pattern_set_corner_color_rgba (pattern, 3, color[0], color[1], color[2], color[3]);
cairo_mesh_pattern_set_corner_color_rgba (pattern, 0, values[0], values[1], values[2], values[3]);
cairo_mesh_pattern_set_corner_color_rgba (pattern, 1, values[0], values[1], values[2], values[3]);
cairo_mesh_pattern_set_corner_color_rgba (pattern, 2, values[0], values[1], values[2], values[3]);
cairo_mesh_pattern_set_corner_color_rgba (pattern, 3, values[0], values[1], values[2], values[3]);
cairo_mesh_pattern_end_patch (pattern);
}
@ -1488,11 +1509,11 @@ gsk_border_node_draw (GskRenderNode *node,
gsk_rounded_rect_path (&self->outline, cr);
gsk_rounded_rect_path (&inside, cr);
if (gdk_rgba_equal (&self->border_color[0], &self->border_color[1]) &&
gdk_rgba_equal (&self->border_color[0], &self->border_color[2]) &&
gdk_rgba_equal (&self->border_color[0], &self->border_color[3]))
if (gdk_color_equal (&self->border_color[0], &self->border_color[1]) &&
gdk_color_equal (&self->border_color[0], &self->border_color[2]) &&
gdk_color_equal (&self->border_color[0], &self->border_color[3]))
{
gdk_cairo_set_source_rgba_ccs (cr, ccs, &self->border_color[0]);
gdk_cairo_set_source_color (cr, ccs, &self->border_color[0]);
}
else
{
@ -1600,7 +1621,7 @@ gsk_border_node_diff (GskRenderNode *node1,
uniform2 &&
self1->border_width[0] == self2->border_width[0] &&
gsk_rounded_rect_equal (&self1->outline, &self2->outline) &&
gdk_rgba_equal (&self1->border_color[0], &self2->border_color[0]))
gdk_color_equal (&self1->border_color[0], &self2->border_color[0]))
return;
/* Different uniformity -> diff impossible */
@ -1614,10 +1635,10 @@ gsk_border_node_diff (GskRenderNode *node1,
self1->border_width[1] == self2->border_width[1] &&
self1->border_width[2] == self2->border_width[2] &&
self1->border_width[3] == self2->border_width[3] &&
gdk_rgba_equal (&self1->border_color[0], &self2->border_color[0]) &&
gdk_rgba_equal (&self1->border_color[1], &self2->border_color[1]) &&
gdk_rgba_equal (&self1->border_color[2], &self2->border_color[2]) &&
gdk_rgba_equal (&self1->border_color[3], &self2->border_color[3]) &&
gdk_color_equal (&self1->border_color[0], &self2->border_color[0]) &&
gdk_color_equal (&self1->border_color[1], &self2->border_color[1]) &&
gdk_color_equal (&self1->border_color[2], &self2->border_color[2]) &&
gdk_color_equal (&self1->border_color[3], &self2->border_color[3]) &&
gsk_rounded_rect_equal (&self1->outline, &self2->outline))
return;
@ -1632,6 +1653,7 @@ gsk_border_node_class_init (gpointer g_class,
node_class->node_type = GSK_BORDER_NODE;
node_class->finalize = gsk_border_node_finalize;
node_class->draw = gsk_border_node_draw;
node_class->diff = gsk_border_node_diff;
}
@ -1682,9 +1704,23 @@ gsk_border_node_get_widths (const GskRenderNode *node)
const GdkRGBA *
gsk_border_node_get_colors (const GskRenderNode *node)
{
const GskBorderNode *self = (const GskBorderNode *) node;
GskBorderNode *self = (GskBorderNode *) node;
const GdkRGBA *colors;
return self->border_color;
G_LOCK (rgba);
if (self->border_rgba == NULL)
{
self->border_rgba = g_new (GdkRGBA, 4);
for (int i = 0; i < 4; i++)
gdk_color_to_float (&self->border_color[i], GDK_COLOR_STATE_SRGB, (float *) &self->border_rgba[i]);
}
colors = self->border_rgba;
G_UNLOCK (rgba);
return colors;
}
/**
@ -1706,6 +1742,37 @@ GskRenderNode *
gsk_border_node_new (const GskRoundedRect *outline,
const float border_width[4],
const GdkRGBA border_color[4])
{
GdkColor color[4];
for (int i = 0; i < 4; i++)
gdk_color_init_from_rgba (&color[i], &border_color[i]);
return gsk_border_node_new2 (outline, border_width, color);
for (int i = 0; i < 4; i++)
gdk_color_finish (&color[i]);
}
/*< private >
* gsk_border_node_new2:
* @outline: a `GskRoundedRect` describing the outline of the border
* @border_width: (array fixed-size=4): the stroke width of the border on
* the top, right, bottom and left side respectively.
* @border_color: (array fixed-size=4): the color used on the top, right,
* bottom and left side.
*
* Creates a `GskRenderNode` that will stroke a border rectangle inside the
* given @outline.
*
* The 4 sides of the border can have different widths and colors.
*
* Returns: (transfer full) (type GskBorderNode): A new `GskRenderNode`
*/
GskRenderNode *
gsk_border_node_new2 (const GskRoundedRect *outline,
const float border_width[4],
const GdkColor border_color[4])
{
GskBorderNode *self;
GskRenderNode *node;
@ -1718,14 +1785,16 @@ gsk_border_node_new (const GskRoundedRect *outline,
node = (GskRenderNode *) self;
node->offscreen_for_opacity = FALSE;
node->preferred_depth = gdk_memory_depth_merge (
gdk_memory_depth_merge (my_color_get_depth (&border_color[0]),
my_color_get_depth (&border_color[1])),
gdk_memory_depth_merge (my_color_get_depth (&border_color[2]),
my_color_get_depth (&border_color[3])));
gdk_memory_depth_merge (gdk_color_get_depth (&border_color[0]),
gdk_color_get_depth (&border_color[1])),
gdk_memory_depth_merge (gdk_color_get_depth (&border_color[2]),
gdk_color_get_depth (&border_color[3])));
gsk_rounded_rect_init_copy (&self->outline, outline);
memcpy (self->border_width, border_width, sizeof (self->border_width));
memcpy (self->border_color, border_color, sizeof (self->border_color));
for (int i = 0; i < 4; i++)
gdk_color_init_copy (&self->border_color[i], &border_color[i]);
if (border_width[0] == border_width[1] &&
border_width[0] == border_width[2] &&
@ -1734,9 +1803,9 @@ gsk_border_node_new (const GskRoundedRect *outline,
else
self->uniform_width = FALSE;
if (gdk_rgba_equal (&border_color[0], &border_color[1]) &&
gdk_rgba_equal (&border_color[0], &border_color[2]) &&
gdk_rgba_equal (&border_color[0], &border_color[3]))
if (gdk_color_equal (&border_color[0], &border_color[1]) &&
gdk_color_equal (&border_color[0], &border_color[2]) &&
gdk_color_equal (&border_color[0], &border_color[3]))
self->uniform_color = TRUE;
else
self->uniform_color = FALSE;
@ -1746,7 +1815,23 @@ gsk_border_node_new (const GskRoundedRect *outline,
return node;
}
/* Private */
/*< private >
* gsk_border_node_get_colors2:
* @node: (type GskBorderNode): a `GskRenderNode` for a border
*
* Retrieves the colors of the border.
*
* Returns: (transfer none): an array of 4 `GdkColor` structs
* for the top, right, bottom and left color of the border
*/
const GdkColor *
gsk_border_node_get_colors2 (const GskRenderNode *node)
{
const GskBorderNode *self = (const GskBorderNode *) node;
return self->border_color;
}
bool
gsk_border_node_get_uniform (const GskRenderNode *self)
{

View File

@ -126,5 +126,10 @@ GskRenderNode * gsk_color_node_new2 (const GdkColor *
const GdkColor* gsk_color_node_get_color2 (const GskRenderNode *node);
GskRenderNode * gsk_border_node_new2 (const GskRoundedRect *outline,
const float border_width[4],
const GdkColor border_color[4]);
const GdkColor *gsk_border_node_get_colors2 (const GskRenderNode *node);
G_END_DECLS