cross-fade: Use gtk_css_parser_consume_any()

.. and gtk_css_parser_consume_function().

gtk_css_parser_consume_any() is a new function that implements the CSS
spec's any combinator ||.
This commit is contained in:
Benjamin Otte 2019-03-30 12:04:51 +01:00
parent 96f9cbcabf
commit d99ae4b6c2
3 changed files with 122 additions and 45 deletions

View File

@ -229,60 +229,81 @@ gtk_css_image_cross_fade_snapshot (GtkCssImage *image,
} }
} }
static gboolean
parse_progress (GtkCssParser *parser,
gpointer option_data,
gpointer user_data)
{
double *progress = option_data;
GtkCssValue *number;
number = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY);
if (number == NULL)
return FALSE;
*progress = _gtk_css_number_value_get (number, 1);
_gtk_css_value_unref (number);
if (*progress > 1.0)
{
_gtk_css_parser_error (parser, "Percentages over 100%% are not allowed");
return FALSE;
}
return TRUE;
}
static gboolean
parse_image (GtkCssParser *parser,
gpointer option_data,
gpointer user_data)
{
GtkCssImage **image = option_data;
*image = _gtk_css_image_new_parse (parser);
if (*image == NULL)
return FALSE;
return TRUE;
}
static guint
gtk_css_image_cross_fade_parse_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
GtkCssImageCrossFade *self = data;
double progress = -1.0;
GtkCssImage *image = NULL;
GtkCssParseOption options[] =
{
{ (void *) gtk_css_number_value_can_parse, parse_progress, &progress },
{ NULL, parse_image, &image },
};
if (!gtk_css_parser_consume_any (parser, options, G_N_ELEMENTS (options), self))
return 0;
g_assert (image != NULL);
/* XXX */
if (progress < 0)
progress = 1.0 - self->total_progress;
gtk_css_image_cross_fade_add (self, progress, image);
return 1;
}
static gboolean static gboolean
gtk_css_image_cross_fade_parse (GtkCssImage *image, gtk_css_image_cross_fade_parse (GtkCssImage *image,
GtkCssParser *parser) GtkCssParser *parser)
{ {
GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image); if (!gtk_css_parser_has_function (parser, "cross-fade"))
double progress;
if (!_gtk_css_parser_try (parser, "cross-fade(", TRUE))
{ {
_gtk_css_parser_error (parser, "Expected 'cross-fade('"); _gtk_css_parser_error (parser, "Expected 'cross-fade('");
return FALSE; return FALSE;
} }
if (gtk_css_number_value_can_parse (parser)) return gtk_css_parser_consume_function (parser, 1, G_MAXUINT, gtk_css_image_cross_fade_parse_arg, image);
{
GtkCssValue *number;
number = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY);
if (number == NULL)
return FALSE;
progress = _gtk_css_number_value_get (number, 1);
_gtk_css_value_unref (number);
if (progress > 1.0)
{
_gtk_css_parser_error (parser, "Percentages over 100%% are not allowed");
return FALSE;
}
}
else
progress = 0.5;
image = _gtk_css_image_new_parse (parser);
if (image == NULL)
return FALSE;
gtk_css_image_cross_fade_add (self, progress, image);
if (_gtk_css_parser_try (parser, ",", TRUE))
{
/* XXX: allow parsing colors here */
image = _gtk_css_image_new_parse (parser);
if (image == NULL)
return FALSE;
gtk_css_image_cross_fade_add (self, 1.0 - progress, image);
}
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_parser_error (parser, "Missing closing bracket");
return FALSE;
}
return TRUE;
} }
static void static void

View File

@ -1223,3 +1223,42 @@ gtk_css_parser_consume_function (GtkCssParser *self,
return result; return result;
} }
gsize
gtk_css_parser_consume_any (GtkCssParser *parser,
const GtkCssParseOption *options,
gsize n_options,
gpointer user_data)
{
gsize result;
gsize i;
g_return_val_if_fail (parser != NULL, 0);
g_return_val_if_fail (options != NULL, 0);
g_return_val_if_fail (n_options < sizeof (gsize) * 8 - 1, 0);
result = 0;
while (result != (1 << n_options) - 1)
{
for (i = 0; i < n_options; i++)
{
if (result & (1 << i))
continue;
if (options[i].can_parse && !options[i].can_parse (parser, options[i].data, user_data))
continue;
if (!options[i].parse (parser, options[i].data, user_data))
return 0;
result |= 1 << i;
break;
}
if (i == n_options)
break;
}
if (result == 0)
{
_gtk_css_parser_error (parser, "No valid value given");
return result;
}
return result;
}

View File

@ -31,6 +31,19 @@ typedef void (* GtkCssParserErrorFunc) (GtkCssParser *parser,
const GError *error, const GError *error,
gpointer user_data); gpointer user_data);
typedef struct _GtkCssParseOption GtkCssParseOption;
struct _GtkCssParseOption
{
gboolean (* can_parse) (GtkCssParser *parser,
gpointer option_data,
gpointer user_data);
gboolean (* parse) (GtkCssParser *parser,
gpointer option_data,
gpointer user_data);
gpointer data;
};
GtkCssParser * _gtk_css_parser_new (const char *data, GtkCssParser * _gtk_css_parser_new (const char *data,
GFile *file, GFile *file,
GtkCssParserErrorFunc error_func, GtkCssParserErrorFunc error_func,
@ -90,6 +103,10 @@ gboolean gtk_css_parser_consume_function (GtkCssParser *self,
guint max_args, guint max_args,
guint (* parse_func) (GtkCssParser *, guint, gpointer), guint (* parse_func) (GtkCssParser *, guint, gpointer),
gpointer data); gpointer data);
gsize gtk_css_parser_consume_any (GtkCssParser *parser,
const GtkCssParseOption *options,
gsize n_options,
gpointer user_data);
gboolean _gtk_css_parser_has_number (GtkCssParser *parser); gboolean _gtk_css_parser_has_number (GtkCssParser *parser);
char * _gtk_css_parser_read_string (GtkCssParser *parser); char * _gtk_css_parser_read_string (GtkCssParser *parser);