cssimage: Add token parser for linear-gradient
This requires refactoring of gtk_css_token_source_consume_function() to allow a single call to the parse_args function to consume multiple arguments. Because the first argument to linear-gradient() is the optional direction, we need to indicate that we skipped it. So the parse function returns 2 in that case. This way we can set the minimum required arguments to 3, while still allowing linear-gradient(red, blue); which is equivalent to linear-gradient(to bottom, red, blue);
This commit is contained in:
@@ -327,7 +327,7 @@ _gtk_css_ease_value_parse (GtkCssParser *parser)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static guint
|
||||
token_parse_cubic_bezier (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
@@ -342,13 +342,13 @@ token_parse_cubic_bezier (GtkCssTokenSource *source,
|
||||
(numbers[n] < 0 || numbers[n] > 1.0))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Value %g out of range. Must be from 0.0 to 1.0", numbers[n]);
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static guint
|
||||
token_parse_steps (GtkCssTokenSource *source,
|
||||
guint nth_argument,
|
||||
gpointer data)
|
||||
@@ -363,17 +363,17 @@ token_parse_steps (GtkCssTokenSource *source,
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a positive integer for number of steps");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
else if (token->number.number <= 0)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Number of steps must be greater than 0");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
value->u.steps.steps = token->number.number;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -385,10 +385,10 @@ token_parse_steps (GtkCssTokenSource *source,
|
||||
{
|
||||
gtk_css_token_source_error (source, "Only allowed values are 'start' and 'end'");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ gtk_css_image_icon_theme_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static guint
|
||||
token_parse_arg (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
@@ -130,13 +130,13 @@ token_parse_arg (GtkCssTokenSource *source,
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a string for the icon name");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
icon_theme->name = g_strdup (token->string.string);
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
||||
@@ -361,6 +361,130 @@ gtk_css_image_linear_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_image_linear_token_parse_argument (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssImageLinear *linear = data;
|
||||
GtkCssImageLinearColorStop stop;
|
||||
const GtkCssToken *token;
|
||||
|
||||
if (arg == 0)
|
||||
{
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
|
||||
if (gtk_css_token_is_ident (token, "to"))
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
guint value;
|
||||
guint optional_index[2];
|
||||
} sides[] = {
|
||||
{ "top", 1 << GTK_CSS_TOP, { 2, 3 } },
|
||||
{ "bottom", 1 << GTK_CSS_BOTTOM, { 2, 3 } },
|
||||
{ "left", 1 << GTK_CSS_LEFT, { 0, 1 } },
|
||||
{ "right", 1 << GTK_CSS_RIGHT, { 0, 1 } }
|
||||
};
|
||||
guint i, j;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
for (i = 0; i < G_N_ELEMENTS (sides); i++)
|
||||
{
|
||||
if (!gtk_css_token_is_ident (token, sides[i].name))
|
||||
continue;
|
||||
|
||||
linear->side = sides[i].value;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
for (j = 0; j < G_N_ELEMENTS (sides[i].optional_index); j++)
|
||||
{
|
||||
guint idx = sides[i].optional_index[j];
|
||||
if (!gtk_css_token_is_ident (token, sides[idx].name))
|
||||
continue;
|
||||
|
||||
linear->side = sides[idx].value;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
gtk_css_token_source_error (source, "Expected a direction");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return 0;
|
||||
}
|
||||
else if (!gtk_css_color_value_check_token (token))
|
||||
{
|
||||
/* We check for !color here so the error message is "expected angle"
|
||||
* for nonsense values */
|
||||
linear->angle = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
|
||||
if (linear->angle == NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
linear->side = 1 << GTK_CSS_BOTTOM;
|
||||
}
|
||||
|
||||
stop.color = gtk_css_color_value_token_parse (source);
|
||||
if (stop.color == NULL)
|
||||
return 0;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_number_value_check_token (token))
|
||||
{
|
||||
stop.offset = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_PARSE_PERCENT
|
||||
| GTK_CSS_PARSE_LENGTH);
|
||||
if (stop.offset == NULL)
|
||||
{
|
||||
_gtk_css_value_unref (stop.color);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stop.offset = NULL;
|
||||
}
|
||||
|
||||
g_array_append_val (linear->stops, stop);
|
||||
/* We consume the optional side argument here, too. */
|
||||
return arg == 0 ? 2 : 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_linear_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_function (token, "linear-gradient"))
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "repeating-linear-gradient"))
|
||||
{
|
||||
linear->repeating = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected 'linear-gradient('");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return gtk_css_token_source_consume_function (source,
|
||||
3, G_MAXUINT,
|
||||
gtk_css_image_linear_token_parse_argument,
|
||||
image);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_linear_print (GtkCssImage *image,
|
||||
GString *string)
|
||||
@@ -598,6 +722,7 @@ _gtk_css_image_linear_class_init (GtkCssImageLinearClass *klass)
|
||||
|
||||
image_class->draw = gtk_css_image_linear_draw;
|
||||
image_class->parse = gtk_css_image_linear_parse;
|
||||
image_class->token_parse = gtk_css_image_linear_token_parse;
|
||||
image_class->print = gtk_css_image_linear_print;
|
||||
image_class->compute = gtk_css_image_linear_compute;
|
||||
image_class->equal = gtk_css_image_linear_equal;
|
||||
|
||||
@@ -180,7 +180,7 @@ gtk_css_image_scaled_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static guint
|
||||
token_parse_arg (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
@@ -190,11 +190,11 @@ token_parse_arg (GtkCssTokenSource *source,
|
||||
|
||||
image = gtk_css_image_new_token_parse (source);
|
||||
if (image == NULL)
|
||||
return FALSE;
|
||||
return 0;
|
||||
|
||||
g_ptr_array_add (images, image);
|
||||
|
||||
return TRUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
||||
@@ -343,7 +343,7 @@ gboolean
|
||||
gtk_css_token_source_consume_function (GtkCssTokenSource *source,
|
||||
guint min_args,
|
||||
guint max_args,
|
||||
gboolean (* parse_func) (GtkCssTokenSource *, guint, gpointer),
|
||||
guint (* parse_func) (GtkCssTokenSource *, guint, gpointer),
|
||||
gpointer data)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
@@ -358,17 +358,20 @@ gtk_css_token_source_consume_function (GtkCssTokenSource *source,
|
||||
gtk_css_token_source_consume_token (source);
|
||||
func_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_CLOSE_PARENS);
|
||||
|
||||
for (arg = 0; arg < max_args; arg++)
|
||||
arg = 0;
|
||||
while (arg < max_args)
|
||||
{
|
||||
if (!parse_func (func_source, arg, data))
|
||||
guint parse_args = parse_func (func_source, arg, data);
|
||||
if (parse_args == 0)
|
||||
{
|
||||
gtk_css_token_source_consume_all (func_source);
|
||||
break;
|
||||
}
|
||||
arg += parse_args;
|
||||
token = gtk_css_token_source_get_token (func_source);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
|
||||
{
|
||||
if (arg + 1 < min_args)
|
||||
if (arg < min_args)
|
||||
{
|
||||
gtk_css_token_source_error (source, "%s() requires at least %u arguments", function_name, min_args);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
|
||||
@@ -70,7 +70,7 @@ char * gtk_css_token_source_consume_to_string (GtkCssTokenSour
|
||||
gboolean gtk_css_token_source_consume_function (GtkCssTokenSource *source,
|
||||
guint min_args,
|
||||
guint max_args,
|
||||
gboolean (* parse_func) (GtkCssTokenSource *, guint, gpointer),
|
||||
guint (* parse_func) (GtkCssTokenSource *, guint, gpointer),
|
||||
gpointer data);
|
||||
gboolean gtk_css_token_source_consume_number (GtkCssTokenSource *source,
|
||||
double *number);
|
||||
|
||||
@@ -1015,7 +1015,7 @@ _gtk_css_transform_value_parse (GtkCssParser *parser)
|
||||
return value;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static guint
|
||||
token_parse_matrix (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
@@ -1025,24 +1025,24 @@ token_parse_matrix (GtkCssTokenSource *source,
|
||||
switch (n)
|
||||
{
|
||||
case 0:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xx);
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xx) ? 1 : 0;
|
||||
case 1:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xy);
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xy) ? 1 : 0;
|
||||
case 2:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.x0);
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.x0) ? 1 : 0;
|
||||
case 3:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yx);
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yx) ? 1 : 0;
|
||||
case 4:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yy);
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yy) ? 1 : 0;
|
||||
case 5:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.y0);
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.y0) ? 1 : 0;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static guint
|
||||
token_parse_translate (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
@@ -1053,7 +1053,7 @@ token_parse_translate (GtkCssTokenSource *source,
|
||||
{
|
||||
transform->translate.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH);
|
||||
if (transform->translate.x == NULL)
|
||||
return FALSE;
|
||||
return 0;
|
||||
transform->translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
|
||||
}
|
||||
else if (n == 1)
|
||||
@@ -1061,16 +1061,16 @@ token_parse_translate (GtkCssTokenSource *source,
|
||||
_gtk_css_value_unref (transform->translate.y);
|
||||
transform->translate.y = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH);
|
||||
if (transform->translate.y == NULL)
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
return TRUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static guint
|
||||
token_parse_length (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
@@ -1078,10 +1078,13 @@ token_parse_length (GtkCssTokenSource *source,
|
||||
GtkCssValue **value = data;
|
||||
|
||||
*value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH);
|
||||
return *value != NULL;
|
||||
if (*value == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static guint
|
||||
token_parse_scale (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
@@ -1092,7 +1095,7 @@ token_parse_scale (GtkCssTokenSource *source,
|
||||
{
|
||||
transform->scale.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
|
||||
if (transform->scale.x == NULL)
|
||||
return FALSE;
|
||||
return 0;
|
||||
transform->scale.y = _gtk_css_value_ref (transform->scale.x);
|
||||
}
|
||||
else if (n == 1)
|
||||
@@ -1100,16 +1103,16 @@ token_parse_scale (GtkCssTokenSource *source,
|
||||
_gtk_css_value_unref (transform->scale.y);
|
||||
transform->scale.y = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
|
||||
if (transform->scale.y == NULL)
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
return TRUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static guint
|
||||
token_parse_number (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
@@ -1117,10 +1120,13 @@ token_parse_number (GtkCssTokenSource *source,
|
||||
GtkCssValue **value = data;
|
||||
|
||||
*value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
|
||||
return *value != NULL;
|
||||
if (*value == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static guint
|
||||
token_parse_angle (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
@@ -1128,10 +1134,13 @@ token_parse_angle (GtkCssTokenSource *source,
|
||||
GtkCssValue **value = data;
|
||||
|
||||
*value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
|
||||
return *value != NULL;
|
||||
if (*value == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static guint
|
||||
token_parse_skew (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
@@ -1142,7 +1151,7 @@ token_parse_skew (GtkCssTokenSource *source,
|
||||
{
|
||||
transform->skew.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
|
||||
if (transform->skew.x == NULL)
|
||||
return FALSE;
|
||||
return 0;
|
||||
transform->skew.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
|
||||
}
|
||||
else if (n == 1)
|
||||
@@ -1150,13 +1159,13 @@ token_parse_skew (GtkCssTokenSource *source,
|
||||
_gtk_css_value_unref (transform->skew.y);
|
||||
transform->skew.y = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
|
||||
if (transform->skew.y == NULL)
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
return TRUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
|
||||
Reference in New Issue
Block a user