[gtk+] css: Add support for '*' and '/' to calc()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] css: Add support for '*' and '/' to calc()
- Date: Sat, 13 Feb 2016 03:50:04 +0000 (UTC)
commit 63d1f8074287e4001b74b2f52018f32fe0b9cb7b
Author: Benjamin Otte <otte redhat com>
Date: Sat Feb 13 03:56:12 2016 +0100
css: Add support for '*' and '/' to calc()
More tests are included.
gtk/gtkcsscalcvalue.c | 101 +++++++++++++++++++++++++++++-
testsuite/css/parser/Makefile.am | 3 +
testsuite/css/parser/calc-errors.css | 59 +++++++++++++++++
testsuite/css/parser/calc-errors.errors | 15 +++++
testsuite/css/parser/calc.css | 4 +
testsuite/css/parser/calc.ref.css | 4 +
6 files changed, 183 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkcsscalcvalue.c b/gtk/gtkcsscalcvalue.c
index 8df2a67..2bcb545 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('");
diff --git a/testsuite/css/parser/Makefile.am b/testsuite/css/parser/Makefile.am
index fcef072..54c9506 100644
--- a/testsuite/css/parser/Makefile.am
+++ b/testsuite/css/parser/Makefile.am
@@ -228,6 +228,9 @@ test_data = \
box-shadow.ref.css \
calc.css \
calc.ref.css \
+ calc-errors.css \
+ calc-errors.ref.css \
+ calc-errors.errors \
calc-simple.css \
calc-simple.ref.css \
close-at-end-of-file.css \
diff --git a/testsuite/css/parser/calc-errors.css b/testsuite/css/parser/calc-errors.css
new file mode 100644
index 0000000..a109e62
--- /dev/null
+++ b/testsuite/css/parser/calc-errors.css
@@ -0,0 +1,59 @@
+a {
+ margin-left: calc(calc(1px));
+}
+
+b {
+ margin-left: calc(1px + 2s);
+}
+
+c {
+ margin-left: calc(1px - 2s);
+}
+
+d {
+ margin-left: calc(2 * 3);
+}
+
+e {
+ margin-left: calc(2px * 3px);
+}
+
+f {
+ margin-left: calc(2 / 3px);
+}
+
+g {
+ margin-left: calc(2 / 3);
+}
+
+h {
+ margin-left: calc(2px / 3px);
+}
+
+i {
+ margin-left: calc(error);
+}
+
+j {
+ margin-left: calc(1px + error);
+}
+
+k {
+ margin-left: calc(1px - error);
+}
+
+l {
+ margin-left: calc(1 * error);
+}
+
+m {
+ margin-left: calc(1 / error);
+}
+
+n {
+ margin-left: calc(1px * error);
+}
+
+o {
+ margin-left: calc(1px / error);
+}
diff --git a/testsuite/css/parser/calc-errors.errors b/testsuite/css/parser/calc-errors.errors
new file mode 100644
index 0000000..891991d
--- /dev/null
+++ b/testsuite/css/parser/calc-errors.errors
@@ -0,0 +1,15 @@
+calc-errors.css:2: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:6: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:10: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:14: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:18: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:22: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:26: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:30: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:34: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:38: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:42: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:46: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:50: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:54: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
+calc-errors.css:58: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
diff --git a/testsuite/css/parser/calc-errors.ref.css b/testsuite/css/parser/calc-errors.ref.css
new file mode 100644
index 0000000..e69de29
diff --git a/testsuite/css/parser/calc.css b/testsuite/css/parser/calc.css
index 6e7bf54..5406818 100644
--- a/testsuite/css/parser/calc.css
+++ b/testsuite/css/parser/calc.css
@@ -17,3 +17,7 @@ d {
e {
border-left-width: calc(1px + 1px);
}
+
+f {
+ background-size: calc(2 * 3px + 4px * 5 - 6px / 3);
+}
diff --git a/testsuite/css/parser/calc.ref.css b/testsuite/css/parser/calc.ref.css
index 4e858f7..f0c2bbe 100644
--- a/testsuite/css/parser/calc.ref.css
+++ b/testsuite/css/parser/calc.ref.css
@@ -17,3 +17,7 @@ d {
e {
border-left-width: 2px;
}
+
+f {
+ background-size: 24px;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]