css: Add support for '*' and '/' to calc()
More tests are included.
This commit is contained in:
@ -316,13 +316,94 @@ gtk_css_calc_value_new_sum (GtkCssValue *value1,
|
|||||||
return gtk_css_value_new_from_array (array);
|
return gtk_css_value_new_from_array (array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 *
|
GtkCssValue *
|
||||||
gtk_css_calc_value_parse_sum (GtkCssParser *parser,
|
gtk_css_calc_value_parse_sum (GtkCssParser *parser,
|
||||||
GtkCssNumberParseFlags flags)
|
GtkCssNumberParseFlags flags)
|
||||||
{
|
{
|
||||||
GtkCssValue *result;
|
GtkCssValue *result;
|
||||||
|
|
||||||
result = _gtk_css_number_value_parse (parser, flags);
|
result = gtk_css_calc_value_parse_product (parser, flags);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -332,17 +413,22 @@ gtk_css_calc_value_parse_sum (GtkCssParser *parser,
|
|||||||
|
|
||||||
if (_gtk_css_parser_try (parser, "+", TRUE))
|
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))
|
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);
|
next = gtk_css_number_value_multiply (temp, -1);
|
||||||
_gtk_css_value_unref (temp);
|
_gtk_css_value_unref (temp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp = gtk_css_number_value_add (result, next);
|
temp = gtk_css_number_value_add (result, next);
|
||||||
@ -352,6 +438,10 @@ gtk_css_calc_value_parse_sum (GtkCssParser *parser,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
_gtk_css_value_unref (result);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkCssValue *
|
GtkCssValue *
|
||||||
@ -360,6 +450,11 @@ gtk_css_calc_value_parse (GtkCssParser *parser,
|
|||||||
{
|
{
|
||||||
GtkCssValue *value;
|
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))
|
if (!_gtk_css_parser_try (parser, "calc(", TRUE))
|
||||||
{
|
{
|
||||||
_gtk_css_parser_error (parser, "Expected 'calc('");
|
_gtk_css_parser_error (parser, "Expected 'calc('");
|
||||||
|
|||||||
@ -228,6 +228,9 @@ test_data = \
|
|||||||
box-shadow.ref.css \
|
box-shadow.ref.css \
|
||||||
calc.css \
|
calc.css \
|
||||||
calc.ref.css \
|
calc.ref.css \
|
||||||
|
calc-errors.css \
|
||||||
|
calc-errors.ref.css \
|
||||||
|
calc-errors.errors \
|
||||||
calc-simple.css \
|
calc-simple.css \
|
||||||
calc-simple.ref.css \
|
calc-simple.ref.css \
|
||||||
close-at-end-of-file.css \
|
close-at-end-of-file.css \
|
||||||
|
|||||||
59
testsuite/css/parser/calc-errors.css
Normal file
59
testsuite/css/parser/calc-errors.css
Normal file
@ -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);
|
||||||
|
}
|
||||||
15
testsuite/css/parser/calc-errors.errors
Normal file
15
testsuite/css/parser/calc-errors.errors
Normal file
@ -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
|
||||||
0
testsuite/css/parser/calc-errors.ref.css
Normal file
0
testsuite/css/parser/calc-errors.ref.css
Normal file
@ -17,3 +17,7 @@ d {
|
|||||||
e {
|
e {
|
||||||
border-left-width: calc(1px + 1px);
|
border-left-width: calc(1px + 1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f {
|
||||||
|
background-size: calc(2 * 3px + 4px * 5 - 6px / 3);
|
||||||
|
}
|
||||||
|
|||||||
@ -17,3 +17,7 @@ d {
|
|||||||
e {
|
e {
|
||||||
border-left-width: 2px;
|
border-left-width: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f {
|
||||||
|
background-size: 24px;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user