css: Add initial support for calc()

So far, calc() only supports literals, ie it's completely useless.
This commit is contained in:
Benjamin Otte 2016-02-12 06:56:14 +01:00
parent a52ecd2be6
commit cd6dc954f2
7 changed files with 264 additions and 1 deletions

View File

@ -387,6 +387,7 @@ gtk_private_h_sources = \
gtkcssarrayvalueprivate.h \
gtkcssbgsizevalueprivate.h \
gtkcssbordervalueprivate.h \
gtkcsscalcvalueprivate.h \
gtkcsscolorvalueprivate.h \
gtkcsscornervalueprivate.h \
gtkcsscustomgadgetprivate.h \
@ -652,6 +653,7 @@ gtk_base_c_sources = \
gtkcssarrayvalue.c \
gtkcssbgsizevalue.c \
gtkcssbordervalue.c \
gtkcsscalcvalue.c \
gtkcsscolorvalue.c \
gtkcsscornervalue.c \
gtkcsscustomgadget.c \

152
gtk/gtkcsscalcvalue.c Normal file
View File

@ -0,0 +1,152 @@
/* GTK - The GIMP Toolkit
* Copyright © 2016 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkcsscalcvalueprivate.h"
#include "gtkcssenumvalueprivate.h"
#include "gtkcssinitialvalueprivate.h"
#include "gtkstylepropertyprivate.h"
#include "fallback-c89.c"
struct _GtkCssValue {
GTK_CSS_VALUE_BASE
GtkCssValue *term;
};
static void
gtk_css_value_calc_free (GtkCssValue *value)
{
_gtk_css_value_unref (value->term);
g_slice_free (GtkCssValue, value);
}
static GtkCssValue *gtk_css_calc_value_new (GtkCssValue *term);
static GtkCssValue *
gtk_css_value_calc_compute (GtkCssValue *calc,
guint property_id,
GtkStyleProviderPrivate *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
{
GtkCssValue *computed_term;
computed_term = _gtk_css_value_compute (calc->term, property_id, provider, style, parent_style);
if (computed_term == calc->term)
return _gtk_css_value_ref (calc);
return gtk_css_calc_value_new (computed_term);
}
static gboolean
gtk_css_value_calc_equal (const GtkCssValue *calc1,
const GtkCssValue *calc2)
{
return _gtk_css_value_equal (calc1->term, calc2->term);
}
static GtkCssValue *
gtk_css_value_calc_transition (GtkCssValue *start,
GtkCssValue *end,
guint property_id,
double progress)
{
return NULL;
}
static void
gtk_css_value_calc_print (const GtkCssValue *calc,
GString *string)
{
g_string_append (string, "calc(");
_gtk_css_value_print (calc->term, string);
g_string_append (string, ")");
}
double
gtk_css_value_calc_get (const GtkCssValue *value,
double one_hundred_percent)
{
return _gtk_css_number_value_get (value->term, one_hundred_percent);
}
GtkCssDimension
gtk_css_value_calc_get_dimension (const GtkCssValue *value)
{
return gtk_css_number_value_get_dimension (value->term);
}
gboolean
gtk_css_value_calc_has_percent (const GtkCssValue *value)
{
return gtk_css_number_value_has_percent (value->term);
}
static const GtkCssNumberValueClass GTK_CSS_VALUE_CALC = {
{
gtk_css_value_calc_free,
gtk_css_value_calc_compute,
gtk_css_value_calc_equal,
gtk_css_value_calc_transition,
gtk_css_value_calc_print
},
gtk_css_value_calc_get,
gtk_css_value_calc_get_dimension,
gtk_css_value_calc_has_percent,
};
static GtkCssValue *
gtk_css_calc_value_new (GtkCssValue *term)
{
GtkCssValue *result;
result = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_CALC.value_class);
result->term = term;
return result;
}
GtkCssValue *
gtk_css_calc_value_parse (GtkCssParser *parser,
GtkCssNumberParseFlags flags)
{
GtkCssValue *term;
if (!_gtk_css_parser_try (parser, "calc(", TRUE))
{
_gtk_css_parser_error (parser, "Expected 'calc('");
return NULL;
}
term = _gtk_css_number_value_parse (parser, flags);
if (term == NULL)
return NULL;
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_value_unref (term);
_gtk_css_parser_error (parser, "Expected ')' for calc() statement");
return NULL;
}
return gtk_css_calc_value_new (term);
}

View File

@ -0,0 +1,30 @@
/*
* Copyright © 2016 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_CSS_CALC_VALUE_PRIVATE_H__
#define __GTK_CSS_CALC_VALUE_PRIVATE_H__
#include "gtkcssnumbervalueprivate.h"
G_BEGIN_DECLS
GtkCssValue * gtk_css_calc_value_parse (GtkCssParser *parser,
GtkCssNumberParseFlags flags);
G_END_DECLS
#endif /* __GTK_CSS_CALC_VALUE_PRIVATE_H__ */

View File

@ -19,6 +19,7 @@
#include "gtkcssnumbervalueprivate.h"
#include "gtkcsscalcvalueprivate.h"
#include "gtkcssdimensionvalueprivate.h"
struct _GtkCssValue {
@ -51,13 +52,17 @@ _gtk_css_number_value_new (double value,
gboolean
gtk_css_number_value_can_parse (GtkCssParser *parser)
{
return _gtk_css_parser_has_number (parser);
return _gtk_css_parser_has_number (parser)
|| _gtk_css_parser_has_prefix (parser, "calc");
}
GtkCssValue *
_gtk_css_number_value_parse (GtkCssParser *parser,
GtkCssNumberParseFlags flags)
{
if (_gtk_css_parser_has_prefix (parser, "calc"))
return gtk_css_calc_value_parse (parser, flags);
return gtk_css_dimension_value_parse (parser, flags);
}

View File

@ -226,6 +226,8 @@ test_data = \
border-width.ref.css \
box-shadow.css \
box-shadow.ref.css \
calc-simple.css \
calc-simple.ref.css \
close-at-end-of-file.css \
close-at-end-of-file.errors \
close-at-end-of-file.ref.css \

View File

@ -0,0 +1,31 @@
a {
margin: calc(1px) calc(0px) calc(-3px);
}
b {
background-position: calc(50%) calc(0%);
}
c {
background-image: linear-gradient(calc(45deg), red calc(0%), green calc(100%));
}
d {
border-radius: calc(1px) calc(2px) / calc(1em) calc(2em) calc(3em);
}
e {
border-top-left-radius: calc(50%);
}
f {
border-image-source: radial-gradient(circle calc(20px) at calc(50%) calc(25%), red calc(0%), blue calc(100%));
}
g {
border-left: calc(1px);
}
h {
border-right: red calc(2px);
}

View File

@ -0,0 +1,41 @@
a {
margin-bottom: -3px;
margin-left: 0;
margin-right: 0;
margin-top: 1px;
}
b {
background-position: top;
}
c {
background-image: linear-gradient(45deg, rgb(255,0,0) 0, rgb(0,128,0) 100%);
}
d {
border-bottom-left-radius: 2px 2em;
border-bottom-right-radius: 1px 3em;
border-top-left-radius: 1px 1em;
border-top-right-radius: 2px 2em;
}
e {
border-top-left-radius: 50%;
}
f {
border-image-source: radial-gradient(circle 20px at center 25%, rgb(255,0,0) 0, rgb(0,0,255) 100%);
}
g {
border-left-color: initial;
border-left-style: initial;
border-left-width: 1px;
}
h {
border-right-color: rgb(255,0,0);
border-right-style: initial;
border-right-width: 2px;
}