summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2019-04-09 05:15:45 +0200
committerBenjamin Otte <otte@redhat.com>2019-04-12 19:34:28 +0200
commita31e5f7a8c4c6965d92b8171c514b12f435a021f (patch)
tree61d8135bdb92da8463b9230ee2be0d7607e509c6
parente0a01ba1743cd147ee29ad11944f8204768dd5c1 (diff)
downloadgtk+-a31e5f7a8c4c6965d92b8171c514b12f435a021f.tar.gz
cssshadow: Use gtk_css_parser_consume_any()
This way, the arguments can now really be speicified in any order. A new testcase testing all the ordering possibilities has been added.
-rw-r--r--gtk/gtkcsscolorvalue.c17
-rw-r--r--gtk/gtkcsscolorvalueprivate.h1
-rw-r--r--gtk/gtkcssshadowvalue.c185
-rw-r--r--testsuite/css/parser/meson.build2
-rw-r--r--testsuite/css/parser/shadow-ordering.css43
-rw-r--r--testsuite/css/parser/shadow-ordering.ref.css43
6 files changed, 213 insertions, 78 deletions
diff --git a/gtk/gtkcsscolorvalue.c b/gtk/gtkcsscolorvalue.c
index 40b3159666..617f92bdc1 100644
--- a/gtk/gtkcsscolorvalue.c
+++ b/gtk/gtkcsscolorvalue.c
@@ -574,6 +574,23 @@ parse_color_number (GtkCssParser *parser,
}
}
+gboolean
+gtk_css_color_value_can_parse (GtkCssParser *parser)
+{
+ /* This is way too generous, but meh... */
+ return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_IDENT)
+ || gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_AT_KEYWORD)
+ || gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_HASH_ID)
+ || gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_HASH_UNRESTRICTED)
+ || gtk_css_parser_has_function (parser, "lighter")
+ || gtk_css_parser_has_function (parser, "darker")
+ || gtk_css_parser_has_function (parser, "shade")
+ || gtk_css_parser_has_function (parser, "alpha")
+ || gtk_css_parser_has_function (parser, "mix")
+ || gtk_css_parser_has_function (parser, "rgb")
+ || gtk_css_parser_has_function (parser, "rgba");
+}
+
GtkCssValue *
_gtk_css_color_value_parse (GtkCssParser *parser)
{
diff --git a/gtk/gtkcsscolorvalueprivate.h b/gtk/gtkcsscolorvalueprivate.h
index e5f9c42ee6..fa199ee6ab 100644
--- a/gtk/gtkcsscolorvalueprivate.h
+++ b/gtk/gtkcsscolorvalueprivate.h
@@ -39,6 +39,7 @@ GtkCssValue * _gtk_css_color_value_new_mix (GtkCssValue *color1,
gdouble factor);
GtkCssValue * _gtk_css_color_value_new_current_color (void);
+gboolean gtk_css_color_value_can_parse (GtkCssParser *parser);
GtkCssValue * _gtk_css_color_value_parse (GtkCssParser *parser);
GtkCssValue * _gtk_css_color_value_resolve (GtkCssValue *color,
diff --git a/gtk/gtkcssshadowvalue.c b/gtk/gtkcssshadowvalue.c
index 072396f6c9..f0b2fc243d 100644
--- a/gtk/gtkcssshadowvalue.c
+++ b/gtk/gtkcssshadowvalue.c
@@ -201,103 +201,132 @@ _gtk_css_shadow_value_new_for_transition (GtkCssValue *target)
_gtk_css_rgba_value_new_from_rgba (&transparent));
}
+enum {
+ HOFFSET,
+ VOFFSET,
+ RADIUS,
+ SPREAD,
+ N_VALUES
+};
+
+static gboolean
+has_inset (GtkCssParser *parser,
+ gpointer option_data,
+ gpointer box_shadow_mode)
+{
+ return box_shadow_mode && gtk_css_parser_has_ident (parser, "inset");
+}
+
+static gboolean
+parse_inset (GtkCssParser *parser,
+ gpointer option_data,
+ gpointer box_shadow_mode)
+{
+ gboolean *inset = option_data;
+
+ if (!gtk_css_parser_try_ident (parser, "inset"))
+ {
+ g_assert_not_reached ();
+ return FALSE;
+ }
+
+ *inset = TRUE;
+
+ return TRUE;
+}
+
+static gboolean
+parse_lengths (GtkCssParser *parser,
+ gpointer option_data,
+ gpointer box_shadow_mode)
+{
+ GtkCssValue **values = option_data;
+
+ values[HOFFSET] = _gtk_css_number_value_parse (parser,
+ GTK_CSS_PARSE_LENGTH);
+ if (values[HOFFSET] == NULL)
+ return FALSE;
+
+ values[VOFFSET] = _gtk_css_number_value_parse (parser,
+ GTK_CSS_PARSE_LENGTH);
+ if (values[VOFFSET] == NULL)
+ return FALSE;
+
+ if (gtk_css_number_value_can_parse (parser))
+ {
+ values[RADIUS] = _gtk_css_number_value_parse (parser,
+ GTK_CSS_PARSE_LENGTH
+ | GTK_CSS_POSITIVE_ONLY);
+ if (values[RADIUS] == NULL)
+ return FALSE;
+ }
+ else
+ values[RADIUS] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
+
+ if (box_shadow_mode && gtk_css_number_value_can_parse (parser))
+ {
+ values[SPREAD] = _gtk_css_number_value_parse (parser,
+ GTK_CSS_PARSE_LENGTH);
+ if (values[SPREAD] == NULL)
+ return FALSE;
+ }
+ else
+ values[SPREAD] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
+
+ return TRUE;
+}
+
static gboolean
-value_is_done_parsing (GtkCssParser *parser)
+parse_color (GtkCssParser *parser,
+ gpointer option_data,
+ gpointer box_shadow_mode)
{
- return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF) ||
- gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_COMMA) ||
- gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SEMICOLON) ||
- gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_CLOSE_CURLY);
+ GtkCssValue **color = option_data;
+
+ *color = _gtk_css_color_value_parse (parser);
+ if (*color == NULL)
+ return FALSE;
+
+ return TRUE;
}
GtkCssValue *
_gtk_css_shadow_value_parse (GtkCssParser *parser,
gboolean box_shadow_mode)
{
- enum {
- HOFFSET,
- VOFFSET,
- RADIUS,
- SPREAD,
- COLOR,
- N_VALUES
- };
GtkCssValue *values[N_VALUES] = { NULL, };
- gboolean inset;
+ GtkCssValue *color = NULL;
+ gboolean inset = FALSE;
+ GtkCssParseOption options[] =
+ {
+ { (void *) gtk_css_number_value_can_parse, parse_lengths, values },
+ { has_inset, parse_inset, &inset },
+ { (void *) gtk_css_color_value_can_parse, parse_color, &color },
+ };
guint i;
- inset = FALSE;
-
- do
- {
- if (values[HOFFSET] == NULL &&
- gtk_css_number_value_can_parse (parser))
- {
- values[HOFFSET] = _gtk_css_number_value_parse (parser,
- GTK_CSS_PARSE_LENGTH);
- if (values[HOFFSET] == NULL)
- goto fail;
-
- values[VOFFSET] = _gtk_css_number_value_parse (parser,
- GTK_CSS_PARSE_LENGTH);
- if (values[VOFFSET] == NULL)
- goto fail;
-
- if (gtk_css_number_value_can_parse (parser))
- {
- values[RADIUS] = _gtk_css_number_value_parse (parser,
- GTK_CSS_PARSE_LENGTH
- | GTK_CSS_POSITIVE_ONLY);
- if (values[RADIUS] == NULL)
- goto fail;
- }
- else
- values[RADIUS] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
-
- if (box_shadow_mode && gtk_css_number_value_can_parse (parser))
- {
- values[SPREAD] = _gtk_css_number_value_parse (parser,
- GTK_CSS_PARSE_LENGTH);
- if (values[SPREAD] == NULL)
- goto fail;
- }
- else
- values[SPREAD] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
- }
- else if (!inset && box_shadow_mode && gtk_css_parser_try_ident (parser, "inset"))
- {
- inset = TRUE;
- }
- else if (values[COLOR] == NULL)
- {
- values[COLOR] = _gtk_css_color_value_parse (parser);
-
- if (values[COLOR] == NULL)
- goto fail;
- }
- else
- {
- /* We parsed everything and there's still stuff left?
- * Pretend we didn't notice and let the normal code produce
- * a 'junk at end of value' error */
- goto fail;
- }
- }
- while (values[HOFFSET] == NULL || !value_is_done_parsing (parser));
-
- if (values[COLOR] == NULL)
- values[COLOR] = _gtk_css_color_value_new_current_color ();
+ if (!gtk_css_parser_consume_any (parser, options, G_N_ELEMENTS (options), GUINT_TO_POINTER (box_shadow_mode)))
+ goto fail;
+
+ if (values[0] == NULL)
+ {
+ gtk_css_parser_error_syntax (parser, "Expected shadow value to contain a length");
+ goto fail;
+ }
+
+ if (color == NULL)
+ color = _gtk_css_color_value_new_current_color ();
return gtk_css_shadow_value_new (values[HOFFSET], values[VOFFSET],
values[RADIUS], values[SPREAD],
- inset, values[COLOR]);
+ inset, color);
fail:
for (i = 0; i < N_VALUES; i++)
{
- if (values[i])
- _gtk_css_value_unref (values[i]);
+ g_clear_pointer (&values[i], gtk_css_value_unref);
}
+ g_clear_pointer (&color, gtk_css_value_unref);
return NULL;
}
diff --git a/testsuite/css/parser/meson.build b/testsuite/css/parser/meson.build
index db4672365a..9451633efd 100644
--- a/testsuite/css/parser/meson.build
+++ b/testsuite/css/parser/meson.build
@@ -383,6 +383,8 @@ test_data = [
'selector.ref.css',
'shadow.css',
'shadow.ref.css',
+ 'shadow-ordering.css',
+ 'shadow-ordering.ref.css',
'shorthand.css',
'shorthand.ref.css',
'simple.css',
diff --git a/testsuite/css/parser/shadow-ordering.css b/testsuite/css/parser/shadow-ordering.css
new file mode 100644
index 0000000000..5450fa38df
--- /dev/null
+++ b/testsuite/css/parser/shadow-ordering.css
@@ -0,0 +1,43 @@
+a {
+ box-shadow: 0 0;
+}
+
+b {
+ box-shadow: 0 0 inset;
+}
+
+c {
+ box-shadow: 0 0 inset red;
+}
+
+d {
+ box-shadow: 0 0 red;
+}
+
+e {
+ box-shadow: 0 0 red inset;
+}
+
+f {
+ box-shadow: inset 0 0;
+}
+
+g {
+ box-shadow: inset red 0 0;
+}
+
+h {
+ box-shadow: inset 0 0 red;
+}
+
+i {
+ box-shadow: red 0 0;
+}
+
+j {
+ box-shadow: red inset 0 0;
+}
+
+k {
+ box-shadow: red 0 0 inset;
+}
diff --git a/testsuite/css/parser/shadow-ordering.ref.css b/testsuite/css/parser/shadow-ordering.ref.css
new file mode 100644
index 0000000000..ee7a10a2b1
--- /dev/null
+++ b/testsuite/css/parser/shadow-ordering.ref.css
@@ -0,0 +1,43 @@
+a {
+ box-shadow: 0 0 currentColor;
+}
+
+b {
+ box-shadow: 0 0 currentColor inset;
+}
+
+c {
+ box-shadow: 0 0 rgb(255,0,0) inset;
+}
+
+d {
+ box-shadow: 0 0 rgb(255,0,0);
+}
+
+e {
+ box-shadow: 0 0 rgb(255,0,0) inset;
+}
+
+f {
+ box-shadow: 0 0 currentColor inset;
+}
+
+g {
+ box-shadow: 0 0 rgb(255,0,0) inset;
+}
+
+h {
+ box-shadow: 0 0 rgb(255,0,0) inset;
+}
+
+i {
+ box-shadow: 0 0 rgb(255,0,0);
+}
+
+j {
+ box-shadow: 0 0 rgb(255,0,0) inset;
+}
+
+k {
+ box-shadow: 0 0 rgb(255,0,0) inset;
+}