summaryrefslogtreecommitdiff
path: root/gtk/gtkcsscalcvalue.c
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2016-02-13 03:56:12 +0100
committerBenjamin Otte <otte@redhat.com>2016-02-13 04:49:08 +0100
commit63d1f8074287e4001b74b2f52018f32fe0b9cb7b (patch)
tree43e87be7ae215bda35d6f6f7bc83bd5eef49397a /gtk/gtkcsscalcvalue.c
parent4a9fa1e7505651c3074b1a620047f6bfc5158a5a (diff)
downloadgtk+-63d1f8074287e4001b74b2f52018f32fe0b9cb7b.tar.gz
css: Add support for '*' and '/' to calc()
More tests are included.
Diffstat (limited to 'gtk/gtkcsscalcvalue.c')
-rw-r--r--gtk/gtkcsscalcvalue.c101
1 files changed, 98 insertions, 3 deletions
diff --git a/gtk/gtkcsscalcvalue.c b/gtk/gtkcsscalcvalue.c
index 8df2a67ad9..2bcb5455fc 100644
--- a/gtk/gtkcsscalcvalue.c
+++ b/gtk/gtkcsscalcvalue.c
@@ -317,12 +317,93 @@ gtk_css_calc_value_new_sum (GtkCssValue *value1,
}
GtkCssValue *
+gtk_css_calc_value_parse_value (GtkCssParser *parser,
+ GtkCssNumberParseFlags flags)
+{
+ if (_gtk_css_parser_has_prefix (parser, "calc"))
+ {
+ _gtk_css_parser_error (parser, "Nested calc() expressions are not allowed.");
+ return NULL;
+ }
+
+ return _gtk_css_number_value_parse (parser, flags);
+}
+
+static gboolean
+is_number (GtkCssValue *value)
+{
+ return gtk_css_number_value_get_dimension (value) == GTK_CSS_DIMENSION_NUMBER
+ && !gtk_css_number_value_has_percent (value);
+}
+
+GtkCssValue *
+gtk_css_calc_value_parse_product (GtkCssParser *parser,
+ GtkCssNumberParseFlags flags)
+{
+ GtkCssValue *result, *value, *temp;
+ GtkCssNumberParseFlags actual_flags;
+
+ actual_flags = flags | GTK_CSS_PARSE_NUMBER;
+
+ result = gtk_css_calc_value_parse_value (parser, actual_flags);
+ if (result == NULL)
+ return NULL;
+
+ while (_gtk_css_parser_begins_with (parser, '*') || _gtk_css_parser_begins_with (parser, '/'))
+ {
+ if (actual_flags != GTK_CSS_PARSE_NUMBER && !is_number (result))
+ actual_flags = GTK_CSS_PARSE_NUMBER;
+
+ if (_gtk_css_parser_try (parser, "*", TRUE))
+ {
+ value = gtk_css_calc_value_parse_product (parser, actual_flags);
+ if (value == NULL)
+ goto fail;
+ if (is_number (value))
+ temp = gtk_css_number_value_multiply (result, _gtk_css_number_value_get (value, 100));
+ else
+ temp = gtk_css_number_value_multiply (value, _gtk_css_number_value_get (result, 100));
+ _gtk_css_value_unref (value);
+ _gtk_css_value_unref (result);
+ result = temp;
+ }
+ else if (_gtk_css_parser_try (parser, "/", TRUE))
+ {
+ value = gtk_css_calc_value_parse_product (parser, GTK_CSS_PARSE_NUMBER);
+ if (value == NULL)
+ goto fail;
+ temp = gtk_css_number_value_multiply (result, 1.0 / _gtk_css_number_value_get (value, 100));
+ _gtk_css_value_unref (value);
+ _gtk_css_value_unref (result);
+ result = temp;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ goto fail;
+ }
+ }
+
+ if (is_number (result) && !(flags & GTK_CSS_PARSE_NUMBER))
+ {
+ _gtk_css_parser_error (parser, "calc() product term has no units");
+ goto fail;
+ }
+
+ return result;
+
+fail:
+ _gtk_css_value_unref (result);
+ return NULL;
+}
+
+GtkCssValue *
gtk_css_calc_value_parse_sum (GtkCssParser *parser,
GtkCssNumberParseFlags flags)
{
GtkCssValue *result;
- result = _gtk_css_number_value_parse (parser, flags);
+ result = gtk_css_calc_value_parse_product (parser, flags);
if (result == NULL)
return NULL;
@@ -332,17 +413,22 @@ gtk_css_calc_value_parse_sum (GtkCssParser *parser,
if (_gtk_css_parser_try (parser, "+", TRUE))
{
- next = _gtk_css_number_value_parse (parser, flags);
+ next = gtk_css_calc_value_parse_product (parser, flags);
+ if (next == NULL)
+ goto fail;
}
else if (_gtk_css_parser_try (parser, "-", TRUE))
{
- temp = _gtk_css_number_value_parse (parser, flags);
+ temp = gtk_css_calc_value_parse_product (parser, flags);
+ if (temp == NULL)
+ goto fail;
next = gtk_css_number_value_multiply (temp, -1);
_gtk_css_value_unref (temp);
}
else
{
g_assert_not_reached ();
+ goto fail;
}
temp = gtk_css_number_value_add (result, next);
@@ -352,6 +438,10 @@ gtk_css_calc_value_parse_sum (GtkCssParser *parser,
}
return result;
+
+fail:
+ _gtk_css_value_unref (result);
+ return NULL;
}
GtkCssValue *
@@ -360,6 +450,11 @@ gtk_css_calc_value_parse (GtkCssParser *parser,
{
GtkCssValue *value;
+ /* This confuses '*' and '/' so we disallow backwards compat. */
+ flags &= ~GTK_CSS_NUMBER_AS_PIXELS;
+ /* This can only be handled at compute time, we allow '-' after all */
+ flags &= ~GTK_CSS_POSITIVE_ONLY;
+
if (!_gtk_css_parser_try (parser, "calc(", TRUE))
{
_gtk_css_parser_error (parser, "Expected 'calc('");