nodeparser: Handle disallowed values for radial gradients

Make sure the radii are strictly positive.

Also handle the case where start >= end.
We can't really underline that error, because we don't track the
locations of the start/end properties until we know that there's an
error.
So just underline the whole radial gradient declaration.

Test included
This commit is contained in:
Benjamin Otte 2024-08-11 17:44:19 +02:00
parent 9643a21827
commit 68d73dcce5
5 changed files with 77 additions and 3 deletions

View File

@ -516,6 +516,33 @@ parse_positive_double (GtkCssParser *parser,
return gtk_css_parser_consume_number (parser, out_double);
}
static gboolean
parse_strictly_positive_double (GtkCssParser *parser,
Context *context,
gpointer out_double)
{
double tmp;
if (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SIGNED_NUMBER)
|| gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SIGNED_INTEGER))
{
gtk_css_parser_error_syntax (parser, "Expected a strictly positive number");
return FALSE;
}
if (!gtk_css_parser_consume_number (parser, &tmp))
return FALSE;
if (tmp == 0)
{
gtk_css_parser_error_syntax (parser, "Expected a strictly positive number");
return FALSE;
}
*(double *) out_double = tmp;
return TRUE;
}
static gboolean
parse_point (GtkCssParser *parser,
Context *context,
@ -1765,8 +1792,8 @@ parse_radial_gradient_node_internal (GtkCssParser *parser,
const Declaration declarations[] = {
{ "bounds", parse_rect, NULL, &bounds },
{ "center", parse_point, NULL, &center },
{ "hradius", parse_positive_double, NULL, &hradius },
{ "vradius", parse_positive_double, NULL, &vradius },
{ "hradius", parse_strictly_positive_double, NULL, &hradius },
{ "vradius", parse_strictly_positive_double, NULL, &vradius },
{ "start", parse_positive_double, NULL, &start },
{ "end", parse_positive_double, NULL, &end },
{ "stops", parse_stops, clear_stops, &stops },
@ -1784,7 +1811,16 @@ parse_radial_gradient_node_internal (GtkCssParser *parser,
g_array_append_val (stops, to);
}
if (repeating)
if (end <= start)
{
gtk_css_parser_error (parser,
GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE,
gtk_css_parser_get_block_location (parser),
gtk_css_parser_get_end_location (parser),
"\"start\" must be larger than \"end\"");
result = NULL;
}
else if (repeating)
result = gsk_repeating_radial_gradient_node_new (&bounds, &center, hradius, vradius, start, end,
(GskColorStop *) stops->data, stops->len);
else

View File

@ -419,6 +419,9 @@ node_parser_tests = [
'occlusion-wrong-rect-contains',
'radial-gradient.node',
'radial-gradient.ref.node',
'radial-gradient-start-end.errors',
'radial-gradient-start-end.node',
'radial-gradient-start-end.ref.node',
'repeating-linear-gradient.node',
'repeating-linear-gradient.ref.node',
'repeating-radial-gradient.node',

View File

@ -0,0 +1,4 @@
<data>:1:1-4:2: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE
<data>:6:1-9:2: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE
<data>:12:12-13: error: GTK_CSS_PARSER_ERROR_SYNTAX
<data>:16:12-13: error: GTK_CSS_PARSER_ERROR_SYNTAX

View File

@ -0,0 +1,17 @@
radial-gradient {
start: 1;
end: 0;
}
radial-gradient {
start: 0.5;
end: 0.5;
}
radial-gradient {
hradius: 0;
}
radial-gradient {
vradius: 0;
}

View File

@ -0,0 +1,14 @@
radial-gradient {
bounds: 0 0 50 50;
center: 25 25;
hradius: 25;
vradius: 25;
stops: 0 rgb(170,255,0), 1 rgb(255,0,204);
}
radial-gradient {
bounds: 0 0 50 50;
center: 25 25;
hradius: 25;
vradius: 25;
stops: 0 rgb(170,255,0), 1 rgb(255,0,204);
}