Compare commits
78 Commits
async-dial
...
wip/otte/t
Author | SHA1 | Date | |
---|---|---|---|
|
be2d3321aa | ||
|
62b2f979e5 | ||
|
c6951488f9 | ||
|
935141b915 | ||
|
947f3ea5ec | ||
|
7ca4ef7b0c | ||
|
3659741414 | ||
|
02f31d7133 | ||
|
58aa294970 | ||
|
55e3a1927d | ||
|
b00e9f629c | ||
|
f54cf9d9d4 | ||
|
e351cbc83f | ||
|
f4fba248ad | ||
|
27bbfe9d80 | ||
|
63b1e50835 | ||
|
87eeb1bdfb | ||
|
fabc1f633d | ||
|
01b320f563 | ||
|
ca5075c26d | ||
|
9c12d01ba3 | ||
|
9d07be0238 | ||
|
f36217dda6 | ||
|
0f9526578a | ||
|
afe70c4568 | ||
|
eb86a5fb3f | ||
|
ca1c46c170 | ||
|
23c729459f | ||
|
7a36b5df90 | ||
|
69506210a2 | ||
|
0fbdcc3cd1 | ||
|
ff7f62b3ca | ||
|
b3ee232880 | ||
|
768cdf8a55 | ||
|
b2c070551b | ||
|
e1444d0d35 | ||
|
33b2684c29 | ||
|
16dff3909b | ||
|
920a88512b | ||
|
fcf65bf8a4 | ||
|
a39d1a620f | ||
|
ae248b3443 | ||
|
28babd269b | ||
|
fef9fe68d0 | ||
|
945bddf120 | ||
|
87d3bb5799 | ||
|
19d88eca1f | ||
|
2e05b896de | ||
|
c767617d54 | ||
|
90e423b34d | ||
|
d7c8885852 | ||
|
567d9887f7 | ||
|
32d671cfd7 | ||
|
fae4a14177 | ||
|
c0ee099aa1 | ||
|
ab402e2400 | ||
|
c5d5825cf0 | ||
|
6c72e9423f | ||
|
73d69e353b | ||
|
e9bc9082a4 | ||
|
b9c77aadec | ||
|
974ca283ef | ||
|
0a11e4d36b | ||
|
662065bdb1 | ||
|
9c02a600b2 | ||
|
257273c439 | ||
|
348052064a | ||
|
14e7c42200 | ||
|
e64a143ff7 | ||
|
840d347d59 | ||
|
674ca8ae1c | ||
|
25b2e2f3e5 | ||
|
48b241833a | ||
|
460ad90379 | ||
|
adeec6656c | ||
|
78fd100ade | ||
|
b1a8537314 | ||
|
7a69ea89ca |
@@ -397,6 +397,8 @@ gtk_private_h_sources = \
|
||||
gtkcsscornervalueprivate.h \
|
||||
gtkcsscustomgadgetprivate.h \
|
||||
gtkcsscustompropertyprivate.h \
|
||||
gtkcssdeclarationprivate.h \
|
||||
gtkcssdefinecolorruleprivate.h \
|
||||
gtkcssdimensionvalueprivate.h \
|
||||
gtkcsseasevalueprivate.h \
|
||||
gtkcssenginevalueprivate.h \
|
||||
@@ -417,9 +419,13 @@ gtk_private_h_sources = \
|
||||
gtkcssimagescaledprivate.h \
|
||||
gtkcssimagevalueprivate.h \
|
||||
gtkcssimagewin32private.h \
|
||||
gtkcssimportruleprivate.h \
|
||||
gtkcssinheritvalueprivate.h \
|
||||
gtkcssinitialvalueprivate.h \
|
||||
gtkcsskeyframeruleprivate.h \
|
||||
gtkcsskeyframesprivate.h \
|
||||
gtkcsskeyframesruleprivate.h \
|
||||
gtkcsslonghanddeclarationprivate.h \
|
||||
gtkcsslookupprivate.h \
|
||||
gtkcssmatcherprivate.h \
|
||||
gtkcssnodeprivate.h \
|
||||
@@ -431,12 +437,16 @@ gtk_private_h_sources = \
|
||||
gtkcsspathnodeprivate.h \
|
||||
gtkcsspositionvalueprivate.h \
|
||||
gtkcssproviderprivate.h \
|
||||
gtkcssrbtreeprivate.h \
|
||||
gtkcssrepeatvalueprivate.h \
|
||||
gtkcssrgbavalueprivate.h \
|
||||
gtkcssruleprivate.h \
|
||||
gtkcssrulelistprivate.h \
|
||||
gtkcsssectionprivate.h \
|
||||
gtkcssselectorprivate.h \
|
||||
gtkcssshadowsvalueprivate.h \
|
||||
gtkcssshadowvalueprivate.h \
|
||||
gtkcssshorthanddeclarationprivate.h \
|
||||
gtkcssshorthandpropertyprivate.h \
|
||||
gtkcssstaticstyleprivate.h \
|
||||
gtkcssstringvalueprivate.h \
|
||||
@@ -444,6 +454,11 @@ gtk_private_h_sources = \
|
||||
gtkcssstylechangeprivate.h \
|
||||
gtkcssstyleprivate.h \
|
||||
gtkcssstylepropertyprivate.h \
|
||||
gtkcssstyledeclarationprivate.h \
|
||||
gtkcssstyleruleprivate.h \
|
||||
gtkcssstylesheetprivate.h \
|
||||
gtkcsstokenizerprivate.h \
|
||||
gtkcsstokensourceprivate.h \
|
||||
gtkcsstransformvalueprivate.h \
|
||||
gtkcsstransientnodeprivate.h \
|
||||
gtkcsstransitionprivate.h \
|
||||
@@ -452,6 +467,7 @@ gtk_private_h_sources = \
|
||||
gtkcssvalueprivate.h \
|
||||
gtkcsswin32sizevalueprivate.h \
|
||||
gtkcsswidgetnodeprivate.h \
|
||||
gtkcsswidgetstyledeclarationprivate.h \
|
||||
gtkcustompaperunixdialog.h \
|
||||
gtkdialogprivate.h \
|
||||
gtkdndprivate.h \
|
||||
@@ -665,6 +681,8 @@ gtk_base_c_sources = \
|
||||
gtkcsscornervalue.c \
|
||||
gtkcsscustomgadget.c \
|
||||
gtkcsscustomproperty.c \
|
||||
gtkcssdeclaration.c \
|
||||
gtkcssdefinecolorrule.c \
|
||||
gtkcssdimensionvalue.c \
|
||||
gtkcsseasevalue.c \
|
||||
gtkcssenumvalue.c \
|
||||
@@ -685,9 +703,13 @@ gtk_base_c_sources = \
|
||||
gtkcssimagescaled.c \
|
||||
gtkcssimagevalue.c \
|
||||
gtkcssimagewin32.c \
|
||||
gtkcssimportrule.c \
|
||||
gtkcssinheritvalue.c \
|
||||
gtkcssinitialvalue.c \
|
||||
gtkcsskeyframerule.c \
|
||||
gtkcsskeyframes.c \
|
||||
gtkcsskeyframesrule.c \
|
||||
gtkcsslonghanddeclaration.c \
|
||||
gtkcsslookup.c \
|
||||
gtkcssmatcher.c \
|
||||
gtkcssnode.c \
|
||||
@@ -699,21 +721,30 @@ gtk_base_c_sources = \
|
||||
gtkcsspathnode.c \
|
||||
gtkcsspositionvalue.c \
|
||||
gtkcssprovider.c \
|
||||
gtkcssrbtree.c \
|
||||
gtkcssrepeatvalue.c \
|
||||
gtkcssrgbavalue.c \
|
||||
gtkcssrule.c \
|
||||
gtkcssrulelist.c \
|
||||
gtkcsssection.c \
|
||||
gtkcssselector.c \
|
||||
gtkcssstringvalue.c \
|
||||
gtkcssstyle.c \
|
||||
gtkcssstylechange.c \
|
||||
gtkcssshadowsvalue.c \
|
||||
gtkcssshadowvalue.c \
|
||||
gtkcssshorthanddeclaration.c \
|
||||
gtkcssshorthandproperty.c \
|
||||
gtkcssshorthandpropertyimpl.c \
|
||||
gtkcssstaticstyle.c \
|
||||
gtkcssstyle.c \
|
||||
gtkcssstylechange.c \
|
||||
gtkcssstyledeclaration.c \
|
||||
gtkcssstylefuncs.c \
|
||||
gtkcssstyleproperty.c \
|
||||
gtkcssstylepropertyimpl.c \
|
||||
gtkcssstylerule.c \
|
||||
gtkcssstylesheet.c \
|
||||
gtkcsstokenizer.c \
|
||||
gtkcsstokensource.c \
|
||||
gtkcsstransformvalue.c \
|
||||
gtkcsstransientnode.c \
|
||||
gtkcsstransition.c \
|
||||
@@ -722,6 +753,7 @@ gtk_base_c_sources = \
|
||||
gtkcsstypes.c \
|
||||
gtkcssvalue.c \
|
||||
gtkcsswidgetnode.c \
|
||||
gtkcsswidgetstyledeclaration.c \
|
||||
gtkcsswin32sizevalue.c \
|
||||
gtkdialog.c \
|
||||
gtkdragsource.c \
|
||||
|
@@ -397,7 +397,7 @@ gtk_gradient_to_string (GtkGradient *gradient)
|
||||
|
||||
g_return_val_if_fail (gradient != NULL, NULL);
|
||||
|
||||
str = g_string_new ("-gtk-gradient (");
|
||||
str = g_string_new ("-gtk-gradient(");
|
||||
|
||||
if (gradient->radius0 == 0 && gradient->radius1 == 0)
|
||||
{
|
||||
|
@@ -379,6 +379,36 @@ _gtk_css_array_value_parse (GtkCssParser *parser,
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_array_value_token_parse (GtkCssTokenSource *source,
|
||||
GtkCssValue *(* parse_func) (GtkCssTokenSource *))
|
||||
{
|
||||
GtkCssValue *value, *result;
|
||||
GPtrArray *values;
|
||||
|
||||
values = g_ptr_array_new ();
|
||||
|
||||
while (TRUE) {
|
||||
value = parse_func (source);
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
g_ptr_array_set_free_func (values, (GDestroyNotify) _gtk_css_value_unref);
|
||||
g_ptr_array_free (values, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_ptr_array_add (values, value);
|
||||
if (!gtk_css_token_is (gtk_css_token_source_get_token (source), GTK_CSS_TOKEN_COMMA))
|
||||
break;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
result = _gtk_css_array_value_new_from_array ((GtkCssValue **) values->pdata, values->len);
|
||||
g_ptr_array_free (values, TRUE);
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_array_value_get_nth (const GtkCssValue *value,
|
||||
guint i)
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_CSS_ARRAY_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
#include "gtktypes.h"
|
||||
|
||||
@@ -31,6 +32,8 @@ GtkCssValue * _gtk_css_array_value_new_from_array (GtkCssValue **
|
||||
guint n_values);
|
||||
GtkCssValue * _gtk_css_array_value_parse (GtkCssParser *parser,
|
||||
GtkCssValue * (* parse_func) (GtkCssParser *));
|
||||
GtkCssValue * gtk_css_array_value_token_parse (GtkCssTokenSource *source,
|
||||
GtkCssValue * (* parse_func) (GtkCssTokenSource *));
|
||||
|
||||
GtkCssValue * _gtk_css_array_value_get_nth (const GtkCssValue *value,
|
||||
guint i);
|
||||
|
@@ -212,6 +212,65 @@ _gtk_css_bg_size_value_parse (GtkCssParser *parser)
|
||||
return _gtk_css_bg_size_value_new (x, y);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_bg_size_value_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GtkCssValue *x, *y;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "cover"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return _gtk_css_value_ref (&cover_singleton);
|
||||
}
|
||||
if (gtk_css_token_is_ident (token, "contain"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return _gtk_css_value_ref (&contain_singleton);
|
||||
}
|
||||
|
||||
if (gtk_css_token_is_ident (token, "auto"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
x = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_POSITIVE_ONLY
|
||||
| GTK_CSS_PARSE_PERCENT
|
||||
| GTK_CSS_PARSE_LENGTH);
|
||||
if (x == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "auto"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
y = NULL;
|
||||
}
|
||||
else if (!gtk_css_number_value_check_token (token))
|
||||
{
|
||||
y = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_POSITIVE_ONLY
|
||||
| GTK_CSS_PARSE_PERCENT
|
||||
| GTK_CSS_PARSE_LENGTH);
|
||||
if (y == NULL)
|
||||
{
|
||||
_gtk_css_value_unref (x);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return _gtk_css_bg_size_value_new (x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_bg_size_compute_size_for_cover_contain (gboolean cover,
|
||||
GtkCssImage *image,
|
||||
|
@@ -20,8 +20,9 @@
|
||||
#ifndef __GTK_CSS_BG_SIZE_VALUE_PRIVATE_H__
|
||||
#define __GTK_CSS_BG_SIZE_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcssimageprivate.h"
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -29,6 +30,7 @@ G_BEGIN_DECLS
|
||||
GtkCssValue * _gtk_css_bg_size_value_new (GtkCssValue *x,
|
||||
GtkCssValue *y);
|
||||
GtkCssValue * _gtk_css_bg_size_value_parse (GtkCssParser *parser);
|
||||
GtkCssValue * gtk_css_bg_size_value_token_parse (GtkCssTokenSource *source);
|
||||
|
||||
void _gtk_css_bg_size_value_compute_size (const GtkCssValue *bg_size,
|
||||
GtkCssImage *image,
|
||||
|
@@ -204,6 +204,72 @@ _gtk_css_border_value_parse (GtkCssParser *parser,
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_border_value_token_parse (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags,
|
||||
gboolean allow_auto,
|
||||
gboolean allow_fill)
|
||||
{
|
||||
GtkCssValue *result;
|
||||
const GtkCssToken *token;
|
||||
int i;
|
||||
|
||||
result = _gtk_css_border_value_new (NULL, NULL, NULL, NULL);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (allow_fill && gtk_css_token_is_ident (token, "fill"))
|
||||
{
|
||||
result->fill = TRUE;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
}
|
||||
|
||||
for (i = 0;
|
||||
!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF);
|
||||
i++, token = gtk_css_token_source_get_token (source))
|
||||
{
|
||||
if (allow_fill && !result->fill && gtk_css_token_is_ident (token, "fill"))
|
||||
{
|
||||
result->fill = TRUE;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (allow_auto && gtk_css_token_is_ident (token, "auto"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == 4)
|
||||
break;
|
||||
|
||||
result->values[i] = gtk_css_number_value_token_parse (source, flags);
|
||||
if (result->values[i] == NULL)
|
||||
{
|
||||
_gtk_css_value_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (i <= 0)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a number");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
_gtk_css_value_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (; i < 4; i++)
|
||||
{
|
||||
if (result->values[(i - 1) >> 1])
|
||||
result->values[i] = _gtk_css_value_ref (result->values[(i - 1) >> 1]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_border_value_get_top (const GtkCssValue *value)
|
||||
{
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_CSS_BORDER_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
@@ -34,6 +35,10 @@ GtkCssValue * _gtk_css_border_value_parse (GtkCssParser *par
|
||||
GtkCssNumberParseFlags flags,
|
||||
gboolean allow_auto,
|
||||
gboolean allow_fill);
|
||||
GtkCssValue * gtk_css_border_value_token_parse (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags,
|
||||
gboolean allow_auto,
|
||||
gboolean allow_fill);
|
||||
|
||||
GtkCssValue * _gtk_css_border_value_get_top (const GtkCssValue *value);
|
||||
GtkCssValue * _gtk_css_border_value_get_right (const GtkCssValue *value);
|
||||
|
@@ -485,3 +485,208 @@ gtk_css_calc_value_parse (GtkCssParser *parser,
|
||||
return value;
|
||||
}
|
||||
|
||||
GtkCssValue * gtk_css_calc_value_token_parse_sum (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags);
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_calc_value_token_parse_value (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GtkCssValue *result;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
|
||||
if (gtk_css_token_is_function (token, "calc"))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Nested calc() expressions are not allowed.");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_OPEN_PARENS))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
result = gtk_css_calc_value_token_parse_sum (source, flags);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Missing closing ')' in calc() subterm");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
_gtk_css_value_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = gtk_css_number_value_token_parse (source, flags);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_calc_value_token_parse_product (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags)
|
||||
{
|
||||
GtkCssValue *result, *value, *temp;
|
||||
GtkCssNumberParseFlags actual_flags;
|
||||
|
||||
actual_flags = flags | GTK_CSS_PARSE_NUMBER;
|
||||
|
||||
result = gtk_css_calc_value_token_parse_value (source, actual_flags);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
const GtkCssToken *token = gtk_css_token_source_get_token (source);
|
||||
|
||||
if (actual_flags != GTK_CSS_PARSE_NUMBER && !is_number (result))
|
||||
actual_flags = GTK_CSS_PARSE_NUMBER;
|
||||
|
||||
if (gtk_css_token_is_delim (token, '*'))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
value = gtk_css_calc_value_token_parse_product (source, 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_token_is_delim (token, '/'))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
value = gtk_css_calc_value_token_parse_product (source, 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
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_number (result) && !(flags & GTK_CSS_PARSE_NUMBER))
|
||||
{
|
||||
gtk_css_token_source_error (source, "calc() product term has no units");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
fail:
|
||||
_gtk_css_value_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_calc_value_token_parse_sum (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags)
|
||||
{
|
||||
GtkCssValue *result;
|
||||
const GtkCssToken *token;
|
||||
|
||||
result = gtk_css_calc_value_token_parse_product (source, flags);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GtkCssValue *next, *temp;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_delim (token, '+'))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
next = gtk_css_calc_value_token_parse_product (source, flags);
|
||||
if (next == NULL)
|
||||
goto fail;
|
||||
}
|
||||
else if (gtk_css_token_is_delim (token, '-'))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
temp = gtk_css_calc_value_token_parse_product (source, flags);
|
||||
if (temp == NULL)
|
||||
goto fail;
|
||||
next = gtk_css_number_value_multiply (temp, -1);
|
||||
_gtk_css_value_unref (temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
temp = gtk_css_number_value_add (result, next);
|
||||
_gtk_css_value_unref (result);
|
||||
_gtk_css_value_unref (next);
|
||||
result = temp;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
fail:
|
||||
_gtk_css_value_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_calc_value_token_parse (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
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 negative numbers everywhere */
|
||||
flags &= ~GTK_CSS_POSITIVE_ONLY;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is_function (token, "calc"))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected 'calc('");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
value = gtk_css_calc_value_token_parse_sum (source, flags);
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
|
||||
{
|
||||
_gtk_css_value_unref (value);
|
||||
gtk_css_token_source_error (source, "Expected ')' after calc() statement");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@@ -27,6 +27,8 @@ GtkCssValue * gtk_css_calc_value_new_sum (GtkCssValue *val
|
||||
|
||||
GtkCssValue * gtk_css_calc_value_parse (GtkCssParser *parser,
|
||||
GtkCssNumberParseFlags flags);
|
||||
GtkCssValue * gtk_css_calc_value_token_parse (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -860,3 +860,333 @@ _gtk_css_color_value_parse (GtkCssParser *parser)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_comma (GtkCssTokenSource *source)
|
||||
{
|
||||
if (!gtk_css_token_is (gtk_css_token_source_get_token (source), GTK_CSS_TOKEN_COMMA))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected ','");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_percentage (GtkCssTokenSource *source,
|
||||
double *d)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_PERCENTAGE))
|
||||
{
|
||||
*d = token->number.number;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a percentage.");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_css_color_value_check_token (const GtkCssToken *token)
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
|
||||
return gtk_css_token_is_ident (token, "currentColor")
|
||||
|| gtk_css_token_is_ident (token, "transparent")
|
||||
|| gtk_css_token_is_function (token, "rgb")
|
||||
|| gtk_css_token_is_function (token, "rgba")
|
||||
|| gtk_css_token_is_function (token, "lighter")
|
||||
|| gtk_css_token_is_function (token, "darker")
|
||||
|| gtk_css_token_is_function (token, "shade")
|
||||
|| gtk_css_token_is_function (token, "alpha")
|
||||
|| gtk_css_token_is_function (token, "mix")
|
||||
|| gtk_css_token_is_function (token, GTK_WIN32_THEME_SYMBOLIC_COLOR_NAME)
|
||||
|| gtk_css_token_is (token, GTK_CSS_TOKEN_AT_KEYWORD)
|
||||
|| gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID)
|
||||
|| gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_UNRESTRICTED)
|
||||
|| (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) && gdk_rgba_parse (&rgba, token->string.string));
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_color_value_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GtkCssValue *value;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "currentColor"))
|
||||
{
|
||||
value = _gtk_css_color_value_new_current_color ();
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_ident (token, "transparent"))
|
||||
{
|
||||
GdkRGBA transparent = { 0, 0, 0, 0 };
|
||||
|
||||
value = _gtk_css_color_value_new_literal (&transparent);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_FUNCTION))
|
||||
{
|
||||
if (gtk_css_token_is_function (token, "rgb") ||
|
||||
gtk_css_token_is_function (token, "rgba"))
|
||||
{
|
||||
gboolean has_alpha = gtk_css_token_is_function (token, "rgba");
|
||||
GdkRGBA rgba;
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_PERCENTAGE))
|
||||
{
|
||||
if (!parse_percentage (source, &rgba.red) ||
|
||||
!parse_comma (source) ||
|
||||
!parse_percentage (source, &rgba.green) ||
|
||||
!parse_comma (source) ||
|
||||
!parse_percentage (source, &rgba.blue))
|
||||
return NULL;
|
||||
rgba.red = CLAMP (rgba.red, 0, 100.0) / 100.0;
|
||||
rgba.green = CLAMP (rgba.green, 0, 100.0) / 100.0;
|
||||
rgba.blue = CLAMP (rgba.blue, 0, 100.0) / 100.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!gtk_css_token_source_consume_number (source, &rgba.red) ||
|
||||
!parse_comma (source) ||
|
||||
!gtk_css_token_source_consume_number (source, &rgba.green) ||
|
||||
!parse_comma (source) ||
|
||||
!gtk_css_token_source_consume_number (source, &rgba.blue))
|
||||
return NULL;
|
||||
rgba.red = CLAMP (rgba.red, 0, 255.0) / 255.0;
|
||||
rgba.green = CLAMP (rgba.green, 0, 255.0) / 255.0;
|
||||
rgba.blue = CLAMP (rgba.blue, 0, 255.0) / 255.0;
|
||||
}
|
||||
|
||||
if (has_alpha)
|
||||
{
|
||||
if (!parse_comma (source) ||
|
||||
!gtk_css_token_source_consume_number (source, &rgba.alpha))
|
||||
return NULL;
|
||||
rgba.alpha = CLAMP (rgba.alpha, 0, 1.0);
|
||||
}
|
||||
else
|
||||
rgba.alpha = 1.0;
|
||||
|
||||
value = _gtk_css_color_value_new_literal (&rgba);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "lighter"))
|
||||
{
|
||||
GtkCssValue *child;
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
child = gtk_css_color_value_token_parse (source);
|
||||
if (child == NULL)
|
||||
return NULL;
|
||||
|
||||
value = _gtk_css_color_value_new_shade (child, 1.3);
|
||||
|
||||
_gtk_css_value_unref (child);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "darker"))
|
||||
{
|
||||
GtkCssValue *child;
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
child = gtk_css_color_value_token_parse (source);
|
||||
if (child == NULL)
|
||||
return NULL;
|
||||
|
||||
value = _gtk_css_color_value_new_shade (child, 0.7);
|
||||
|
||||
_gtk_css_value_unref (child);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "shade"))
|
||||
{
|
||||
GtkCssValue *child;
|
||||
double d;
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
child = gtk_css_color_value_token_parse (source);
|
||||
if (child == NULL)
|
||||
return NULL;
|
||||
if (!parse_comma (source) ||
|
||||
!gtk_css_token_source_consume_number (source, &d))
|
||||
{
|
||||
_gtk_css_value_unref (child);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
value = _gtk_css_color_value_new_shade (child, d);
|
||||
|
||||
_gtk_css_value_unref (child);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "alpha"))
|
||||
{
|
||||
GtkCssValue *child;
|
||||
double d;
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
child = gtk_css_color_value_token_parse (source);
|
||||
if (child == NULL)
|
||||
return NULL;
|
||||
if (!parse_comma (source) ||
|
||||
!gtk_css_token_source_consume_number (source, &d))
|
||||
{
|
||||
_gtk_css_value_unref (child);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
value = _gtk_css_color_value_new_alpha (child, d);
|
||||
|
||||
_gtk_css_value_unref (child);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "mix"))
|
||||
{
|
||||
GtkCssValue *child1, *child2;
|
||||
double d;
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
child1 = gtk_css_color_value_token_parse (source);
|
||||
if (child1 == NULL)
|
||||
return NULL;
|
||||
if (!parse_comma (source) ||
|
||||
!(child2 = gtk_css_color_value_token_parse (source)))
|
||||
{
|
||||
_gtk_css_value_unref (child1);
|
||||
return NULL;
|
||||
}
|
||||
if (!parse_comma (source) ||
|
||||
!gtk_css_token_source_consume_number (source, &d))
|
||||
{
|
||||
_gtk_css_value_unref (child1);
|
||||
_gtk_css_value_unref (child2);
|
||||
return NULL;
|
||||
}
|
||||
value = _gtk_css_color_value_new_mix (child1, child2, d);
|
||||
_gtk_css_value_unref (child1);
|
||||
_gtk_css_value_unref (child2);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, GTK_WIN32_THEME_SYMBOLIC_COLOR_NAME))
|
||||
{
|
||||
GtkWin32Theme *theme;
|
||||
int id;
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
theme = gtk_win32_theme_token_parse (source);
|
||||
if (theme == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!parse_comma (source))
|
||||
{
|
||||
gtk_win32_theme_unref (theme);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
id = gtk_win32_get_sys_color_id_for_name (token->string.string);
|
||||
if (id == -1)
|
||||
{
|
||||
gtk_css_token_source_error (source, "'%s' is not a win32 color name.", token->string.string);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (!gtk_css_token_source_consume_integer (source, &id))
|
||||
{
|
||||
gtk_win32_theme_unref (theme);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
value = gtk_css_color_value_new_win32_for_theme (theme, id);
|
||||
gtk_win32_theme_unref (theme);
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
|
||||
{
|
||||
gtk_css_token_source_error (source, "No closing ')' in color definition");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_AT_KEYWORD))
|
||||
{
|
||||
value = _gtk_css_color_value_new_name (token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_UNRESTRICTED))
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
const char *s = token->string.string;
|
||||
|
||||
if (g_ascii_isxdigit (s[0]) && g_ascii_isxdigit (s[1]) && g_ascii_isxdigit (s[2]) && s[3] == '\0')
|
||||
{
|
||||
rgba.red = g_ascii_xdigit_value(s[0]) / 15.0;
|
||||
rgba.green = g_ascii_xdigit_value(s[1]) / 15.0;
|
||||
rgba.blue = g_ascii_xdigit_value(s[2]) / 15.0;
|
||||
rgba.alpha = 1.0;
|
||||
}
|
||||
else if (g_ascii_isxdigit (s[0]) && g_ascii_isxdigit (s[1]) && g_ascii_isxdigit (s[2]) &&
|
||||
g_ascii_isxdigit (s[3]) && g_ascii_isxdigit (s[4]) && g_ascii_isxdigit (s[5]) &&
|
||||
s[6] == '\0')
|
||||
{
|
||||
rgba.red = (g_ascii_xdigit_value(s[0]) * 16 + g_ascii_xdigit_value(s[1])) / 255.0;
|
||||
rgba.green = (g_ascii_xdigit_value(s[2]) * 16 + g_ascii_xdigit_value(s[3])) / 255.0;
|
||||
rgba.blue = (g_ascii_xdigit_value(s[4]) * 16 + g_ascii_xdigit_value(s[5])) / 255.0;
|
||||
rgba.alpha = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Not a valid color value, needs to be #RGB or #RRGGBB");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
value = _gtk_css_color_value_new_literal (&rgba);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
const char *name = token->string.string;
|
||||
|
||||
if (!gdk_rgba_parse (&rgba, name))
|
||||
{
|
||||
gtk_css_token_source_error (source, "'%s' is not a valid color name", name);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
value = _gtk_css_color_value_new_literal (&rgba);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Not a color definition");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#define __GTK_CSS_COLOR_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -41,7 +42,9 @@ GtkCssValue * _gtk_css_color_value_new_win32 (const gchar *theme_c
|
||||
gint id);
|
||||
GtkCssValue * _gtk_css_color_value_new_current_color (void);
|
||||
|
||||
GtkCssValue * _gtk_css_color_value_parse (GtkCssParser *parser);
|
||||
GtkCssValue * _gtk_css_color_value_parse (GtkCssParser *parser);
|
||||
GtkCssValue * gtk_css_color_value_token_parse (GtkCssTokenSource *source);
|
||||
gboolean gtk_css_color_value_check_token (const GtkCssToken *token);
|
||||
|
||||
GtkCssValue * _gtk_css_color_value_resolve (GtkCssValue *color,
|
||||
GtkStyleProviderPrivate *provider,
|
||||
|
@@ -151,6 +151,38 @@ _gtk_css_corner_value_parse (GtkCssParser *parser)
|
||||
return _gtk_css_corner_value_new (x, y);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_corner_value_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssValue *x, *y;
|
||||
|
||||
x = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_POSITIVE_ONLY
|
||||
| GTK_CSS_PARSE_PERCENT
|
||||
| GTK_CSS_NUMBER_AS_PIXELS
|
||||
| GTK_CSS_PARSE_LENGTH);
|
||||
if (x == NULL)
|
||||
return NULL;
|
||||
|
||||
if (gtk_css_token_is (gtk_css_token_source_get_token (source), GTK_CSS_TOKEN_EOF))
|
||||
y = _gtk_css_value_ref (x);
|
||||
else
|
||||
{
|
||||
y = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_POSITIVE_ONLY
|
||||
| GTK_CSS_PARSE_PERCENT
|
||||
| GTK_CSS_NUMBER_AS_PIXELS
|
||||
| GTK_CSS_PARSE_LENGTH);
|
||||
if (y == NULL)
|
||||
{
|
||||
_gtk_css_value_unref (x);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return _gtk_css_corner_value_new (x, y);
|
||||
}
|
||||
|
||||
double
|
||||
_gtk_css_corner_value_get_x (const GtkCssValue *corner,
|
||||
double one_hundred_percent)
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_CSS_CORNER_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -28,6 +29,7 @@ G_BEGIN_DECLS
|
||||
GtkCssValue * _gtk_css_corner_value_new (GtkCssValue *x,
|
||||
GtkCssValue *y);
|
||||
GtkCssValue * _gtk_css_corner_value_parse (GtkCssParser *parser);
|
||||
GtkCssValue * gtk_css_corner_value_token_parse (GtkCssTokenSource *source);
|
||||
|
||||
double _gtk_css_corner_value_get_x (const GtkCssValue *corner,
|
||||
double one_hundred_percent);
|
||||
|
@@ -43,6 +43,14 @@ gtk_css_custom_property_parse_value (GtkStyleProperty *property,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
gtk_css_custom_property_token_parse (GtkStyleProperty *property,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
gtk_css_token_source_unknown (source, "Custom CSS properties are no longer supported.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_custom_property_query (GtkStyleProperty *property,
|
||||
GValue *value,
|
||||
@@ -81,6 +89,7 @@ _gtk_css_custom_property_class_init (GtkCssCustomPropertyClass *klass)
|
||||
GtkStylePropertyClass *property_class = GTK_STYLE_PROPERTY_CLASS (klass);
|
||||
|
||||
property_class->parse_value = gtk_css_custom_property_parse_value;
|
||||
property_class->token_parse = gtk_css_custom_property_token_parse;
|
||||
property_class->query = gtk_css_custom_property_query;
|
||||
property_class->assign = gtk_css_custom_property_assign;
|
||||
}
|
||||
|
196
gtk/gtkcssdeclaration.c
Normal file
196
gtk/gtkcssdeclaration.c
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssdeclarationprivate.h"
|
||||
|
||||
#include "gtkcsslonghanddeclarationprivate.h"
|
||||
#include "gtkcssshorthanddeclarationprivate.h"
|
||||
#include "gtkcsswidgetstyledeclarationprivate.h"
|
||||
#include "gtkstylepropertyprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_NAME,
|
||||
PROP_PARENT_STYLE,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
typedef struct _GtkCssDeclarationPrivate GtkCssDeclarationPrivate;
|
||||
struct _GtkCssDeclarationPrivate {
|
||||
GtkCssStyleDeclaration *parent_style;
|
||||
};
|
||||
|
||||
static GParamSpec *declaration_props[NUM_PROPERTIES] = { NULL, };
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkCssDeclaration, gtk_css_declaration, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_css_declaration_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkCssDeclaration *declaration = GTK_CSS_DECLARATION (gobject);
|
||||
GtkCssDeclarationPrivate *priv = gtk_css_declaration_get_instance_private (declaration);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PARENT_STYLE:
|
||||
priv->parent_style = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_declaration_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkCssDeclaration *declaration = GTK_CSS_DECLARATION (gobject);
|
||||
GtkCssDeclarationPrivate *priv = gtk_css_declaration_get_instance_private (declaration);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, gtk_css_declaration_get_name (declaration));
|
||||
break;
|
||||
|
||||
case PROP_PARENT_STYLE:
|
||||
g_value_set_object (value, priv->parent_style);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_declaration_class_init (GtkCssDeclarationClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = gtk_css_declaration_set_property;
|
||||
object_class->get_property = gtk_css_declaration_get_property;
|
||||
|
||||
declaration_props[PROP_NAME] =
|
||||
g_param_spec_string ("name",
|
||||
P_("name"),
|
||||
P_("Name this declaration defines a value for"),
|
||||
NULL,
|
||||
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
declaration_props[PROP_PARENT_STYLE] =
|
||||
g_param_spec_object ("parent-style",
|
||||
P_("parent style"),
|
||||
P_("The parent style"),
|
||||
GTK_TYPE_CSS_STYLE_DECLARATION,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, declaration_props);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_declaration_init (GtkCssDeclaration *declaration)
|
||||
{
|
||||
}
|
||||
|
||||
GtkCssDeclaration *
|
||||
gtk_css_declaration_new_parse (GtkCssStyleDeclaration *style,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GtkStyleProperty *prop;
|
||||
char *name;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a property name");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
name = g_utf8_strdown (token->string.string, -1);
|
||||
prop = _gtk_style_property_lookup (name);
|
||||
g_free (name);
|
||||
if (GTK_IS_CSS_STYLE_PROPERTY (prop))
|
||||
return gtk_css_longhand_declaration_new_parse (style, source);
|
||||
else if (GTK_IS_CSS_SHORTHAND_PROPERTY (prop))
|
||||
return gtk_css_shorthand_declaration_new_parse (style, source);
|
||||
else if (gtk_css_widget_style_declaration_accepts_name (token->string.string))
|
||||
return gtk_css_widget_style_declaration_new_parse (style, source);
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_unknown (source,
|
||||
"Property name \"%s\" does not define a valid property",
|
||||
token->string.string);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GtkCssStyleDeclaration *
|
||||
gtk_css_declaration_get_parent_style (GtkCssDeclaration *decl)
|
||||
{
|
||||
GtkCssDeclarationPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_DECLARATION (decl), NULL);
|
||||
|
||||
priv = gtk_css_declaration_get_instance_private (decl);
|
||||
|
||||
return priv->parent_style;
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_css_declaration_get_name (GtkCssDeclaration *decl)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CSS_DECLARATION (decl), NULL);
|
||||
|
||||
return GTK_CSS_DECLARATION_GET_CLASS (decl)->get_name (decl);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_declaration_print_value (GtkCssDeclaration *decl,
|
||||
GString *string)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CSS_DECLARATION (decl));
|
||||
g_return_if_fail (string != NULL);
|
||||
|
||||
return GTK_CSS_DECLARATION_GET_CLASS (decl)->print_value (decl, string);
|
||||
}
|
||||
|
||||
char *
|
||||
gtk_css_declaration_get_value_string (GtkCssDeclaration *decl)
|
||||
{
|
||||
GString *string;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_DECLARATION (decl), NULL);
|
||||
|
||||
string = g_string_new (NULL);
|
||||
gtk_css_declaration_print_value (decl, string);
|
||||
|
||||
return g_string_free (string, FALSE);
|
||||
}
|
68
gtk/gtkcssdeclarationprivate.h
Normal file
68
gtk/gtkcssdeclarationprivate.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_DECLARATION_PRIVATE_H__
|
||||
#define __GTK_CSS_DECLARATION_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssstyledeclarationprivate.h"
|
||||
|
||||
#include "gtk/gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_DECLARATION (gtk_css_declaration_get_type ())
|
||||
#define GTK_CSS_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_DECLARATION, GtkCssDeclaration))
|
||||
#define GTK_CSS_DECLARATION_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_DECLARATION, GtkCssDeclarationClass))
|
||||
#define GTK_IS_CSS_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_DECLARATION))
|
||||
#define GTK_IS_CSS_DECLARATION_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_DECLARATION))
|
||||
#define GTK_CSS_DECLARATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_DECLARATION, GtkCssDeclarationClass))
|
||||
|
||||
/* typedef struct _GtkCssDeclaration GtkCssDeclaration; */
|
||||
typedef struct _GtkCssDeclarationClass GtkCssDeclarationClass;
|
||||
|
||||
struct _GtkCssDeclaration
|
||||
{
|
||||
GObject parent;
|
||||
};
|
||||
|
||||
struct _GtkCssDeclarationClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
const char * (* get_name) (GtkCssDeclaration *decl);
|
||||
void (* print_value) (GtkCssDeclaration *decl,
|
||||
GString *string);
|
||||
};
|
||||
|
||||
GType gtk_css_declaration_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssDeclaration * gtk_css_declaration_new_parse (GtkCssStyleDeclaration *style,
|
||||
GtkCssTokenSource *source);
|
||||
|
||||
const char * gtk_css_declaration_get_name (GtkCssDeclaration *decl);
|
||||
GtkCssStyleDeclaration *gtk_css_declaration_get_parent_style (GtkCssDeclaration *decl);
|
||||
|
||||
void gtk_css_declaration_print_value (GtkCssDeclaration *decl,
|
||||
GString *string);
|
||||
char * gtk_css_declaration_get_value_string (GtkCssDeclaration *decl);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_DECLARATION_PRIVATE_H__ */
|
152
gtk/gtkcssdefinecolorrule.c
Normal file
152
gtk/gtkcssdefinecolorrule.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssdefinecolorruleprivate.h"
|
||||
|
||||
#include "gtkcsscolorvalueprivate.h"
|
||||
#include "gtkcssstylesheetprivate.h"
|
||||
|
||||
typedef struct _GtkCssDefineColorRulePrivate GtkCssDefineColorRulePrivate;
|
||||
struct _GtkCssDefineColorRulePrivate {
|
||||
char *name;
|
||||
GtkCssValue *color;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssDefineColorRule, gtk_css_define_color_rule, GTK_TYPE_CSS_RULE)
|
||||
|
||||
static void
|
||||
gtk_css_define_color_rule_finalize (GObject *object)
|
||||
{
|
||||
GtkCssDefineColorRule *define_color_rule = GTK_CSS_DEFINE_COLOR_RULE (object);
|
||||
GtkCssDefineColorRulePrivate *priv = gtk_css_define_color_rule_get_instance_private (define_color_rule);
|
||||
|
||||
g_free (priv->name);
|
||||
if (priv->color)
|
||||
_gtk_css_value_unref (priv->color);
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_define_color_rule_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_define_color_rule_class_init (GtkCssDefineColorRuleClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_define_color_rule_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_define_color_rule_init (GtkCssDefineColorRule *define_color_rule)
|
||||
{
|
||||
}
|
||||
|
||||
static GtkCssRule *
|
||||
gtk_css_define_color_rule_new (GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_CSS_DEFINE_COLOR_RULE,
|
||||
"parent-rule", parent_rule,
|
||||
"parent-stylesheet", parent_style_sheet,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GtkCssRule *
|
||||
gtk_css_define_color_rule_new_parse (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
GtkCssDefineColorRulePrivate *priv;
|
||||
const GtkCssToken *token;
|
||||
GtkCssRule *result;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
g_return_val_if_fail (parent_rule == NULL || GTK_IS_CSS_RULE (parent_rule), NULL);
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (parent_style_sheet), NULL);
|
||||
|
||||
result = gtk_css_define_color_rule_new (parent_rule, parent_style_sheet);
|
||||
priv = gtk_css_define_color_rule_get_instance_private (GTK_CSS_DEFINE_COLOR_RULE (result));
|
||||
gtk_css_token_source_set_consumer (source, G_OBJECT (result));
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (token->type != GTK_CSS_TOKEN_AT_KEYWORD ||
|
||||
g_ascii_strcasecmp (token->string.string, "define-color") != 0)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected '@define-color'");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected name of color");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
priv->name = g_strdup (token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
priv->color = gtk_css_color_value_token_parse (source);
|
||||
if (priv->color == NULL)
|
||||
{
|
||||
g_object_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_SEMICOLON))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected ';' at end of @define-color");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_css_define_color_rule_get_name (GtkCssDefineColorRule *rule)
|
||||
{
|
||||
GtkCssDefineColorRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_DEFINE_COLOR_RULE (rule), NULL);
|
||||
|
||||
priv = gtk_css_define_color_rule_get_instance_private (rule);
|
||||
|
||||
return priv->name;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_define_color_rule_get_value (GtkCssDefineColorRule *rule)
|
||||
{
|
||||
GtkCssDefineColorRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_DEFINE_COLOR_RULE (rule), NULL);
|
||||
|
||||
priv = gtk_css_define_color_rule_get_instance_private (rule);
|
||||
|
||||
return priv->color;
|
||||
}
|
60
gtk/gtkcssdefinecolorruleprivate.h
Normal file
60
gtk/gtkcssdefinecolorruleprivate.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_DEFINE_COLOR_RULE_PRIVATE_H__
|
||||
#define __GTK_CSS_DEFINE_COLOR_RULE_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssruleprivate.h"
|
||||
#include "gtk/gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_DEFINE_COLOR_RULE (gtk_css_define_color_rule_get_type ())
|
||||
#define GTK_CSS_DEFINE_COLOR_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_DEFINE_COLOR_RULE, GtkCssDefineColorRule))
|
||||
#define GTK_CSS_DEFINE_COLOR_RULE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_DEFINE_COLOR_RULE, GtkCssDefineColorRuleClass))
|
||||
#define GTK_IS_CSS_DEFINE_COLOR_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_DEFINE_COLOR_RULE))
|
||||
#define GTK_IS_CSS_DEFINE_COLOR_RULE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_DEFINE_COLOR_RULE))
|
||||
#define GTK_CSS_DEFINE_COLOR_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_DEFINE_COLOR_RULE, GtkCssDefineColorRuleClass))
|
||||
|
||||
typedef struct _GtkCssDefineColorRule GtkCssDefineColorRule;
|
||||
typedef struct _GtkCssDefineColorRuleClass GtkCssDefineColorRuleClass;
|
||||
|
||||
struct _GtkCssDefineColorRule
|
||||
{
|
||||
GtkCssRule parent;
|
||||
};
|
||||
|
||||
struct _GtkCssDefineColorRuleClass
|
||||
{
|
||||
GtkCssRuleClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_define_color_rule_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssRule * gtk_css_define_color_rule_new_parse (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet);
|
||||
|
||||
const char * gtk_css_define_color_rule_get_name (GtkCssDefineColorRule *rule);
|
||||
GtkCssValue * gtk_css_define_color_rule_get_value (GtkCssDefineColorRule *rule);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_DEFINE_COLOR_RULE_PRIVATE_H__ */
|
@@ -323,3 +323,115 @@ gtk_css_dimension_value_new (double value,
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_dimension_value_token_parse (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags)
|
||||
{
|
||||
const GtkCssToken *token = gtk_css_token_source_get_token (source);
|
||||
double d;
|
||||
GtkCssUnit unit;
|
||||
|
||||
if ((gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_NUMBER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_NUMBER)) &&
|
||||
((flags & (GTK_CSS_PARSE_NUMBER | GTK_CSS_NUMBER_AS_PIXELS)) ||
|
||||
(token->number.number == 0.0 && (flags & (GTK_CSS_PARSE_LENGTH | GTK_CSS_PARSE_ANGLE)))))
|
||||
{
|
||||
d = token->number.number;
|
||||
if (flags & GTK_CSS_NUMBER_AS_PIXELS)
|
||||
{
|
||||
if (d != 0.0)
|
||||
gtk_css_token_source_deprecated (source, "Not using units is deprecated. Assuming 'px'.");
|
||||
unit = GTK_CSS_PX;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & GTK_CSS_PARSE_NUMBER)
|
||||
unit = GTK_CSS_NUMBER;
|
||||
else if (flags & GTK_CSS_PARSE_LENGTH)
|
||||
unit = GTK_CSS_PX;
|
||||
else if (flags & GTK_CSS_PARSE_ANGLE)
|
||||
unit = GTK_CSS_DEG;
|
||||
}
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_PERCENTAGE) &&
|
||||
(flags & GTK_CSS_PARSE_PERCENT))
|
||||
{
|
||||
d = token->number.number;
|
||||
unit = GTK_CSS_PERCENT;
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_DIMENSION))
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
GtkCssUnit unit;
|
||||
GtkCssNumberParseFlags flag;
|
||||
} units[] = {
|
||||
{ "px", GTK_CSS_PX, GTK_CSS_PARSE_LENGTH },
|
||||
{ "pt", GTK_CSS_PT, GTK_CSS_PARSE_LENGTH },
|
||||
{ "em", GTK_CSS_EM, GTK_CSS_PARSE_LENGTH },
|
||||
{ "ex", GTK_CSS_EX, GTK_CSS_PARSE_LENGTH },
|
||||
{ "rem", GTK_CSS_REM, GTK_CSS_PARSE_LENGTH },
|
||||
{ "pc", GTK_CSS_PC, GTK_CSS_PARSE_LENGTH },
|
||||
{ "in", GTK_CSS_IN, GTK_CSS_PARSE_LENGTH },
|
||||
{ "cm", GTK_CSS_CM, GTK_CSS_PARSE_LENGTH },
|
||||
{ "mm", GTK_CSS_MM, GTK_CSS_PARSE_LENGTH },
|
||||
{ "rad", GTK_CSS_RAD, GTK_CSS_PARSE_ANGLE },
|
||||
{ "deg", GTK_CSS_DEG, GTK_CSS_PARSE_ANGLE },
|
||||
{ "grad", GTK_CSS_GRAD, GTK_CSS_PARSE_ANGLE },
|
||||
{ "turn", GTK_CSS_TURN, GTK_CSS_PARSE_ANGLE },
|
||||
{ "s", GTK_CSS_S, GTK_CSS_PARSE_TIME },
|
||||
{ "ms", GTK_CSS_MS, GTK_CSS_PARSE_TIME }
|
||||
};
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (units); i++)
|
||||
{
|
||||
if ((flags & units[i].flag) == 0)
|
||||
continue;
|
||||
|
||||
if (g_ascii_strcasecmp (units[i].name, token->dimension.dimension) == 0)
|
||||
{
|
||||
d = token->dimension.value;
|
||||
unit = units[i].unit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == G_N_ELEMENTS (units))
|
||||
{
|
||||
gtk_css_token_source_error (source, "'%s' is not a valid unit.", token->dimension.dimension);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & GTK_CSS_PARSE_LENGTH)
|
||||
gtk_css_token_source_error (source, "Expected a length");
|
||||
else if (flags & GTK_CSS_PARSE_ANGLE)
|
||||
gtk_css_token_source_error (source, "Expected an angle");
|
||||
else if (flags & GTK_CSS_PARSE_TIME)
|
||||
gtk_css_token_source_error (source, "Expected a time");
|
||||
else if (flags & GTK_CSS_PARSE_PERCENT)
|
||||
gtk_css_token_source_error (source, "Expected a percentage");
|
||||
else
|
||||
gtk_css_token_source_error (source, "Expected a number");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((flags & GTK_CSS_POSITIVE_ONLY) && d < 0.0)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Negative values are not allowed");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return gtk_css_dimension_value_new (d, unit);
|
||||
}
|
||||
|
||||
|
@@ -30,6 +30,9 @@ GtkCssValue * gtk_css_dimension_value_new (double val
|
||||
GtkCssValue * gtk_css_dimension_value_parse (GtkCssParser *parser,
|
||||
GtkCssNumberParseFlags flags);
|
||||
|
||||
GtkCssValue * gtk_css_dimension_value_token_parse (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_DIMENSION_VALUE_PRIVATE_H__ */
|
||||
|
@@ -37,7 +37,7 @@ struct _GtkCssValue {
|
||||
double y2;
|
||||
} cubic;
|
||||
struct {
|
||||
guint steps;
|
||||
int steps;
|
||||
gboolean start;
|
||||
} steps;
|
||||
} u;
|
||||
@@ -125,7 +125,7 @@ gtk_css_value_ease_print (const GtkCssValue *ease,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_printf (string, "steps(%u%s)", ease->u.steps.steps, ease->u.steps.start ? ",start" : "");
|
||||
g_string_append_printf (string, "steps(%d%s)", ease->u.steps.steps, ease->u.steps.start ? ",start" : "");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -167,7 +167,7 @@ _gtk_css_ease_value_new_cubic_bezier (double x1,
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
_gtk_css_ease_value_new_steps (guint n_steps,
|
||||
_gtk_css_ease_value_new_steps (gint n_steps,
|
||||
gboolean start)
|
||||
{
|
||||
GtkCssValue *value;
|
||||
@@ -327,6 +327,137 @@ _gtk_css_ease_value_parse (GtkCssParser *parser)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static guint
|
||||
token_parse_cubic_bezier (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
{
|
||||
double *numbers = data;
|
||||
|
||||
if (!gtk_css_token_source_consume_number (source, &numbers[n]))
|
||||
return FALSE;
|
||||
|
||||
/* XXX: This error is too late */
|
||||
if (n % 2 == 0 &&
|
||||
(numbers[n] < 0 || numbers[n] > 1.0))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Value %g out of range. Must be from 0.0 to 1.0", numbers[n]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static guint
|
||||
token_parse_steps (GtkCssTokenSource *source,
|
||||
guint nth_argument,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssValue *value = data;
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (nth_argument == 0)
|
||||
{
|
||||
if (!gtk_css_token_source_consume_integer (source, &value->u.steps.steps))
|
||||
return 0;
|
||||
|
||||
if (value->u.steps.steps <= 0)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Number of steps must be greater than 0");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, "start"))
|
||||
value->u.steps.start = TRUE;
|
||||
else if (gtk_css_token_is_ident (token, "end"))
|
||||
value->u.steps.start = FALSE;
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Only allowed values are 'start' and 'end'");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return 0;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_ease_value_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
guint i;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
for (i = 0; i < G_N_ELEMENTS (parser_values); i++)
|
||||
{
|
||||
if (parser_values[i].needs_custom)
|
||||
continue;
|
||||
|
||||
if (gtk_css_token_is_ident (token, parser_values[i].name))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
if (parser_values[i].is_bezier)
|
||||
return _gtk_css_ease_value_new_cubic_bezier (parser_values[i].values[0],
|
||||
parser_values[i].values[1],
|
||||
parser_values[i].values[2],
|
||||
parser_values[i].values[3]);
|
||||
else
|
||||
return _gtk_css_ease_value_new_steps (parser_values[i].values[0],
|
||||
parser_values[i].values[1] != 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (gtk_css_token_is_function (token, "cubic-bezier"))
|
||||
{
|
||||
double numbers[4];
|
||||
|
||||
if (!gtk_css_token_source_consume_function (source, 4, 4, token_parse_cubic_bezier, numbers))
|
||||
{
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
return _gtk_css_ease_value_new_cubic_bezier (numbers[0], numbers[1], numbers[2], numbers[3]);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "steps"))
|
||||
{
|
||||
GtkCssValue *value = _gtk_css_ease_value_new_steps (1, FALSE);
|
||||
|
||||
if (!gtk_css_token_source_consume_function (source, 1, 2, token_parse_steps, value))
|
||||
{
|
||||
_gtk_css_value_unref (value);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Unknown ease value");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline double
|
||||
cubic (double a, double b, double c, double t)
|
||||
{
|
||||
return ((a * t + b) * t + c) * t;
|
||||
}
|
||||
|
||||
static inline double
|
||||
cubic_deriv (double a, double b, double c, double t)
|
||||
{
|
||||
return (3 * a * t + 2 * b) * t + c;
|
||||
}
|
||||
|
||||
double
|
||||
_gtk_css_ease_value_transform (const GtkCssValue *ease,
|
||||
double progress)
|
||||
@@ -343,8 +474,36 @@ _gtk_css_ease_value_transform (const GtkCssValue *ease,
|
||||
case GTK_CSS_EASE_CUBIC_BEZIER:
|
||||
{
|
||||
static const double epsilon = 0.00001;
|
||||
double ax, bx, cx;
|
||||
double ay, by, cy;
|
||||
double tmin, t, tmax;
|
||||
guint i;
|
||||
|
||||
cx = 3.0 * ease->u.cubic.x1;
|
||||
bx = 3.0 * (ease->u.cubic.x2 - ease->u.cubic.x1) - cx;
|
||||
ax = 1.0 - cx - bx;
|
||||
cy = 3.0 * ease->u.cubic.y1;
|
||||
by = 3.0 * (ease->u.cubic.y2 - ease->u.cubic.y1) - cy;
|
||||
ay = 1.0 - cy - by;
|
||||
|
||||
/* Try with Newton's method first */
|
||||
t = progress;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
double sample, deriv;
|
||||
|
||||
sample = cubic (ax, bx, cx, t);
|
||||
if (fabs (sample - t) < epsilon)
|
||||
return cubic (ay, by, cy, t);
|
||||
|
||||
deriv = cubic_deriv (ax, bx, cx, t);
|
||||
if (deriv < epsilon)
|
||||
return cubic (ay, by, cy, t);
|
||||
|
||||
t = t - (sample - t) / deriv;
|
||||
}
|
||||
|
||||
/* Fallback if Newton doesn't converge */
|
||||
tmin = 0.0;
|
||||
tmax = 1.0;
|
||||
t = progress;
|
||||
@@ -352,9 +511,7 @@ _gtk_css_ease_value_transform (const GtkCssValue *ease,
|
||||
while (tmin < tmax)
|
||||
{
|
||||
double sample;
|
||||
sample = (((1.0 + 3 * ease->u.cubic.x1 - 3 * ease->u.cubic.x2) * t
|
||||
+ -6 * ease->u.cubic.x1 + 3 * ease->u.cubic.x2) * t
|
||||
+ 3 * ease->u.cubic.x1 ) * t;
|
||||
sample = cubic (ax, bx, cx, t);
|
||||
if (fabs(sample - progress) < epsilon)
|
||||
break;
|
||||
|
||||
@@ -365,9 +522,7 @@ _gtk_css_ease_value_transform (const GtkCssValue *ease,
|
||||
t = (tmax + tmin) * .5;
|
||||
}
|
||||
|
||||
return (((1.0 + 3 * ease->u.cubic.y1 - 3 * ease->u.cubic.y2) * t
|
||||
+ -6 * ease->u.cubic.y1 + 3 * ease->u.cubic.y2) * t
|
||||
+ 3 * ease->u.cubic.y1 ) * t;
|
||||
return cubic (ay, by, cy, t);
|
||||
}
|
||||
case GTK_CSS_EASE_STEPS:
|
||||
progress *= ease->u.steps.steps;
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_CSS_EASE_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -31,6 +32,7 @@ GtkCssValue * _gtk_css_ease_value_new_cubic_bezier (double x1,
|
||||
double y2);
|
||||
gboolean _gtk_css_ease_value_can_parse (GtkCssParser *parser);
|
||||
GtkCssValue * _gtk_css_ease_value_parse (GtkCssParser *parser);
|
||||
GtkCssValue * gtk_css_ease_value_token_parse (GtkCssTokenSource *source);
|
||||
|
||||
double _gtk_css_ease_value_transform (const GtkCssValue *ease,
|
||||
double progress);
|
||||
|
@@ -130,6 +130,40 @@ _gtk_css_engine_value_parse (GtkCssParser *parser)
|
||||
return _gtk_css_engine_value_new (engine);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_engine_value_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkThemingEngine *engine;
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "none"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return _gtk_css_engine_value_new (gtk_theming_engine_load (NULL));
|
||||
}
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a valid theme name");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
engine = gtk_theming_engine_load (token->string.string);
|
||||
|
||||
if (engine == NULL)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Theming engine '%s' not found", token->string.string);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
return _gtk_css_engine_value_new (engine);
|
||||
}
|
||||
|
||||
GtkThemingEngine *
|
||||
_gtk_css_engine_value_get_engine (const GtkCssValue *value)
|
||||
{
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_CSS_ENGINE_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
#include "deprecated/gtkthemingengine.h"
|
||||
|
||||
@@ -28,6 +29,7 @@ G_BEGIN_DECLS
|
||||
|
||||
GtkCssValue * _gtk_css_engine_value_new (GtkThemingEngine *engine);
|
||||
GtkCssValue * _gtk_css_engine_value_parse (GtkCssParser *parser);
|
||||
GtkCssValue * gtk_css_engine_value_token_parse (GtkCssTokenSource *source);
|
||||
|
||||
GtkThemingEngine * _gtk_css_engine_value_get_engine (const GtkCssValue *engine);
|
||||
|
||||
|
@@ -101,6 +101,23 @@ _gtk_css_border_style_value_new (GtkBorderStyle border_style)
|
||||
return _gtk_css_value_ref (&border_style_values[border_style]);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_border_style_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (border_style_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, border_style_values[i].name))
|
||||
return _gtk_css_value_ref (&border_style_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_border_style_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -243,6 +260,23 @@ _gtk_css_font_size_value_new (GtkCssFontSize font_size)
|
||||
return _gtk_css_value_ref (&font_size_values[font_size]);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_font_size_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (font_size_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, font_size_values[i].name))
|
||||
return _gtk_css_value_ref (&font_size_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_font_size_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -291,6 +325,23 @@ _gtk_css_font_style_value_new (PangoStyle font_style)
|
||||
return _gtk_css_value_ref (&font_style_values[font_style]);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_font_style_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (font_style_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, font_style_values[i].name))
|
||||
return _gtk_css_value_ref (&font_style_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_font_style_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -338,6 +389,23 @@ _gtk_css_font_variant_value_new (PangoVariant font_variant)
|
||||
return _gtk_css_value_ref (&font_variant_values[font_variant]);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_font_variant_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (font_variant_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, font_variant_values[i].name))
|
||||
return _gtk_css_value_ref (&font_variant_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_font_variant_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -467,6 +535,23 @@ _gtk_css_font_weight_value_new (PangoWeight font_weight)
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_font_weight_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (font_weight_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, font_weight_values[i].name))
|
||||
return _gtk_css_value_ref (&font_weight_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_font_weight_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -529,6 +614,23 @@ _gtk_css_font_stretch_value_new (PangoStretch font_stretch)
|
||||
return _gtk_css_value_ref (&font_stretch_values[font_stretch]);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_font_stretch_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (font_stretch_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, font_stretch_values[i].name))
|
||||
return _gtk_css_value_ref (&font_stretch_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_font_stretch_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -577,6 +679,23 @@ _gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line)
|
||||
return _gtk_css_value_ref (&text_decoration_line_values[line]);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_text_decoration_line_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (text_decoration_line_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, text_decoration_line_values[i].name))
|
||||
return _gtk_css_value_ref (&text_decoration_line_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_text_decoration_line_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -625,6 +744,23 @@ _gtk_css_text_decoration_style_value_new (GtkTextDecorationStyle style)
|
||||
return _gtk_css_value_ref (&text_decoration_style_values[style]);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_text_decoration_style_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (text_decoration_style_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, text_decoration_style_values[i].name))
|
||||
return _gtk_css_value_ref (&text_decoration_style_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_text_decoration_style_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -679,6 +815,23 @@ _gtk_css_area_value_new (GtkCssArea area)
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_area_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (area_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, area_values[i].name))
|
||||
return _gtk_css_value_ref (&area_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_area_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -734,6 +887,23 @@ _gtk_css_direction_value_new (GtkCssDirection direction)
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_direction_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (direction_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, direction_values[i].name))
|
||||
return _gtk_css_value_ref (&direction_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_direction_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -790,6 +960,23 @@ _gtk_css_play_state_value_new (GtkCssPlayState play_state)
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_play_state_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (play_state_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, play_state_values[i].name))
|
||||
return _gtk_css_value_ref (&play_state_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_play_state_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -845,6 +1032,23 @@ _gtk_css_fill_mode_value_new (GtkCssFillMode fill_mode)
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_fill_mode_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (fill_mode_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, fill_mode_values[i].name))
|
||||
return _gtk_css_value_ref (&fill_mode_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_fill_mode_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -879,26 +1083,43 @@ static const GtkCssValueClass GTK_CSS_VALUE_ICON_EFFECT = {
|
||||
gtk_css_value_enum_print
|
||||
};
|
||||
|
||||
static GtkCssValue image_effect_values[] = {
|
||||
static GtkCssValue icon_effect_values[] = {
|
||||
{ >K_CSS_VALUE_ICON_EFFECT, 1, GTK_CSS_ICON_EFFECT_NONE, "none" },
|
||||
{ >K_CSS_VALUE_ICON_EFFECT, 1, GTK_CSS_ICON_EFFECT_HIGHLIGHT, "highlight" },
|
||||
{ >K_CSS_VALUE_ICON_EFFECT, 1, GTK_CSS_ICON_EFFECT_DIM, "dim" }
|
||||
};
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_icon_effect_value_new (GtkCssIconEffect image_effect)
|
||||
_gtk_css_icon_effect_value_new (GtkCssIconEffect icon_effect)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (image_effect_values); i++)
|
||||
for (i = 0; i < G_N_ELEMENTS (icon_effect_values); i++)
|
||||
{
|
||||
if (image_effect_values[i].value == image_effect)
|
||||
return _gtk_css_value_ref (&image_effect_values[i]);
|
||||
if (icon_effect_values[i].value == icon_effect)
|
||||
return _gtk_css_value_ref (&icon_effect_values[i]);
|
||||
}
|
||||
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_icon_effect_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (icon_effect_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, icon_effect_values[i].name))
|
||||
return _gtk_css_value_ref (&icon_effect_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_icon_effect_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -906,10 +1127,10 @@ _gtk_css_icon_effect_value_try_parse (GtkCssParser *parser)
|
||||
|
||||
g_return_val_if_fail (parser != NULL, NULL);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (image_effect_values); i++)
|
||||
for (i = 0; i < G_N_ELEMENTS (icon_effect_values); i++)
|
||||
{
|
||||
if (_gtk_css_parser_try (parser, image_effect_values[i].name, TRUE))
|
||||
return _gtk_css_value_ref (&image_effect_values[i]);
|
||||
if (_gtk_css_parser_try (parser, icon_effect_values[i].name, TRUE))
|
||||
return _gtk_css_value_ref (&icon_effect_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -986,6 +1207,23 @@ _gtk_css_icon_style_value_new (GtkCssIconStyle icon_style)
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_icon_style_value_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (icon_style_values); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, icon_style_values[i].name))
|
||||
return _gtk_css_value_ref (&icon_style_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_icon_style_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
|
@@ -22,67 +22,82 @@
|
||||
|
||||
#include "gtkenums.h"
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcsstypesprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GtkCssValue * _gtk_css_border_style_value_new (GtkBorderStyle border_style);
|
||||
GtkCssValue * gtk_css_border_style_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_border_style_value_try_parse (GtkCssParser *parser);
|
||||
GtkBorderStyle _gtk_css_border_style_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_font_size_value_new (GtkCssFontSize size);
|
||||
GtkCssValue * gtk_css_font_size_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_font_size_value_try_parse (GtkCssParser *parser);
|
||||
GtkCssFontSize _gtk_css_font_size_value_get (const GtkCssValue *value);
|
||||
double _gtk_css_font_size_get_default (GtkStyleProviderPrivate *provider);
|
||||
|
||||
GtkCssValue * _gtk_css_font_style_value_new (PangoStyle style);
|
||||
GtkCssValue * gtk_css_font_style_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_font_style_value_try_parse (GtkCssParser *parser);
|
||||
PangoStyle _gtk_css_font_style_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_font_variant_value_new (PangoVariant variant);
|
||||
GtkCssValue * gtk_css_font_variant_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_font_variant_value_try_parse (GtkCssParser *parser);
|
||||
PangoVariant _gtk_css_font_variant_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_font_weight_value_new (PangoWeight weight);
|
||||
GtkCssValue * gtk_css_font_weight_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_font_weight_value_try_parse (GtkCssParser *parser);
|
||||
PangoWeight _gtk_css_font_weight_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_font_stretch_value_new (PangoStretch stretch);
|
||||
GtkCssValue * gtk_css_font_stretch_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_font_stretch_value_try_parse (GtkCssParser *parser);
|
||||
PangoStretch _gtk_css_font_stretch_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line);
|
||||
GtkCssValue * gtk_css_text_decoration_line_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_text_decoration_line_value_try_parse (GtkCssParser *parser);
|
||||
GtkTextDecorationLine _gtk_css_text_decoration_line_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_text_decoration_style_value_new (GtkTextDecorationStyle style);
|
||||
GtkCssValue * gtk_css_text_decoration_style_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_text_decoration_style_value_try_parse (GtkCssParser *parser);
|
||||
GtkTextDecorationStyle _gtk_css_text_decoration_style_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_area_value_new (GtkCssArea area);
|
||||
GtkCssValue * gtk_css_area_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_area_value_try_parse (GtkCssParser *parser);
|
||||
GtkCssArea _gtk_css_area_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_direction_value_new (GtkCssDirection direction);
|
||||
GtkCssValue * gtk_css_direction_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_direction_value_try_parse (GtkCssParser *parser);
|
||||
GtkCssDirection _gtk_css_direction_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_play_state_value_new (GtkCssPlayState play_state);
|
||||
GtkCssValue * gtk_css_play_state_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_play_state_value_try_parse (GtkCssParser *parser);
|
||||
GtkCssPlayState _gtk_css_play_state_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_fill_mode_value_new (GtkCssFillMode fill_mode);
|
||||
GtkCssValue * gtk_css_fill_mode_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_fill_mode_value_try_parse (GtkCssParser *parser);
|
||||
GtkCssFillMode _gtk_css_fill_mode_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_icon_effect_value_new (GtkCssIconEffect image_effect);
|
||||
GtkCssValue * gtk_css_icon_effect_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_icon_effect_value_try_parse (GtkCssParser *parser);
|
||||
GtkCssIconEffect _gtk_css_icon_effect_value_get (const GtkCssValue *value);
|
||||
void gtk_css_icon_effect_apply (GtkCssIconEffect icon_effect,
|
||||
cairo_surface_t *surface);
|
||||
|
||||
GtkCssValue * _gtk_css_icon_style_value_new (GtkCssIconStyle icon_style);
|
||||
GtkCssValue * gtk_css_icon_style_value_from_token (const GtkCssToken *token);
|
||||
GtkCssValue * _gtk_css_icon_style_value_try_parse (GtkCssParser *parser);
|
||||
GtkCssIconStyle _gtk_css_icon_style_value_get (const GtkCssValue *value);
|
||||
|
||||
|
@@ -162,6 +162,32 @@ gtk_css_icon_theme_value_parse (GtkCssParser *parser)
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_icon_theme_value_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token = gtk_css_token_source_get_token (source);
|
||||
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_STRING))
|
||||
{
|
||||
GtkIconTheme *icontheme;
|
||||
GtkCssValue *value;
|
||||
|
||||
icontheme = gtk_icon_theme_new ();
|
||||
gtk_icon_theme_set_custom_theme (icontheme, token->string.string);
|
||||
value = gtk_css_icon_theme_value_new (icontheme);
|
||||
g_object_unref (icontheme);
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a string");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GtkIconTheme *
|
||||
gtk_css_icon_theme_value_get_icon_theme (GtkCssValue *value)
|
||||
{
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include "gtkicontheme.h"
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -30,6 +31,7 @@ G_BEGIN_DECLS
|
||||
GtkCssValue * gtk_css_icon_theme_value_new (GtkIconTheme *icontheme);
|
||||
|
||||
GtkCssValue * gtk_css_icon_theme_value_parse (GtkCssParser *parser);
|
||||
GtkCssValue * gtk_css_icon_theme_value_token_parse (GtkCssTokenSource *source);
|
||||
|
||||
GtkIconTheme * gtk_css_icon_theme_value_get_icon_theme (GtkCssValue *value);
|
||||
|
||||
|
@@ -410,26 +410,27 @@ _gtk_css_image_get_surface (GtkCssImage *image,
|
||||
return result;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *prefix;
|
||||
GType (* type_func) (void);
|
||||
} image_types[] = {
|
||||
{ "url", _gtk_css_image_url_get_type },
|
||||
{ "-gtk-gradient", _gtk_css_image_gradient_get_type },
|
||||
{ "-gtk-icontheme", _gtk_css_image_icon_theme_get_type },
|
||||
{ "-gtk-scaled", _gtk_css_image_scaled_get_type },
|
||||
{ "-gtk-recolor", _gtk_css_image_recolor_get_type },
|
||||
{ "-gtk-win32-theme-part", _gtk_css_image_win32_get_type },
|
||||
{ "linear-gradient", _gtk_css_image_linear_get_type },
|
||||
{ "repeating-linear-gradient", _gtk_css_image_linear_get_type },
|
||||
{ "radial-gradient", _gtk_css_image_radial_get_type },
|
||||
{ "repeating-radial-gradient", _gtk_css_image_radial_get_type },
|
||||
{ "cross-fade", _gtk_css_image_cross_fade_get_type },
|
||||
{ "image", _gtk_css_image_fallback_get_type }
|
||||
};
|
||||
|
||||
static GType
|
||||
gtk_css_image_get_parser_type (GtkCssParser *parser)
|
||||
{
|
||||
static const struct {
|
||||
const char *prefix;
|
||||
GType (* type_func) (void);
|
||||
} image_types[] = {
|
||||
{ "url", _gtk_css_image_url_get_type },
|
||||
{ "-gtk-gradient", _gtk_css_image_gradient_get_type },
|
||||
{ "-gtk-icontheme", _gtk_css_image_icon_theme_get_type },
|
||||
{ "-gtk-scaled", _gtk_css_image_scaled_get_type },
|
||||
{ "-gtk-recolor", _gtk_css_image_recolor_get_type },
|
||||
{ "-gtk-win32-theme-part", _gtk_css_image_win32_get_type },
|
||||
{ "linear-gradient", _gtk_css_image_linear_get_type },
|
||||
{ "repeating-linear-gradient", _gtk_css_image_linear_get_type },
|
||||
{ "radial-gradient", _gtk_css_image_radial_get_type },
|
||||
{ "repeating-radial-gradient", _gtk_css_image_radial_get_type },
|
||||
{ "cross-fade", _gtk_css_image_cross_fade_get_type },
|
||||
{ "image", _gtk_css_image_fallback_get_type }
|
||||
};
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (image_types); i++)
|
||||
@@ -486,3 +487,57 @@ _gtk_css_image_new_parse (GtkCssParser *parser)
|
||||
return image;
|
||||
}
|
||||
|
||||
static GType
|
||||
gtk_css_image_get_type_from_token (const GtkCssToken *token)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (image_types); i++)
|
||||
{
|
||||
if (gtk_css_token_is_function (token, image_types[i].prefix))
|
||||
return image_types[i].type_func ();
|
||||
}
|
||||
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_URL))
|
||||
return _gtk_css_image_url_get_type ();
|
||||
|
||||
return G_TYPE_INVALID;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_css_image_check_token (const GtkCssToken *token)
|
||||
{
|
||||
return gtk_css_image_get_type_from_token (token) != G_TYPE_INVALID;
|
||||
}
|
||||
|
||||
GtkCssImage *
|
||||
gtk_css_image_new_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GtkCssImageClass *klass;
|
||||
GtkCssImage *image;
|
||||
GType image_type;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
image_type = gtk_css_image_get_type_from_token (token);
|
||||
if (image_type == G_TYPE_INVALID)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Not a valid image");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image = g_object_new (image_type, NULL);
|
||||
|
||||
klass = GTK_CSS_IMAGE_GET_CLASS (image);
|
||||
if (!klass->token_parse (image, source))
|
||||
{
|
||||
g_object_unref (image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
@@ -794,6 +794,24 @@ gtk_css_image_builtin_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_builtin_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
|
||||
if (!gtk_css_token_is_ident (token, "builtin"))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected 'builtin'");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
static void
|
||||
gtk_css_image_builtin_print (GtkCssImage *image,
|
||||
GString *string)
|
||||
@@ -864,6 +882,7 @@ gtk_css_image_builtin_class_init (GtkCssImageBuiltinClass *klass)
|
||||
|
||||
image_class->draw = gtk_css_image_builtin_real_draw;
|
||||
image_class->parse = gtk_css_image_builtin_parse;
|
||||
image_class->token_parse = gtk_css_image_builtin_token_parse;
|
||||
image_class->print = gtk_css_image_builtin_print;
|
||||
image_class->compute = gtk_css_image_builtin_compute;
|
||||
image_class->equal = gtk_css_image_builtin_equal;
|
||||
|
@@ -203,6 +203,101 @@ gtk_css_image_cross_fade_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_cross_fade_parse_progress (GtkCssTokenSource *source,
|
||||
gboolean *parsed_something,
|
||||
double *progress)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GtkCssValue *value;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_number_value_check_token (token))
|
||||
{
|
||||
*parsed_something = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
*parsed_something = TRUE;
|
||||
|
||||
value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY);
|
||||
if (value == NULL)
|
||||
return FALSE;
|
||||
|
||||
*progress = _gtk_css_number_value_get (value, 1.0);
|
||||
_gtk_css_value_unref (value);
|
||||
if (*progress < 0.0 || *progress > 1.0)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Percentage must be between 0%% and 100%%");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_image_cross_fade_token_parse_argument (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssImageCrossFade *cross_fade = data;
|
||||
|
||||
if (arg == 0)
|
||||
{
|
||||
gboolean has_percentage = FALSE;
|
||||
|
||||
if (!gtk_css_image_cross_fade_parse_progress (source, &has_percentage, &cross_fade->progress))
|
||||
return 0;
|
||||
|
||||
cross_fade->end = gtk_css_image_new_token_parse (source);
|
||||
if (cross_fade->end == NULL)
|
||||
return 0;
|
||||
|
||||
if (!has_percentage &&
|
||||
!gtk_css_image_cross_fade_parse_progress (source, &has_percentage, &cross_fade->progress))
|
||||
return 0;
|
||||
if (!has_percentage)
|
||||
cross_fade->progress = 0.5;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (arg == 1)
|
||||
{
|
||||
/* XXX: allow parsing colors here */
|
||||
cross_fade->start = gtk_css_image_new_token_parse (source);
|
||||
if (cross_fade->start == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_cross_fade_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is_function (token, "cross-fade"))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected 'cross-fade('");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return gtk_css_token_source_consume_function (source,
|
||||
2, 2,
|
||||
gtk_css_image_cross_fade_token_parse_argument,
|
||||
image);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_cross_fade_print (GtkCssImage *image,
|
||||
GString *string)
|
||||
@@ -249,6 +344,7 @@ _gtk_css_image_cross_fade_class_init (GtkCssImageCrossFadeClass *klass)
|
||||
image_class->equal = gtk_css_image_cross_fade_equal;
|
||||
image_class->draw = gtk_css_image_cross_fade_draw;
|
||||
image_class->parse = gtk_css_image_cross_fade_parse;
|
||||
image_class->token_parse = gtk_css_image_cross_fade_token_parse;
|
||||
image_class->print = gtk_css_image_cross_fade_print;
|
||||
|
||||
object_class->dispose = gtk_css_image_cross_fade_dispose;
|
||||
|
@@ -231,6 +231,64 @@ gtk_css_image_fallback_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_image_fallback_token_parse_argument (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssImageFallback *fallback = GTK_CSS_IMAGE_FALLBACK (data);
|
||||
const GtkCssToken *token;
|
||||
|
||||
if (fallback->color)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Color argument must be last argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_color_value_check_token (token))
|
||||
{
|
||||
fallback->color = gtk_css_color_value_token_parse (source);
|
||||
if (fallback->color == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkCssImage *image;
|
||||
|
||||
image = gtk_css_image_new_token_parse (source);
|
||||
if (image == NULL)
|
||||
return 0;
|
||||
|
||||
fallback->images = g_realloc (fallback->images, (fallback->n_images + 1) * sizeof (GtkCssImage *));
|
||||
fallback->images[fallback->n_images] = image;
|
||||
fallback->n_images++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_fallback_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is_function (token, "image"))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected 'image('");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return gtk_css_token_source_consume_function (source,
|
||||
1, G_MAXUINT,
|
||||
gtk_css_image_fallback_token_parse_argument,
|
||||
image);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_css_image_fallback_class_init (GtkCssImageFallbackClass *klass)
|
||||
{
|
||||
@@ -242,6 +300,7 @@ _gtk_css_image_fallback_class_init (GtkCssImageFallbackClass *klass)
|
||||
image_class->get_aspect_ratio = gtk_css_image_fallback_get_aspect_ratio;
|
||||
image_class->draw = gtk_css_image_fallback_draw;
|
||||
image_class->parse = gtk_css_image_fallback_parse;
|
||||
image_class->token_parse = gtk_css_image_fallback_token_parse;
|
||||
image_class->compute = gtk_css_image_fallback_compute;
|
||||
image_class->print = gtk_css_image_fallback_print;
|
||||
|
||||
|
@@ -263,6 +263,17 @@ gtk_css_image_gradient_parse (GtkCssImage *image,
|
||||
return gradient->gradient != NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_gradient_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssImageGradient *gradient = GTK_CSS_IMAGE_GRADIENT (image);
|
||||
|
||||
gradient->gradient = gtk_gradient_token_parse (source);
|
||||
|
||||
return gradient->gradient != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_gradient_print (GtkCssImage *image,
|
||||
GString *string)
|
||||
@@ -304,6 +315,7 @@ _gtk_css_image_gradient_class_init (GtkCssImageGradientClass *klass)
|
||||
image_class->transition = gtk_css_image_gradient_transition;
|
||||
image_class->draw = gtk_css_image_gradient_draw;
|
||||
image_class->parse = gtk_css_image_gradient_parse;
|
||||
image_class->token_parse = gtk_css_image_gradient_token_parse;
|
||||
image_class->print = gtk_css_image_gradient_print;
|
||||
|
||||
object_class->dispose = gtk_css_image_gradient_dispose;
|
||||
@@ -505,3 +517,32 @@ _gtk_gradient_parse (GtkCssParser *parser)
|
||||
|
||||
return gradient;
|
||||
}
|
||||
|
||||
static void
|
||||
forward_error_to_source (GtkCssParser *parser,
|
||||
const GError *error,
|
||||
gpointer source)
|
||||
{
|
||||
/* XXX: This is bad because it doesn't emit the error on the right token */
|
||||
gtk_css_token_source_emit_error (source, error);
|
||||
}
|
||||
|
||||
GtkGradient *
|
||||
gtk_gradient_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssParser *parser;
|
||||
GtkGradient *gradient;
|
||||
char *str;
|
||||
|
||||
str = gtk_css_token_source_consume_to_string (source);
|
||||
parser = _gtk_css_parser_new (str,
|
||||
NULL,
|
||||
forward_error_to_source,
|
||||
source);
|
||||
gradient = _gtk_gradient_parse (parser);
|
||||
_gtk_css_parser_free (parser);
|
||||
g_free (str);
|
||||
|
||||
return gradient;
|
||||
}
|
||||
|
||||
|
@@ -52,7 +52,8 @@ struct _GtkCssImageGradientClass
|
||||
GType _gtk_css_image_gradient_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/* for lack of a better place to put it */
|
||||
GtkGradient * _gtk_gradient_parse (GtkCssParser *parser);
|
||||
GtkGradient * _gtk_gradient_parse (GtkCssParser *parser);
|
||||
GtkGradient * gtk_gradient_token_parse (GtkCssTokenSource *source);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -117,6 +117,45 @@ gtk_css_image_icon_theme_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
token_parse_arg (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssImageIconTheme *icon_theme = data;
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_STRING))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a string for the icon name");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return 0;
|
||||
}
|
||||
|
||||
icon_theme->name = g_strdup (token->string.string);
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_icon_theme_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is_function (token, "-gtk-icontheme"))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected '-gtk-icontheme('");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return gtk_css_token_source_consume_function (source, 1, 1, token_parse_arg, image);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_icon_theme_print (GtkCssImage *image,
|
||||
GString *string)
|
||||
@@ -177,6 +216,7 @@ _gtk_css_image_icon_theme_class_init (GtkCssImageIconThemeClass *klass)
|
||||
image_class->get_aspect_ratio = gtk_css_image_icon_theme_get_aspect_ratio;
|
||||
image_class->draw = gtk_css_image_icon_theme_draw;
|
||||
image_class->parse = gtk_css_image_icon_theme_parse;
|
||||
image_class->token_parse = gtk_css_image_icon_theme_token_parse;
|
||||
image_class->print = gtk_css_image_icon_theme_print;
|
||||
image_class->compute = gtk_css_image_icon_theme_compute;
|
||||
image_class->equal = gtk_css_image_icon_theme_equal;
|
||||
|
@@ -361,6 +361,130 @@ gtk_css_image_linear_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_image_linear_token_parse_argument (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssImageLinear *linear = data;
|
||||
GtkCssImageLinearColorStop stop;
|
||||
const GtkCssToken *token;
|
||||
|
||||
if (arg == 0)
|
||||
{
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
|
||||
if (gtk_css_token_is_ident (token, "to"))
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
guint value;
|
||||
guint optional_index[2];
|
||||
} sides[] = {
|
||||
{ "top", 1 << GTK_CSS_TOP, { 2, 3 } },
|
||||
{ "bottom", 1 << GTK_CSS_BOTTOM, { 2, 3 } },
|
||||
{ "left", 1 << GTK_CSS_LEFT, { 0, 1 } },
|
||||
{ "right", 1 << GTK_CSS_RIGHT, { 0, 1 } }
|
||||
};
|
||||
guint i, j;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
for (i = 0; i < G_N_ELEMENTS (sides); i++)
|
||||
{
|
||||
if (!gtk_css_token_is_ident (token, sides[i].name))
|
||||
continue;
|
||||
|
||||
linear->side = sides[i].value;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
for (j = 0; j < G_N_ELEMENTS (sides[i].optional_index); j++)
|
||||
{
|
||||
guint idx = sides[i].optional_index[j];
|
||||
if (!gtk_css_token_is_ident (token, sides[idx].name))
|
||||
continue;
|
||||
|
||||
linear->side = sides[idx].value;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
gtk_css_token_source_error (source, "Expected a direction");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return 0;
|
||||
}
|
||||
else if (!gtk_css_color_value_check_token (token))
|
||||
{
|
||||
/* We check for !color here so the error message is "expected angle"
|
||||
* for nonsense values */
|
||||
linear->angle = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
|
||||
if (linear->angle == NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
linear->side = 1 << GTK_CSS_BOTTOM;
|
||||
}
|
||||
|
||||
stop.color = gtk_css_color_value_token_parse (source);
|
||||
if (stop.color == NULL)
|
||||
return 0;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_number_value_check_token (token))
|
||||
{
|
||||
stop.offset = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_PARSE_PERCENT
|
||||
| GTK_CSS_PARSE_LENGTH);
|
||||
if (stop.offset == NULL)
|
||||
{
|
||||
_gtk_css_value_unref (stop.color);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stop.offset = NULL;
|
||||
}
|
||||
|
||||
g_array_append_val (linear->stops, stop);
|
||||
/* We consume the optional side argument here, too. */
|
||||
return arg == 0 ? 2 : 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_linear_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_function (token, "linear-gradient"))
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "repeating-linear-gradient"))
|
||||
{
|
||||
linear->repeating = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected 'linear-gradient('");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return gtk_css_token_source_consume_function (source,
|
||||
3, G_MAXUINT,
|
||||
gtk_css_image_linear_token_parse_argument,
|
||||
image);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_linear_print (GtkCssImage *image,
|
||||
GString *string)
|
||||
@@ -598,6 +722,7 @@ _gtk_css_image_linear_class_init (GtkCssImageLinearClass *klass)
|
||||
|
||||
image_class->draw = gtk_css_image_linear_draw;
|
||||
image_class->parse = gtk_css_image_linear_parse;
|
||||
image_class->token_parse = gtk_css_image_linear_token_parse;
|
||||
image_class->print = gtk_css_image_linear_print;
|
||||
image_class->compute = gtk_css_image_linear_compute;
|
||||
image_class->equal = gtk_css_image_linear_equal;
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "gtk/gtkcssparserprivate.h"
|
||||
#include "gtk/gtkcsstokensourceprivate.h"
|
||||
#include "gtk/gtkcsstypesprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -77,6 +78,9 @@ struct _GtkCssImageClass
|
||||
/* parse CSS, return TRUE on success */
|
||||
gboolean (* parse) (GtkCssImage *image,
|
||||
GtkCssParser *parser);
|
||||
/* parse CSS, return TRUE on success */
|
||||
gboolean (* token_parse) (GtkCssImage *image,
|
||||
GtkCssTokenSource *source);
|
||||
/* print to CSS */
|
||||
void (* print) (GtkCssImage *image,
|
||||
GString *string);
|
||||
@@ -86,6 +90,8 @@ GType _gtk_css_image_get_type (void) G_GNUC_CONST;
|
||||
|
||||
gboolean _gtk_css_image_can_parse (GtkCssParser *parser);
|
||||
GtkCssImage * _gtk_css_image_new_parse (GtkCssParser *parser);
|
||||
gboolean gtk_css_image_check_token (const GtkCssToken *token);
|
||||
GtkCssImage * gtk_css_image_new_token_parse (GtkCssTokenSource *source);
|
||||
|
||||
int _gtk_css_image_get_width (GtkCssImage *image);
|
||||
int _gtk_css_image_get_height (GtkCssImage *image);
|
||||
|
@@ -386,6 +386,210 @@ gtk_css_image_radial_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_radial_token_parse_size (GtkCssImageRadial *radial,
|
||||
GtkCssTokenSource *source,
|
||||
gboolean *shape_is_known,
|
||||
gboolean *has_size)
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
guint value;
|
||||
} names[] = {
|
||||
{ "closest-side", GTK_CSS_CLOSEST_SIDE },
|
||||
{ "farthest-side", GTK_CSS_FARTHEST_SIDE },
|
||||
{ "closest-corner", GTK_CSS_CLOSEST_CORNER },
|
||||
{ "farthest-corner", GTK_CSS_FARTHEST_CORNER }
|
||||
};
|
||||
const GtkCssToken *token;
|
||||
guint i;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
for (i = 0; i < G_N_ELEMENTS (names); i++)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, names[i].name))
|
||||
{
|
||||
radial->size = names[i].value;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
*has_size = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gtk_css_number_value_check_token (token))
|
||||
{
|
||||
radial->size = GTK_CSS_FARTHEST_CORNER;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
*has_size = TRUE;
|
||||
radial->sizes[0] = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_PARSE_LENGTH |
|
||||
(!*shape_is_known || !radial->circle ? GTK_CSS_PARSE_PERCENT : 0));
|
||||
if (radial->sizes[0] == NULL)
|
||||
return FALSE;
|
||||
if (gtk_css_number_value_has_percent (radial->sizes[0]))
|
||||
{
|
||||
*shape_is_known = TRUE;
|
||||
radial->circle = FALSE;
|
||||
}
|
||||
if (!*shape_is_known)
|
||||
{
|
||||
*shape_is_known = TRUE;
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
radial->circle = !gtk_css_number_value_check_token (token);
|
||||
}
|
||||
|
||||
if (radial->circle)
|
||||
return TRUE;
|
||||
|
||||
radial->sizes[1] = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_PARSE_LENGTH | GTK_CSS_PARSE_PERCENT);
|
||||
if (radial->sizes[1] == NULL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_image_radial_token_parse_argument (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssImageRadial *radial = data;
|
||||
GtkCssImageRadialColorStop stop;
|
||||
const GtkCssToken *token;
|
||||
|
||||
if (arg == 0)
|
||||
{
|
||||
gboolean has_shape = FALSE, shape_is_known = FALSE, has_size = FALSE;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "ellipse"))
|
||||
{
|
||||
shape_is_known = has_shape = TRUE;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_ident (token, "circle"))
|
||||
{
|
||||
radial->circle = TRUE;
|
||||
shape_is_known = has_shape = TRUE;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
if (!gtk_css_image_radial_token_parse_size (radial, source, &shape_is_known, &has_size))
|
||||
return 0;
|
||||
|
||||
if (!has_shape)
|
||||
{
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "ellipse"))
|
||||
{
|
||||
if (shape_is_known && radial->circle)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Specified size not allowed for ellipse");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return 0;
|
||||
}
|
||||
shape_is_known = TRUE;
|
||||
has_shape = TRUE;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_ident (token, "circle"))
|
||||
{
|
||||
if (shape_is_known && !radial->circle)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Specified size not allowed for circle");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return 0;
|
||||
}
|
||||
radial->circle = TRUE;
|
||||
shape_is_known = TRUE;
|
||||
has_shape = TRUE;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
}
|
||||
if (!shape_is_known)
|
||||
{
|
||||
g_assert (radial->size != GTK_CSS_EXPLICIT_SIZE);
|
||||
radial->circle = TRUE;
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "at"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
radial->position = gtk_css_position_value_token_parse (source);
|
||||
if (radial->position == NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
radial->position = _gtk_css_position_value_new (_gtk_css_number_value_new (50, GTK_CSS_PERCENT),
|
||||
_gtk_css_number_value_new (50, GTK_CSS_PERCENT));
|
||||
}
|
||||
|
||||
if (has_shape || has_size)
|
||||
return 1;
|
||||
}
|
||||
|
||||
stop.color = gtk_css_color_value_token_parse (source);
|
||||
if (stop.color == NULL)
|
||||
return 0;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_number_value_check_token (token))
|
||||
{
|
||||
stop.offset = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_PARSE_PERCENT
|
||||
| GTK_CSS_PARSE_LENGTH);
|
||||
if (stop.offset == NULL)
|
||||
{
|
||||
_gtk_css_value_unref (stop.color);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stop.offset = NULL;
|
||||
}
|
||||
|
||||
g_array_append_val (radial->stops, stop);
|
||||
/* We consume the optional side argument here, too. */
|
||||
return arg == 0 ? 2 : 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_radial_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_function (token, "radial-gradient"))
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "repeating-radial-gradient"))
|
||||
{
|
||||
radial->repeating = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected 'radial-gradient('");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return gtk_css_token_source_consume_function (source,
|
||||
3, G_MAXUINT,
|
||||
gtk_css_image_radial_token_parse_argument,
|
||||
image);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_radial_print (GtkCssImage *image,
|
||||
GString *string)
|
||||
@@ -662,6 +866,7 @@ _gtk_css_image_radial_class_init (GtkCssImageRadialClass *klass)
|
||||
|
||||
image_class->draw = gtk_css_image_radial_draw;
|
||||
image_class->parse = gtk_css_image_radial_parse;
|
||||
image_class->token_parse = gtk_css_image_radial_token_parse;
|
||||
image_class->print = gtk_css_image_radial_print;
|
||||
image_class->compute = gtk_css_image_radial_compute;
|
||||
image_class->transition = gtk_css_image_radial_transition;
|
||||
|
@@ -227,6 +227,55 @@ gtk_css_image_recolor_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_image_recolor_token_parse_argument (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssImageRecolor *recolor = GTK_CSS_IMAGE_RECOLOR (data);
|
||||
GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (data);
|
||||
|
||||
if (arg == 0)
|
||||
{
|
||||
url->file = gtk_css_token_source_consume_url (source);
|
||||
if (url->file == NULL)
|
||||
return 0;
|
||||
}
|
||||
else if (arg == 1)
|
||||
{
|
||||
recolor->palette = gtk_css_palette_value_token_parse (source);
|
||||
if (recolor->palette == NULL)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_recolor_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is_function (token, "-gtk-recolor"))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected '-gtk-recolor('");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return gtk_css_token_source_consume_function (source,
|
||||
1, 2,
|
||||
gtk_css_image_recolor_token_parse_argument,
|
||||
image);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_css_image_recolor_class_init (GtkCssImageRecolorClass *klass)
|
||||
{
|
||||
@@ -234,6 +283,7 @@ _gtk_css_image_recolor_class_init (GtkCssImageRecolorClass *klass)
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
image_class->parse = gtk_css_image_recolor_parse;
|
||||
image_class->token_parse = gtk_css_image_recolor_token_parse;
|
||||
image_class->compute = gtk_css_image_recolor_compute;
|
||||
image_class->print = gtk_css_image_recolor_print;
|
||||
|
||||
|
@@ -180,6 +180,53 @@ gtk_css_image_scaled_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
token_parse_arg (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GPtrArray *images = data;
|
||||
GtkCssImage *image;
|
||||
|
||||
image = gtk_css_image_new_token_parse (source);
|
||||
if (image == NULL)
|
||||
return 0;
|
||||
|
||||
g_ptr_array_add (images, image);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_scaled_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (image);
|
||||
const GtkCssToken *token;
|
||||
GPtrArray *images;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is_function (token, "-gtk-scaled"))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected '-gtk-scaled('");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
images = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
|
||||
if (!gtk_css_token_source_consume_function (source, 1, G_MAXUINT, token_parse_arg, images))
|
||||
{
|
||||
g_ptr_array_free (images, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
scaled->n_images = images->len;
|
||||
scaled->images = (GtkCssImage **) g_ptr_array_free (images, FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_css_image_scaled_class_init (GtkCssImageScaledClass *klass)
|
||||
{
|
||||
@@ -191,6 +238,7 @@ _gtk_css_image_scaled_class_init (GtkCssImageScaledClass *klass)
|
||||
image_class->get_aspect_ratio = gtk_css_image_scaled_get_aspect_ratio;
|
||||
image_class->draw = gtk_css_image_scaled_draw;
|
||||
image_class->parse = gtk_css_image_scaled_parse;
|
||||
image_class->token_parse = gtk_css_image_scaled_token_parse;
|
||||
image_class->compute = gtk_css_image_scaled_compute;
|
||||
image_class->print = gtk_css_image_scaled_print;
|
||||
|
||||
|
@@ -163,6 +163,19 @@ gtk_css_image_url_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_url_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image);
|
||||
|
||||
url->file = gtk_css_token_source_consume_url (source);
|
||||
if (url->file == NULL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_url_print (GtkCssImage *image,
|
||||
GString *string)
|
||||
@@ -195,6 +208,7 @@ _gtk_css_image_url_class_init (GtkCssImageUrlClass *klass)
|
||||
image_class->compute = gtk_css_image_url_compute;
|
||||
image_class->draw = gtk_css_image_url_draw;
|
||||
image_class->parse = gtk_css_image_url_parse;
|
||||
image_class->token_parse = gtk_css_image_url_token_parse;
|
||||
image_class->print = gtk_css_image_url_print;
|
||||
|
||||
object_class->dispose = gtk_css_image_url_dispose;
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include "gtkcssimagewin32private.h"
|
||||
|
||||
#include "gtkcssprovider.h"
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
|
||||
G_DEFINE_TYPE (GtkCssImageWin32, _gtk_css_image_win32, GTK_TYPE_CSS_IMAGE)
|
||||
|
||||
@@ -212,6 +213,134 @@ gtk_css_image_win32_parse (GtkCssImage *image,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_image_win32_token_parse_over_argument (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssImageWin32 *wimage = GTK_CSS_IMAGE_WIN32 (data);
|
||||
|
||||
if (arg == 0)
|
||||
{
|
||||
if (!gtk_css_token_source_consume_integer (source, &wimage->part2))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
else if (arg == 1)
|
||||
{
|
||||
if (!gtk_css_token_source_consume_integer (source, &wimage->state2))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
else if (arg == 2)
|
||||
{
|
||||
if (!gtk_css_token_source_consume_number (source, &wimage->over_alpha))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_image_win32_token_parse_margins_argument (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssImageWin32 *wimage = GTK_CSS_IMAGE_WIN32 (data);
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (i > 0 && !gtk_css_number_value_check_token (gtk_css_token_source_get_token (source)))
|
||||
break;
|
||||
|
||||
if (!gtk_css_token_source_consume_integer (source, &wimage->margins[i]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (; i < 4; i++)
|
||||
wimage->margins[i] = wimage->margins[i - 1];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_image_win32_token_parse_argument (GtkCssTokenSource *source,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssImageWin32 *wimage = GTK_CSS_IMAGE_WIN32 (data);
|
||||
|
||||
if (arg == 0)
|
||||
{
|
||||
wimage->theme = gtk_win32_theme_token_parse (source);
|
||||
if (wimage->theme == NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
else if (arg == 1)
|
||||
{
|
||||
if (!gtk_css_token_source_consume_integer (source, &wimage->part))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
else if (arg == 2)
|
||||
{
|
||||
if (!gtk_css_token_source_consume_integer (source, &wimage->state))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_function (token, "over"))
|
||||
{
|
||||
return gtk_css_token_source_consume_function (source,
|
||||
2, 3,
|
||||
gtk_css_image_win32_token_parse_over_argument,
|
||||
wimage) ? 1 : 0;
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "margins"))
|
||||
{
|
||||
return gtk_css_token_source_consume_function (source,
|
||||
1, 1,
|
||||
gtk_css_image_win32_token_parse_margins_argument,
|
||||
wimage) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected over() or margins()");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_win32_token_parse (GtkCssImage *image,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is_function (token, "-gtk-win32-theme-part"))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected '-gtk-win32-theme-part('");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return gtk_css_token_source_consume_function (source,
|
||||
3, G_MAXUINT,
|
||||
gtk_css_image_win32_token_parse_argument,
|
||||
image);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_win32_print (GtkCssImage *image,
|
||||
GString *string)
|
||||
@@ -244,6 +373,7 @@ _gtk_css_image_win32_class_init (GtkCssImageWin32Class *klass)
|
||||
|
||||
image_class->draw = gtk_css_image_win32_draw;
|
||||
image_class->parse = gtk_css_image_win32_parse;
|
||||
image_class->token_parse = gtk_css_image_win32_token_parse;
|
||||
image_class->print = gtk_css_image_win32_print;
|
||||
}
|
||||
|
||||
|
192
gtk/gtkcssimportrule.c
Normal file
192
gtk/gtkcssimportrule.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssimportruleprivate.h"
|
||||
|
||||
#include "gtkcssstylesheetprivate.h"
|
||||
|
||||
typedef struct _GtkCssImportRulePrivate GtkCssImportRulePrivate;
|
||||
struct _GtkCssImportRulePrivate {
|
||||
GFile *file;
|
||||
GtkCssStyleSheet *style_sheet;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssImportRule, gtk_css_import_rule, GTK_TYPE_CSS_RULE)
|
||||
|
||||
static void
|
||||
gtk_css_import_rule_finalize (GObject *object)
|
||||
{
|
||||
GtkCssImportRule *import_rule = GTK_CSS_IMPORT_RULE (object);
|
||||
GtkCssImportRulePrivate *priv = gtk_css_import_rule_get_instance_private (import_rule);
|
||||
|
||||
if (priv->file)
|
||||
g_object_unref (priv->file);
|
||||
if (priv->style_sheet)
|
||||
g_object_unref (priv->style_sheet);
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_import_rule_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_import_rule_class_init (GtkCssImportRuleClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_import_rule_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_import_rule_init (GtkCssImportRule *import_rule)
|
||||
{
|
||||
}
|
||||
|
||||
static GtkCssRule *
|
||||
gtk_css_import_rule_new (GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_CSS_IMPORT_RULE,
|
||||
"parent-rule", parent_rule,
|
||||
"parent-stylesheet", parent_style_sheet,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_import_rule_would_recurse (GtkCssImportRule *rule)
|
||||
{
|
||||
GtkCssImportRulePrivate *priv = gtk_css_import_rule_get_instance_private (GTK_CSS_IMPORT_RULE (rule));
|
||||
GtkCssStyleSheet *sheet;
|
||||
|
||||
for (sheet = gtk_css_rule_get_parent_style_sheet (GTK_CSS_RULE (rule));
|
||||
sheet != NULL;
|
||||
sheet = gtk_css_style_sheet_get_parent_style_sheet (sheet))
|
||||
{
|
||||
GFile *sheet_file = gtk_css_style_sheet_get_file (sheet);
|
||||
|
||||
if (sheet_file && g_file_equal (sheet_file, priv->file))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GtkCssRule *
|
||||
gtk_css_import_rule_new_parse (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
GtkCssImportRulePrivate *priv;
|
||||
const GtkCssToken *token;
|
||||
GtkCssRule *result;
|
||||
GtkCssTokenizer *tokenizer;
|
||||
GtkCssTokenSource *import_source;
|
||||
GError *load_error = NULL;
|
||||
GBytes *bytes;
|
||||
char *data;
|
||||
gsize size;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
g_return_val_if_fail (parent_rule == NULL || GTK_IS_CSS_RULE (parent_rule), NULL);
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (parent_style_sheet), NULL);
|
||||
|
||||
result = gtk_css_import_rule_new (parent_rule, parent_style_sheet);
|
||||
gtk_css_token_source_set_consumer (source, G_OBJECT (result));
|
||||
priv = gtk_css_import_rule_get_instance_private (GTK_CSS_IMPORT_RULE (result));
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (token->type != GTK_CSS_TOKEN_AT_KEYWORD ||
|
||||
g_ascii_strcasecmp (token->string.string, "import") != 0)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected '@import'");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_STRING))
|
||||
{
|
||||
priv->file = gtk_css_token_source_resolve_url (source, token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->file = gtk_css_token_source_consume_url (source);
|
||||
if (priv->file == NULL)
|
||||
{
|
||||
g_object_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_SEMICOLON))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected ';' at end of @import");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (gtk_css_import_rule_would_recurse (GTK_CSS_IMPORT_RULE (result)))
|
||||
{
|
||||
char *path = g_file_get_path (priv->file);
|
||||
gtk_css_token_source_error (source,
|
||||
"Loading '%s' would recurse",
|
||||
path);
|
||||
g_object_unref (result);
|
||||
g_free (path);
|
||||
bytes = g_bytes_new (NULL, 0);
|
||||
}
|
||||
else if (g_file_load_contents (priv->file, NULL,
|
||||
&data, &size,
|
||||
NULL, &load_error))
|
||||
{
|
||||
bytes = g_bytes_new_take (data, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_emit_error (source, load_error);
|
||||
bytes = g_bytes_new (NULL, 0);
|
||||
g_error_free (load_error);
|
||||
}
|
||||
tokenizer = gtk_css_tokenizer_new (bytes, NULL, NULL, NULL);
|
||||
import_source = gtk_css_token_source_new_for_tokenizer (tokenizer, priv->file);
|
||||
priv->style_sheet = gtk_css_style_sheet_new_import (import_source, result);
|
||||
gtk_css_token_source_unref (import_source);
|
||||
gtk_css_tokenizer_unref (tokenizer);
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssStyleSheet *
|
||||
gtk_css_import_rule_get_style_sheet (GtkCssImportRule *rule)
|
||||
{
|
||||
GtkCssImportRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_IMPORT_RULE (rule), NULL);
|
||||
|
||||
priv = gtk_css_import_rule_get_instance_private (rule);
|
||||
|
||||
return priv->style_sheet;
|
||||
}
|
||||
|
57
gtk/gtkcssimportruleprivate.h
Normal file
57
gtk/gtkcssimportruleprivate.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_IMPORT_RULE_PRIVATE_H__
|
||||
#define __GTK_CSS_IMPORT_RULE_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssruleprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_IMPORT_RULE (gtk_css_import_rule_get_type ())
|
||||
#define GTK_CSS_IMPORT_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_IMPORT_RULE, GtkCssImportRule))
|
||||
#define GTK_CSS_IMPORT_RULE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_IMPORT_RULE, GtkCssImportRuleClass))
|
||||
#define GTK_IS_CSS_IMPORT_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_IMPORT_RULE))
|
||||
#define GTK_IS_CSS_IMPORT_RULE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_IMPORT_RULE))
|
||||
#define GTK_CSS_IMPORT_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_IMPORT_RULE, GtkCssImportRuleClass))
|
||||
|
||||
typedef struct _GtkCssImportRule GtkCssImportRule;
|
||||
typedef struct _GtkCssImportRuleClass GtkCssImportRuleClass;
|
||||
|
||||
struct _GtkCssImportRule
|
||||
{
|
||||
GtkCssRule parent;
|
||||
};
|
||||
|
||||
struct _GtkCssImportRuleClass
|
||||
{
|
||||
GtkCssRuleClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_import_rule_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssRule * gtk_css_import_rule_new_parse (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet);
|
||||
|
||||
GtkCssStyleSheet * gtk_css_import_rule_get_style_sheet (GtkCssImportRule *rule);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_IMPORT_RULE_PRIVATE_H__ */
|
176
gtk/gtkcsskeyframerule.c
Normal file
176
gtk/gtkcsskeyframerule.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcsskeyframeruleprivate.h"
|
||||
|
||||
#include "gtkcssstylesheetprivate.h"
|
||||
|
||||
typedef struct _GtkCssKeyframeRulePrivate GtkCssKeyframeRulePrivate;
|
||||
struct _GtkCssKeyframeRulePrivate {
|
||||
double *offsets;
|
||||
gsize n_offsets;
|
||||
GtkCssStyleDeclaration *style;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssKeyframeRule, gtk_css_keyframe_rule, GTK_TYPE_CSS_RULE)
|
||||
|
||||
static void
|
||||
gtk_css_keyframe_rule_finalize (GObject *object)
|
||||
{
|
||||
GtkCssKeyframeRule *keyframe_rule = GTK_CSS_KEYFRAME_RULE (object);
|
||||
GtkCssKeyframeRulePrivate *priv = gtk_css_keyframe_rule_get_instance_private (keyframe_rule);
|
||||
|
||||
g_free (priv->offsets);
|
||||
g_object_unref (priv->style);
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_keyframe_rule_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_keyframe_rule_class_init (GtkCssKeyframeRuleClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_keyframe_rule_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_keyframe_rule_init (GtkCssKeyframeRule *keyframe_rule)
|
||||
{
|
||||
GtkCssKeyframeRulePrivate *priv = gtk_css_keyframe_rule_get_instance_private (keyframe_rule);
|
||||
|
||||
priv->style = gtk_css_style_declaration_new (GTK_CSS_RULE (keyframe_rule));
|
||||
}
|
||||
|
||||
static GtkCssRule *
|
||||
gtk_css_keyframe_rule_new (GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_CSS_KEYFRAME_RULE,
|
||||
"parent-rule", parent_rule,
|
||||
"parent-stylesheet", parent_style_sheet,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GtkCssRule *
|
||||
gtk_css_keyframe_rule_new_parse (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
GtkCssKeyframeRulePrivate *priv;
|
||||
GtkCssTokenSource *style_source;
|
||||
const GtkCssToken *token;
|
||||
GtkCssRule *rule;
|
||||
GArray *offsets;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
g_return_val_if_fail (parent_rule == NULL || GTK_IS_CSS_RULE (parent_rule), NULL);
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (parent_style_sheet), NULL);
|
||||
|
||||
rule = gtk_css_keyframe_rule_new (parent_rule, parent_style_sheet);
|
||||
priv = gtk_css_keyframe_rule_get_instance_private (GTK_CSS_KEYFRAME_RULE (rule));
|
||||
gtk_css_token_source_set_consumer (source, G_OBJECT (rule));
|
||||
|
||||
offsets = g_array_new (FALSE, FALSE, sizeof (double));
|
||||
while (TRUE)
|
||||
{
|
||||
double offset;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "from"))
|
||||
offset = 0;
|
||||
else if (gtk_css_token_is_ident (token, "to"))
|
||||
offset = 100;
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_PERCENTAGE))
|
||||
offset = token->number.number;
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected percentage");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_array_free (offsets, TRUE);
|
||||
g_object_unref (rule);
|
||||
return NULL;
|
||||
}
|
||||
g_array_append_val (offsets, offset);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COMMA))
|
||||
break;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
priv->n_offsets = offsets->len;
|
||||
priv->offsets = (double *) g_array_free (offsets, FALSE);
|
||||
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_OPEN_CURLY))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected percentage");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (rule);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
style_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_CLOSE_CURLY);
|
||||
gtk_css_style_declaration_parse (priv->style, style_source);
|
||||
gtk_css_token_source_unref (style_source);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
return rule;
|
||||
}
|
||||
|
||||
gsize
|
||||
gtk_css_keyframe_rule_get_n_offsets (GtkCssKeyframeRule *rule)
|
||||
{
|
||||
GtkCssKeyframeRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_KEYFRAME_RULE (rule), 0);
|
||||
|
||||
priv = gtk_css_keyframe_rule_get_instance_private (rule);
|
||||
|
||||
return priv->n_offsets;
|
||||
}
|
||||
|
||||
double
|
||||
gtk_css_keyframe_rule_get_offset (GtkCssKeyframeRule *rule,
|
||||
gsize id)
|
||||
{
|
||||
GtkCssKeyframeRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_KEYFRAME_RULE (rule), 0.0);
|
||||
|
||||
priv = gtk_css_keyframe_rule_get_instance_private (rule);
|
||||
g_return_val_if_fail (id < priv->n_offsets, 0.0);
|
||||
|
||||
return priv->offsets[id];
|
||||
}
|
||||
|
||||
GtkCssStyleDeclaration *
|
||||
gtk_css_keyframe_rule_get_style (GtkCssKeyframeRule *rule)
|
||||
{
|
||||
GtkCssKeyframeRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_KEYFRAME_RULE (rule), 0);
|
||||
|
||||
priv = gtk_css_keyframe_rule_get_instance_private (rule);
|
||||
|
||||
return priv->style;
|
||||
}
|
63
gtk/gtkcsskeyframeruleprivate.h
Normal file
63
gtk/gtkcsskeyframeruleprivate.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_KEYFRAME_RULE_PRIVATE_H__
|
||||
#define __GTK_CSS_KEYFRAME_RULE_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssruleprivate.h"
|
||||
#include "gtk/gtkcssstyledeclarationprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_KEYFRAME_RULE (gtk_css_keyframe_rule_get_type ())
|
||||
#define GTK_CSS_KEYFRAME_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_KEYFRAME_RULE, GtkCssKeyframeRule))
|
||||
#define GTK_CSS_KEYFRAME_RULE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_KEYFRAME_RULE, GtkCssKeyframeRuleClass))
|
||||
#define GTK_IS_CSS_KEYFRAME_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_KEYFRAME_RULE))
|
||||
#define GTK_IS_CSS_KEYFRAME_RULE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_KEYFRAME_RULE))
|
||||
#define GTK_CSS_KEYFRAME_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_KEYFRAME_RULE, GtkCssKeyframeRuleClass))
|
||||
|
||||
typedef struct _GtkCssKeyframeRule GtkCssKeyframeRule;
|
||||
typedef struct _GtkCssKeyframeRuleClass GtkCssKeyframeRuleClass;
|
||||
|
||||
struct _GtkCssKeyframeRule
|
||||
{
|
||||
GtkCssRule parent;
|
||||
};
|
||||
|
||||
struct _GtkCssKeyframeRuleClass
|
||||
{
|
||||
GtkCssRuleClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_keyframe_rule_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssRule * gtk_css_keyframe_rule_new_parse (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet);
|
||||
|
||||
gsize gtk_css_keyframe_rule_get_n_offsets (GtkCssKeyframeRule *rule);
|
||||
double gtk_css_keyframe_rule_get_offset (GtkCssKeyframeRule *rule,
|
||||
gsize id);
|
||||
|
||||
GtkCssStyleDeclaration *gtk_css_keyframe_rule_get_style (GtkCssKeyframeRule *rule);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_KEYFRAME_RULE_PRIVATE_H__ */
|
@@ -20,8 +20,10 @@
|
||||
#include "gtkcsskeyframesprivate.h"
|
||||
|
||||
#include "gtkcssarrayvalueprivate.h"
|
||||
#include "gtkcsskeyframeruleprivate.h"
|
||||
#include "gtkcsslonghanddeclarationprivate.h"
|
||||
#include "gtkcssshorthanddeclarationprivate.h"
|
||||
#include "gtkcssshorthandpropertyprivate.h"
|
||||
#include "gtkcssstylepropertyprivate.h"
|
||||
#include "gtkstylepropertyprivate.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -370,6 +372,67 @@ _gtk_css_keyframes_parse (GtkCssParser *parser)
|
||||
return keyframes;
|
||||
}
|
||||
|
||||
GtkCssKeyframes *
|
||||
gtk_css_keyframes_new_from_rule (GtkCssKeyframesRule *rule)
|
||||
{
|
||||
GtkCssKeyframes *keyframes;
|
||||
GtkCssRuleList *rules;
|
||||
guint i, j, k, l;
|
||||
|
||||
keyframes = gtk_css_keyframes_new ();
|
||||
|
||||
rules = gtk_css_keyframes_rule_get_css_rules (rule);
|
||||
for (i = 0; i < gtk_css_rule_list_get_length (rules); i++)
|
||||
{
|
||||
/* Don't do GTK_CSS_KEYFRAME_RULE() cast here. */
|
||||
GtkCssKeyframeRule *keyframe = (GtkCssKeyframeRule *) gtk_css_rule_list_get_item (rules, i);
|
||||
|
||||
if (!GTK_IS_CSS_KEYFRAME_RULE (keyframe))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < gtk_css_keyframe_rule_get_n_offsets (keyframe); j++)
|
||||
{
|
||||
double offset = gtk_css_keyframe_rule_get_offset (keyframe, j) / 100;
|
||||
GtkCssStyleDeclaration *style;
|
||||
guint offset_idx;
|
||||
|
||||
if (offset < 0 || offset > 1)
|
||||
continue;
|
||||
|
||||
offset_idx = gtk_css_keyframes_add_keyframe (keyframes, offset);
|
||||
style = gtk_css_keyframe_rule_get_style (keyframe);
|
||||
|
||||
for (k = 0; k < gtk_css_style_declaration_get_length (style); k++)
|
||||
{
|
||||
GtkCssDeclaration *decl = gtk_css_style_declaration_get_declaration (style, k);
|
||||
|
||||
if (GTK_IS_CSS_LONGHAND_DECLARATION (decl))
|
||||
{
|
||||
GtkCssLonghandDeclaration *longhand = GTK_CSS_LONGHAND_DECLARATION (decl);
|
||||
keyframes_set_value (keyframes,
|
||||
offset_idx,
|
||||
gtk_css_longhand_declaration_get_property (longhand),
|
||||
_gtk_css_value_ref (gtk_css_longhand_declaration_get_value (longhand)));
|
||||
}
|
||||
else if (GTK_IS_CSS_SHORTHAND_DECLARATION (decl))
|
||||
{
|
||||
GtkCssShorthandDeclaration *shorthand = GTK_CSS_SHORTHAND_DECLARATION (decl);
|
||||
|
||||
for (l = 0; l < gtk_css_shorthand_declaration_get_length (shorthand); l++)
|
||||
{
|
||||
keyframes_set_value (keyframes,
|
||||
offset_idx,
|
||||
gtk_css_shorthand_declaration_get_subproperty (shorthand, l),
|
||||
_gtk_css_value_ref (gtk_css_shorthand_declaration_get_value (shorthand, l)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return keyframes;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_property_by_name (gconstpointer a,
|
||||
gconstpointer b,
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_CSS_KEYFRAMES_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsskeyframesruleprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
#include "gtktypes.h"
|
||||
|
||||
@@ -29,6 +30,7 @@ G_BEGIN_DECLS
|
||||
typedef struct _GtkCssKeyframes GtkCssKeyframes;
|
||||
|
||||
GtkCssKeyframes * _gtk_css_keyframes_parse (GtkCssParser *parser);
|
||||
GtkCssKeyframes * gtk_css_keyframes_new_from_rule (GtkCssKeyframesRule *rule);
|
||||
|
||||
GtkCssKeyframes * _gtk_css_keyframes_ref (GtkCssKeyframes *keyframes);
|
||||
void _gtk_css_keyframes_unref (GtkCssKeyframes *keyframes);
|
||||
|
287
gtk/gtkcsskeyframesrule.c
Normal file
287
gtk/gtkcsskeyframesrule.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcsskeyframesruleprivate.h"
|
||||
|
||||
#include "gtkcsskeyframeruleprivate.h"
|
||||
#include "gtkcssstylesheetprivate.h"
|
||||
|
||||
typedef struct _GtkCssKeyframesRulePrivate GtkCssKeyframesRulePrivate;
|
||||
struct _GtkCssKeyframesRulePrivate {
|
||||
char *name;
|
||||
GtkCssRuleList *rules;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssKeyframesRule, gtk_css_keyframes_rule, GTK_TYPE_CSS_RULE)
|
||||
|
||||
typedef struct _GtkCssTokenSourceKeyframe GtkCssTokenSourceKeyframe;
|
||||
struct _GtkCssTokenSourceKeyframe {
|
||||
GtkCssTokenSource parent;
|
||||
GtkCssTokenSource *source;
|
||||
GSList *blocks;
|
||||
gboolean done;
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_css_token_source_keyframe_finalize (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourceKeyframe *keyframe = (GtkCssTokenSourceKeyframe *) source;
|
||||
|
||||
g_slist_free (keyframe->blocks);
|
||||
|
||||
gtk_css_token_source_unref (keyframe->source);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_token_source_keyframe_consume_token (GtkCssTokenSource *source,
|
||||
GObject *consumer)
|
||||
{
|
||||
GtkCssTokenSourceKeyframe *keyframe = (GtkCssTokenSourceKeyframe *) source;
|
||||
const GtkCssToken *token;
|
||||
|
||||
if (keyframe->done)
|
||||
return;
|
||||
|
||||
token = gtk_css_token_source_peek_token (keyframe->source);
|
||||
switch (token->type)
|
||||
{
|
||||
case GTK_CSS_TOKEN_FUNCTION:
|
||||
case GTK_CSS_TOKEN_OPEN_PARENS:
|
||||
keyframe->blocks = g_slist_prepend (keyframe->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_PARENS));
|
||||
break;
|
||||
case GTK_CSS_TOKEN_OPEN_SQUARE:
|
||||
keyframe->blocks = g_slist_prepend (keyframe->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_SQUARE));
|
||||
break;
|
||||
case GTK_CSS_TOKEN_OPEN_CURLY:
|
||||
keyframe->blocks = g_slist_prepend (keyframe->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_CURLY));
|
||||
break;
|
||||
case GTK_CSS_TOKEN_CLOSE_PARENS:
|
||||
case GTK_CSS_TOKEN_CLOSE_SQUARE:
|
||||
case GTK_CSS_TOKEN_CLOSE_CURLY:
|
||||
if (keyframe->blocks && GPOINTER_TO_UINT (keyframe->blocks->data) == token->type)
|
||||
keyframe->blocks = g_slist_remove (keyframe->blocks, keyframe->blocks->data);
|
||||
if (token->type == GTK_CSS_TOKEN_CLOSE_CURLY && keyframe->blocks == NULL)
|
||||
keyframe->done = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token_as (keyframe->source, consumer);
|
||||
}
|
||||
|
||||
const GtkCssToken *
|
||||
gtk_css_token_source_keyframe_peek_token (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourceKeyframe *keyframe = (GtkCssTokenSourceKeyframe *) source;
|
||||
static GtkCssToken eof_token = { GTK_CSS_TOKEN_EOF };
|
||||
|
||||
if (keyframe->done)
|
||||
return &eof_token;
|
||||
|
||||
return gtk_css_token_source_peek_token (keyframe->source);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_token_source_keyframe_error (GtkCssTokenSource *source,
|
||||
const GError *error)
|
||||
{
|
||||
GtkCssTokenSourceKeyframe *keyframe = (GtkCssTokenSourceKeyframe *) source;
|
||||
|
||||
gtk_css_token_source_emit_error (keyframe->source, error);
|
||||
}
|
||||
|
||||
static GFile *
|
||||
gtk_css_token_source_keyframe_get_location (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourceKeyframe *keyframe = (GtkCssTokenSourceKeyframe *) source;
|
||||
|
||||
return gtk_css_token_source_get_location (keyframe->source);
|
||||
}
|
||||
|
||||
static const GtkCssTokenSourceClass GTK_CSS_TOKEN_SOURCE_KEYFRAME = {
|
||||
gtk_css_token_source_keyframe_finalize,
|
||||
gtk_css_token_source_keyframe_consume_token,
|
||||
gtk_css_token_source_keyframe_peek_token,
|
||||
gtk_css_token_source_keyframe_error,
|
||||
gtk_css_token_source_keyframe_get_location,
|
||||
};
|
||||
|
||||
static GtkCssTokenSource *
|
||||
gtk_css_token_source_new_keyframe (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourceKeyframe *keyframe = gtk_css_token_source_new (GtkCssTokenSourceKeyframe, >K_CSS_TOKEN_SOURCE_KEYFRAME);
|
||||
|
||||
keyframe->source = gtk_css_token_source_ref (source);
|
||||
gtk_css_token_source_set_consumer (&keyframe->parent,
|
||||
gtk_css_token_source_get_consumer (source));
|
||||
|
||||
return &keyframe->parent;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_keyframes_rule_finalize (GObject *object)
|
||||
{
|
||||
GtkCssKeyframesRule *keyframes_rule = GTK_CSS_KEYFRAMES_RULE (object);
|
||||
GtkCssKeyframesRulePrivate *priv = gtk_css_keyframes_rule_get_instance_private (keyframes_rule);
|
||||
|
||||
g_free (priv->name);
|
||||
g_object_unref (priv->rules);
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_keyframes_rule_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_keyframes_rule_class_init (GtkCssKeyframesRuleClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_keyframes_rule_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_keyframes_rule_init (GtkCssKeyframesRule *keyframes_rule)
|
||||
{
|
||||
GtkCssKeyframesRulePrivate *priv = gtk_css_keyframes_rule_get_instance_private (keyframes_rule);
|
||||
|
||||
priv->rules = gtk_css_rule_list_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_keyframes_rule_set_name (GtkCssKeyframesRule *keyframes,
|
||||
const char *name)
|
||||
{
|
||||
GtkCssKeyframesRulePrivate *priv;
|
||||
|
||||
priv = gtk_css_keyframes_rule_get_instance_private (keyframes);
|
||||
|
||||
g_free (priv->name);
|
||||
priv->name = g_strdup (name);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_keyframes_rule_append (GtkCssKeyframesRule *keyframes,
|
||||
GtkCssRule *rule)
|
||||
{
|
||||
GtkCssKeyframesRulePrivate *priv;
|
||||
|
||||
priv = gtk_css_keyframes_rule_get_instance_private (keyframes);
|
||||
|
||||
gtk_css_rule_list_append (priv->rules, rule);
|
||||
}
|
||||
|
||||
static GtkCssRule *
|
||||
gtk_css_keyframes_rule_new (GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_CSS_KEYFRAMES_RULE,
|
||||
"parent-rule", parent_rule,
|
||||
"parent-stylesheet", parent_style_sheet,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GtkCssRule *
|
||||
gtk_css_keyframes_rule_new_parse (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GtkCssRule *rule;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
g_return_val_if_fail (parent_rule == NULL || GTK_IS_CSS_RULE (parent_rule), NULL);
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (parent_style_sheet), NULL);
|
||||
|
||||
rule = gtk_css_keyframes_rule_new (parent_rule, parent_style_sheet);
|
||||
gtk_css_token_source_set_consumer (source, G_OBJECT (rule));
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (token->type != GTK_CSS_TOKEN_AT_KEYWORD ||
|
||||
g_ascii_strcasecmp (token->string.string, "keyframes") != 0)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected '@keyframes'");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (rule);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected name of keyframes");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_keyframes_rule_set_name (GTK_CSS_KEYFRAMES_RULE (rule), token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_OPEN_CURLY))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected '{'");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
for (token = gtk_css_token_source_get_token (source);
|
||||
!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF) && !gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_CURLY);
|
||||
token = gtk_css_token_source_get_token (source))
|
||||
{
|
||||
GtkCssTokenSource *keyframe_source = gtk_css_token_source_new_keyframe (source);
|
||||
GtkCssRule *keyframe;
|
||||
|
||||
keyframe = gtk_css_keyframe_rule_new_parse (keyframe_source, rule, parent_style_sheet);
|
||||
if (keyframe)
|
||||
gtk_css_keyframes_rule_append (GTK_CSS_KEYFRAMES_RULE (rule), keyframe);
|
||||
|
||||
gtk_css_token_source_unref (keyframe_source);
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
return rule;
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_css_keyframes_rule_get_name (GtkCssKeyframesRule *rule)
|
||||
{
|
||||
GtkCssKeyframesRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_KEYFRAMES_RULE (rule), NULL);
|
||||
|
||||
priv = gtk_css_keyframes_rule_get_instance_private (rule);
|
||||
|
||||
return priv->name;
|
||||
}
|
||||
|
||||
GtkCssRuleList *
|
||||
gtk_css_keyframes_rule_get_css_rules (GtkCssKeyframesRule *rule)
|
||||
{
|
||||
GtkCssKeyframesRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_KEYFRAMES_RULE (rule), NULL);
|
||||
|
||||
priv = gtk_css_keyframes_rule_get_instance_private (rule);
|
||||
|
||||
return priv->rules;
|
||||
}
|
59
gtk/gtkcsskeyframesruleprivate.h
Normal file
59
gtk/gtkcsskeyframesruleprivate.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_KEYFRAMES_RULE_PRIVATE_H__
|
||||
#define __GTK_CSS_KEYFRAMES_RULE_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssruleprivate.h"
|
||||
#include "gtk/gtkcssrulelistprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_KEYFRAMES_RULE (gtk_css_keyframes_rule_get_type ())
|
||||
#define GTK_CSS_KEYFRAMES_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_KEYFRAMES_RULE, GtkCssKeyframesRule))
|
||||
#define GTK_CSS_KEYFRAMES_RULE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_KEYFRAMES_RULE, GtkCssKeyframesRuleClass))
|
||||
#define GTK_IS_CSS_KEYFRAMES_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_KEYFRAMES_RULE))
|
||||
#define GTK_IS_CSS_KEYFRAMES_RULE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_KEYFRAMES_RULE))
|
||||
#define GTK_CSS_KEYFRAMES_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_KEYFRAMES_RULE, GtkCssKeyframesRuleClass))
|
||||
|
||||
typedef struct _GtkCssKeyframesRule GtkCssKeyframesRule;
|
||||
typedef struct _GtkCssKeyframesRuleClass GtkCssKeyframesRuleClass;
|
||||
|
||||
struct _GtkCssKeyframesRule
|
||||
{
|
||||
GtkCssRule parent;
|
||||
};
|
||||
|
||||
struct _GtkCssKeyframesRuleClass
|
||||
{
|
||||
GtkCssRuleClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_keyframes_rule_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssRule * gtk_css_keyframes_rule_new_parse (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet);
|
||||
|
||||
const char * gtk_css_keyframes_rule_get_name (GtkCssKeyframesRule *rule);
|
||||
GtkCssRuleList * gtk_css_keyframes_rule_get_css_rules (GtkCssKeyframesRule *rule);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_KEYFRAMES_RULE_PRIVATE_H__ */
|
178
gtk/gtkcsslonghanddeclaration.c
Normal file
178
gtk/gtkcsslonghanddeclaration.c
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcsslonghanddeclarationprivate.h"
|
||||
|
||||
#include "gtkcssstylepropertyprivate.h"
|
||||
|
||||
typedef struct _GtkCssLonghandDeclarationPrivate GtkCssLonghandDeclarationPrivate;
|
||||
struct _GtkCssLonghandDeclarationPrivate {
|
||||
GtkCssStyleProperty *prop;
|
||||
GtkCssValue *value;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssLonghandDeclaration, gtk_css_longhand_declaration, GTK_TYPE_CSS_DECLARATION)
|
||||
|
||||
static void
|
||||
gtk_css_longhand_declaration_finalize (GObject *object)
|
||||
{
|
||||
GtkCssLonghandDeclaration *longhand_declaration = GTK_CSS_LONGHAND_DECLARATION (object);
|
||||
GtkCssLonghandDeclarationPrivate *priv = gtk_css_longhand_declaration_get_instance_private (longhand_declaration);
|
||||
|
||||
if (priv->value)
|
||||
_gtk_css_value_unref (priv->value);
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_longhand_declaration_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static const char *
|
||||
gtk_css_longhand_declaration_get_name (GtkCssDeclaration *decl)
|
||||
{
|
||||
GtkCssLonghandDeclaration *longhand_declaration = GTK_CSS_LONGHAND_DECLARATION (decl);
|
||||
GtkCssLonghandDeclarationPrivate *priv = gtk_css_longhand_declaration_get_instance_private (longhand_declaration);
|
||||
|
||||
return _gtk_style_property_get_name (GTK_STYLE_PROPERTY (priv->prop));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_longhand_declaration_print_value (GtkCssDeclaration *decl,
|
||||
GString *string)
|
||||
{
|
||||
GtkCssLonghandDeclaration *longhand_declaration = GTK_CSS_LONGHAND_DECLARATION (decl);
|
||||
GtkCssLonghandDeclarationPrivate *priv = gtk_css_longhand_declaration_get_instance_private (longhand_declaration);
|
||||
|
||||
_gtk_css_value_print (priv->value, string);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_longhand_declaration_class_init (GtkCssLonghandDeclarationClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkCssDeclarationClass *decl_class = GTK_CSS_DECLARATION_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_longhand_declaration_finalize;
|
||||
|
||||
decl_class->get_name = gtk_css_longhand_declaration_get_name;
|
||||
decl_class->print_value = gtk_css_longhand_declaration_print_value;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_longhand_declaration_init (GtkCssLonghandDeclaration *longhand_declaration)
|
||||
{
|
||||
}
|
||||
|
||||
GtkCssDeclaration *
|
||||
gtk_css_longhand_declaration_new_parse (GtkCssStyleDeclaration *style,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssLonghandDeclarationPrivate *priv;
|
||||
const GtkCssToken *token;
|
||||
GtkCssLonghandDeclaration *decl;
|
||||
char *name;
|
||||
|
||||
decl = g_object_new (GTK_TYPE_CSS_LONGHAND_DECLARATION,
|
||||
"parent-style", style,
|
||||
NULL);
|
||||
priv = gtk_css_longhand_declaration_get_instance_private (decl);
|
||||
|
||||
gtk_css_token_source_set_consumer (source, G_OBJECT (decl));
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a property name");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (decl);
|
||||
return NULL;
|
||||
}
|
||||
name = g_utf8_strdown (token->string.string, -1);
|
||||
priv->prop = (GtkCssStyleProperty *) _gtk_style_property_lookup (name);
|
||||
if (!GTK_IS_CSS_STYLE_PROPERTY (priv->prop))
|
||||
{
|
||||
gtk_css_token_source_unknown (source, "Property name '%s' is not a CSS property", token->string.string);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (decl);
|
||||
g_free (name);
|
||||
return NULL;
|
||||
}
|
||||
else if (!g_str_equal (name, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (priv->prop))))
|
||||
gtk_css_token_source_deprecated (source,
|
||||
"The '%s' property has been renamed to '%s'",
|
||||
name, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (priv->prop)));
|
||||
gtk_css_token_source_consume_token (source);
|
||||
g_free (name);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COLON))
|
||||
{
|
||||
gtk_css_token_source_error (source, "No colon following property name");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (decl);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
priv->value = gtk_style_property_token_parse (GTK_STYLE_PROPERTY (priv->prop), source);
|
||||
if (priv->value == NULL)
|
||||
{
|
||||
g_object_unref (decl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GTK_CSS_DECLARATION (decl);
|
||||
}
|
||||
|
||||
guint
|
||||
gtk_css_longhand_declaration_get_id (GtkCssLonghandDeclaration *decl)
|
||||
{
|
||||
GtkCssLonghandDeclarationPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_LONGHAND_DECLARATION (decl), 0);
|
||||
|
||||
priv = gtk_css_longhand_declaration_get_instance_private (decl);
|
||||
|
||||
return _gtk_css_style_property_get_id (priv->prop);
|
||||
}
|
||||
|
||||
GtkCssStyleProperty *
|
||||
gtk_css_longhand_declaration_get_property (GtkCssLonghandDeclaration *decl)
|
||||
{
|
||||
GtkCssLonghandDeclarationPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_LONGHAND_DECLARATION (decl), 0);
|
||||
|
||||
priv = gtk_css_longhand_declaration_get_instance_private (decl);
|
||||
|
||||
return priv->prop;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_longhand_declaration_get_value (GtkCssLonghandDeclaration *decl)
|
||||
{
|
||||
GtkCssLonghandDeclarationPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_LONGHAND_DECLARATION (decl), NULL);
|
||||
|
||||
priv = gtk_css_longhand_declaration_get_instance_private (decl);
|
||||
|
||||
return priv->value;
|
||||
}
|
||||
|
62
gtk/gtkcsslonghanddeclarationprivate.h
Normal file
62
gtk/gtkcsslonghanddeclarationprivate.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_LONGHAND_DECLARATION_PRIVATE_H__
|
||||
#define __GTK_CSS_LONGHAND_DECLARATION_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssdeclarationprivate.h"
|
||||
|
||||
#include "gtk/gtkcssstylepropertyprivate.h"
|
||||
#include "gtk/gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_LONGHAND_DECLARATION (gtk_css_longhand_declaration_get_type ())
|
||||
#define GTK_CSS_LONGHAND_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_LONGHAND_DECLARATION, GtkCssLonghandDeclaration))
|
||||
#define GTK_CSS_LONGHAND_DECLARATION_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_LONGHAND_DECLARATION, GtkCssLonghandDeclarationClass))
|
||||
#define GTK_IS_CSS_LONGHAND_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_LONGHAND_DECLARATION))
|
||||
#define GTK_IS_CSS_LONGHAND_DECLARATION_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_LONGHAND_DECLARATION))
|
||||
#define GTK_CSS_LONGHAND_DECLARATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_LONGHAND_DECLARATION, GtkCssLonghandDeclarationClass))
|
||||
|
||||
typedef struct _GtkCssLonghandDeclaration GtkCssLonghandDeclaration;
|
||||
typedef struct _GtkCssLonghandDeclarationClass GtkCssLonghandDeclarationClass;
|
||||
|
||||
struct _GtkCssLonghandDeclaration
|
||||
{
|
||||
GtkCssDeclaration parent;
|
||||
};
|
||||
|
||||
struct _GtkCssLonghandDeclarationClass
|
||||
{
|
||||
GtkCssDeclarationClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_longhand_declaration_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssDeclaration * gtk_css_longhand_declaration_new_parse (GtkCssStyleDeclaration *style,
|
||||
GtkCssTokenSource *source);
|
||||
|
||||
guint gtk_css_longhand_declaration_get_id (GtkCssLonghandDeclaration *decl);
|
||||
GtkCssStyleProperty * gtk_css_longhand_declaration_get_property (GtkCssLonghandDeclaration *decl);
|
||||
GtkCssValue * gtk_css_longhand_declaration_get_value (GtkCssLonghandDeclaration *decl);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_LONGHAND_DECLARATION_PRIVATE_H__ */
|
@@ -158,6 +158,47 @@ _gtk_css_number_value_parse (GtkCssParser *parser,
|
||||
return gtk_css_dimension_value_parse (parser, flags);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_css_number_value_check_token (const GtkCssToken *token)
|
||||
{
|
||||
return gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER)
|
||||
|| gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER)
|
||||
|| gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_NUMBER)
|
||||
|| gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_NUMBER)
|
||||
|| gtk_css_token_is (token, GTK_CSS_TOKEN_DIMENSION)
|
||||
|| gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION)
|
||||
|| gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION)
|
||||
|| gtk_css_token_is (token, GTK_CSS_TOKEN_PERCENTAGE)
|
||||
|| gtk_css_token_is_function (token, "calc")
|
||||
|| gtk_css_token_is_function (token, "-gtk-win32-size")
|
||||
|| gtk_css_token_is_function (token, "-gtk-win32-part-width")
|
||||
|| gtk_css_token_is_function (token, "-gtk-win32-part-height")
|
||||
|| gtk_css_token_is_function (token, "-gtk-win32-part-border-top")
|
||||
|| gtk_css_token_is_function (token, "-gtk-win32-part-border-left")
|
||||
|| gtk_css_token_is_function (token, "-gtk-win32-part-border-bottom")
|
||||
|| gtk_css_token_is_function (token, "-gtk-win32-part-border-right");
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_number_value_token_parse (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags)
|
||||
{
|
||||
const GtkCssToken *token = gtk_css_token_source_get_token (source);
|
||||
|
||||
if (gtk_css_token_is_function (token, "calc"))
|
||||
return gtk_css_calc_value_token_parse (source, flags);
|
||||
else if (gtk_css_token_is_function (token, "-gtk-win32-size") ||
|
||||
gtk_css_token_is_function (token, "-gtk-win32-part-width") ||
|
||||
gtk_css_token_is_function (token, "-gtk-win32-part-height") ||
|
||||
gtk_css_token_is_function (token, "-gtk-win32-part-border-top") ||
|
||||
gtk_css_token_is_function (token, "-gtk-win32-part-border-left") ||
|
||||
gtk_css_token_is_function (token, "-gtk-win32-part-border-bottom") ||
|
||||
gtk_css_token_is_function (token, "-gtk-win32-part-border-right"))
|
||||
return gtk_css_win32_size_value_token_parse (source, flags);
|
||||
else
|
||||
return gtk_css_dimension_value_token_parse (source, flags);
|
||||
}
|
||||
|
||||
double
|
||||
_gtk_css_number_value_get (const GtkCssValue *number,
|
||||
double one_hundred_percent)
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_CSS_NUMBER_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcsstypesprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
@@ -61,6 +62,9 @@ GtkCssValue * gtk_css_number_value_transition (GtkCssValue *sta
|
||||
gboolean gtk_css_number_value_can_parse (GtkCssParser *parser);
|
||||
GtkCssValue * _gtk_css_number_value_parse (GtkCssParser *parser,
|
||||
GtkCssNumberParseFlags flags);
|
||||
gboolean gtk_css_number_value_check_token (const GtkCssToken *token);
|
||||
GtkCssValue * gtk_css_number_value_token_parse (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags);
|
||||
|
||||
GtkCssDimension gtk_css_number_value_get_dimension (const GtkCssValue *value);
|
||||
gboolean gtk_css_number_value_has_percent (const GtkCssValue *value);
|
||||
|
@@ -242,6 +242,55 @@ gtk_css_palette_value_parse (GtkCssParser *parser)
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_palette_value_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssValue *result, *color;
|
||||
const GtkCssToken *token;
|
||||
char *ident;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "default"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return gtk_css_palette_value_new_default ();
|
||||
}
|
||||
|
||||
result = gtk_css_palette_value_new_empty ();
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected color name");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
_gtk_css_value_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
ident = g_strdup (token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
color = gtk_css_color_value_token_parse (source);
|
||||
if (color == NULL)
|
||||
{
|
||||
g_free (ident);
|
||||
_gtk_css_value_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_css_palette_value_add_color (result, ident, color);
|
||||
g_free (ident);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COMMA))
|
||||
break;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const GdkRGBA *
|
||||
gtk_css_palette_value_get_color (GtkCssValue *value,
|
||||
const char *name)
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_CSS_PALETTE_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -28,6 +29,7 @@ G_BEGIN_DECLS
|
||||
GtkCssValue * gtk_css_palette_value_new_default (void);
|
||||
|
||||
GtkCssValue * gtk_css_palette_value_parse (GtkCssParser *parser);
|
||||
GtkCssValue * gtk_css_palette_value_token_parse (GtkCssTokenSource *source);
|
||||
|
||||
const GdkRGBA * gtk_css_palette_value_get_color (GtkCssValue *value,
|
||||
const char *color_name);
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include "gtkcssparserprivate.h"
|
||||
|
||||
#include "gtkcssdimensionvalueprivate.h"
|
||||
#include "gtkcsstokenizerprivate.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
@@ -46,6 +47,54 @@ struct _GtkCssParser
|
||||
guint line;
|
||||
};
|
||||
|
||||
#include "gtkcssstylesheetprivate.h"
|
||||
|
||||
static void
|
||||
do_the_tokenizer (const char *data)
|
||||
{
|
||||
#if 0
|
||||
GtkCssTokenizer *tokenizer;
|
||||
GtkCssToken token;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_bytes_new_static (data, strlen (data));
|
||||
tokenizer = gtk_css_tokenizer_new (bytes, NULL, NULL, NULL);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
for (gtk_css_tokenizer_read_token (tokenizer, &token);
|
||||
token.type != GTK_CSS_TOKEN_EOF;
|
||||
gtk_css_tokenizer_read_token (tokenizer, &token))
|
||||
{
|
||||
char *s = gtk_css_token_to_string (&token);
|
||||
g_print ("%3zu:%02zu %2d %s\n",
|
||||
gtk_css_tokenizer_get_line (tokenizer), gtk_css_tokenizer_get_line_char (tokenizer),
|
||||
token.type, s);
|
||||
g_free (s);
|
||||
gtk_css_token_clear (&token);
|
||||
}
|
||||
|
||||
gtk_css_tokenizer_unref (tokenizer);
|
||||
#else
|
||||
#if 0
|
||||
GtkCssStyleSheet *sheet;
|
||||
GtkCssTokenSource *source;
|
||||
GtkCssTokenizer *tokenizer;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_bytes_new_static (data, strlen (data));
|
||||
tokenizer = gtk_css_tokenizer_new (bytes, NULL, NULL, NULL);
|
||||
source = gtk_css_token_source_new_for_tokenizer (tokenizer);
|
||||
sheet = gtk_css_style_sheet_new ();
|
||||
gtk_css_style_sheet_parse (sheet, source);
|
||||
|
||||
g_object_unref (sheet);
|
||||
gtk_css_token_source_unref (source);
|
||||
gtk_css_tokenizer_unref (tokenizer);
|
||||
g_bytes_unref (bytes);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
GtkCssParser *
|
||||
_gtk_css_parser_new (const char *data,
|
||||
GFile *file,
|
||||
@@ -57,6 +106,8 @@ _gtk_css_parser_new (const char *data,
|
||||
g_return_val_if_fail (data != NULL, NULL);
|
||||
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
|
||||
|
||||
do_the_tokenizer (data);
|
||||
|
||||
parser = g_slice_new0 (GtkCssParser);
|
||||
|
||||
parser->data = data;
|
||||
|
@@ -291,6 +291,262 @@ _gtk_css_position_value_try_parse (GtkCssParser *parser)
|
||||
return position_value_parse (parser, TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_css_position_value_check_token (const GtkCssToken *token)
|
||||
{
|
||||
return gtk_css_token_is_ident (token, "center")
|
||||
|| gtk_css_token_is_ident (token, "left")
|
||||
|| gtk_css_token_is_ident (token, "right")
|
||||
|| gtk_css_token_is_ident (token, "top")
|
||||
|| gtk_css_token_is_ident (token, "bottom")
|
||||
|| gtk_css_number_value_check_token (token);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
NONE = 0,
|
||||
CENTER,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
TOP,
|
||||
BOTTOM
|
||||
} Keyword;
|
||||
|
||||
static Keyword
|
||||
get_keyword (const GtkCssToken *token)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, "center"))
|
||||
return CENTER;
|
||||
else if (gtk_css_token_is_ident (token, "left"))
|
||||
return LEFT;
|
||||
else if (gtk_css_token_is_ident (token, "right"))
|
||||
return RIGHT;
|
||||
else if (gtk_css_token_is_ident (token, "top"))
|
||||
return TOP;
|
||||
else if (gtk_css_token_is_ident (token, "bottom"))
|
||||
return BOTTOM;
|
||||
else
|
||||
return NONE;
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
value_from_keyword (Keyword keyword,
|
||||
GtkCssValue *value)
|
||||
{
|
||||
switch (keyword)
|
||||
{
|
||||
default:
|
||||
case NONE:
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
case CENTER:
|
||||
g_assert (value == NULL);
|
||||
return _gtk_css_number_value_new (50, GTK_CSS_PERCENT);
|
||||
case LEFT:
|
||||
case TOP:
|
||||
if (value)
|
||||
return value;
|
||||
else
|
||||
return _gtk_css_number_value_new (0, GTK_CSS_PERCENT);
|
||||
case RIGHT:
|
||||
case BOTTOM:
|
||||
if (value == NULL)
|
||||
return _gtk_css_number_value_new (100, GTK_CSS_PERCENT);
|
||||
else
|
||||
{
|
||||
GtkCssValue *mult = gtk_css_number_value_multiply (value, -1);
|
||||
GtkCssValue *hundred = _gtk_css_number_value_new (100, GTK_CSS_PERCENT);
|
||||
GtkCssValue *sum = gtk_css_number_value_add (hundred, mult);
|
||||
|
||||
_gtk_css_value_unref (mult);
|
||||
_gtk_css_value_unref (hundred);
|
||||
_gtk_css_value_unref (value);
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
keywords_compatible (Keyword a, Keyword b)
|
||||
{
|
||||
if ((a == LEFT || a == RIGHT) && (b == LEFT || b == RIGHT))
|
||||
return FALSE;
|
||||
if ((a == TOP || a == BOTTOM) && (b == TOP || b == BOTTOM))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
keywords_need_swap (Keyword x, Keyword y)
|
||||
{
|
||||
/* NB: We assume the keywords are compatible here */
|
||||
return x == TOP || x == BOTTOM
|
||||
|| y == LEFT || y == RIGHT;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_position_value_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GtkCssValue *x, *y;
|
||||
Keyword keyword;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
|
||||
keyword = get_keyword (token);
|
||||
if (keyword == NONE)
|
||||
{
|
||||
/* NUMBER ... */
|
||||
x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_PERCENT | GTK_CSS_PARSE_LENGTH);
|
||||
if (x == NULL)
|
||||
return NULL;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
keyword = get_keyword (token);
|
||||
if (keyword == NONE)
|
||||
{
|
||||
if (gtk_css_number_value_check_token (token))
|
||||
{
|
||||
/* NUMBER NUMBER */
|
||||
y = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_PERCENT | GTK_CSS_PARSE_LENGTH);
|
||||
if (y == NULL)
|
||||
{
|
||||
_gtk_css_value_unref (x);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NUMBER */
|
||||
y = value_from_keyword (CENTER, NULL);
|
||||
}
|
||||
}
|
||||
else if (keyword == LEFT || keyword == RIGHT)
|
||||
{
|
||||
gtk_css_token_source_error (source, "\"left\" and \"right\" may not follow a number");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
_gtk_css_value_unref (x);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NUMBER KEYWORD */
|
||||
y = value_from_keyword (keyword, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* KEYWORD ... */
|
||||
Keyword keyword2;
|
||||
GtkCssValue *value;
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
keyword2 = get_keyword (token);
|
||||
if (keyword2 != NONE)
|
||||
{
|
||||
/* KEYWORD KEYWORD ... */
|
||||
if (!keywords_compatible (keyword, keyword2))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Two keywords for same axis");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (keyword2 != CENTER && gtk_css_number_value_check_token (token))
|
||||
{
|
||||
/* KEYWORD KEYWORD NUMBER */
|
||||
value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_PERCENT | GTK_CSS_PARSE_LENGTH);
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
value = NULL;
|
||||
|
||||
if (keywords_need_swap (keyword, keyword2))
|
||||
{
|
||||
x = value_from_keyword (keyword2, value);
|
||||
y = value_from_keyword (keyword, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = value_from_keyword (keyword, NULL);
|
||||
y = value_from_keyword (keyword2, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gtk_css_number_value_check_token (token))
|
||||
{
|
||||
/* KEYWORD NUMBER ... */
|
||||
x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_PERCENT | GTK_CSS_PARSE_LENGTH);
|
||||
if (x == NULL)
|
||||
return NULL;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
keyword2 = get_keyword (token);
|
||||
if (keyword2 == NONE)
|
||||
{
|
||||
/* KEYWORD NUMBER */
|
||||
if (keyword == TOP || keyword == BOTTOM)
|
||||
{
|
||||
x = value_from_keyword (LEFT, x);
|
||||
y = value_from_keyword (keyword, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
y = value_from_keyword (LEFT, x);
|
||||
x = value_from_keyword (keyword, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* KEYWORD NUMBER KEYWORD ... */
|
||||
if (!keywords_compatible (keyword, keyword2))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Two keywords for same axis");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (keyword2 != CENTER && gtk_css_number_value_check_token (token))
|
||||
{
|
||||
/* KEYWORD NUMBER KEYWORD NUMBER */
|
||||
y = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_PERCENT | GTK_CSS_PARSE_LENGTH);
|
||||
if (y == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
y = NULL;
|
||||
|
||||
if (keywords_need_swap (keyword, keyword2))
|
||||
{
|
||||
value = value_from_keyword (keyword2, y);
|
||||
y = value_from_keyword (keyword, x);
|
||||
x = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = value_from_keyword (keyword, x);
|
||||
y = value_from_keyword (keyword, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* KEYWORD */
|
||||
x = value_from_keyword (keyword, NULL);
|
||||
y = value_from_keyword (CENTER, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _gtk_css_position_value_new (x, y);
|
||||
}
|
||||
|
||||
double
|
||||
_gtk_css_position_value_get_x (const GtkCssValue *position,
|
||||
double one_hundred_percent)
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_CSS_POSITION_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -29,6 +30,8 @@ GtkCssValue * _gtk_css_position_value_new (GtkCssValue *x
|
||||
GtkCssValue *y);
|
||||
GtkCssValue * _gtk_css_position_value_parse (GtkCssParser *parser);
|
||||
GtkCssValue * _gtk_css_position_value_try_parse (GtkCssParser *parser);
|
||||
gboolean gtk_css_position_value_check_token (const GtkCssToken *token);
|
||||
GtkCssValue * gtk_css_position_value_token_parse (GtkCssTokenSource *source);
|
||||
|
||||
double _gtk_css_position_value_get_x (const GtkCssValue *position,
|
||||
double one_hundred_percent);
|
||||
|
@@ -28,12 +28,20 @@
|
||||
#include "gtkbitmaskprivate.h"
|
||||
#include "gtkcssarrayvalueprivate.h"
|
||||
#include "gtkcsscolorvalueprivate.h"
|
||||
#include "gtkcssdefinecolorruleprivate.h"
|
||||
#include "gtkcssdeclarationprivate.h"
|
||||
#include "gtkcssimportruleprivate.h"
|
||||
#include "gtkcsskeyframesprivate.h"
|
||||
#include "gtkcsskeyframesruleprivate.h"
|
||||
#include "gtkcsslonghanddeclarationprivate.h"
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsssectionprivate.h"
|
||||
#include "gtkcssselectorprivate.h"
|
||||
#include "gtkcssshorthandpropertyprivate.h"
|
||||
#include "gtkcssshorthanddeclarationprivate.h"
|
||||
#include "gtkcssstylefuncsprivate.h"
|
||||
#include "gtkcssstylepropertyprivate.h"
|
||||
#include "gtkcssstyleruleprivate.h"
|
||||
#include "gtkcsswidgetstyledeclarationprivate.h"
|
||||
#include "gtksettingsprivate.h"
|
||||
#include "gtkstyleprovider.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
@@ -296,7 +304,7 @@ widget_property_value_new (char *name, GtkCssSection *section)
|
||||
value = g_slice_new0 (WidgetPropertyValue);
|
||||
|
||||
value->name = name;
|
||||
if (gtk_keep_css_sections)
|
||||
if (gtk_keep_css_sections && section)
|
||||
value->section = gtk_css_section_ref (section);
|
||||
|
||||
return value;
|
||||
@@ -395,7 +403,7 @@ gtk_css_ruleset_add (GtkCssRuleset *ruleset,
|
||||
}
|
||||
|
||||
ruleset->styles[i].value = value;
|
||||
if (gtk_keep_css_sections)
|
||||
if (gtk_keep_css_sections && section)
|
||||
ruleset->styles[i].section = gtk_css_section_ref (section);
|
||||
else
|
||||
ruleset->styles[i].section = NULL;
|
||||
@@ -1715,6 +1723,114 @@ gtk_css_provider_postprocess (GtkCssProvider *css_provider)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_provider_load_rules (GtkCssProvider *provider,
|
||||
GtkCssRuleList *list)
|
||||
{
|
||||
GtkCssRule *rule;
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < gtk_css_rule_list_get_length (list); i++)
|
||||
{
|
||||
rule = gtk_css_rule_list_get_item (list, i);
|
||||
|
||||
if (GTK_IS_CSS_DEFINE_COLOR_RULE (rule))
|
||||
{
|
||||
GtkCssDefineColorRule *color_rule = GTK_CSS_DEFINE_COLOR_RULE (rule);
|
||||
|
||||
g_hash_table_insert (provider->priv->symbolic_colors,
|
||||
g_strdup (gtk_css_define_color_rule_get_name (color_rule)),
|
||||
_gtk_css_value_ref (gtk_css_define_color_rule_get_value (color_rule)));
|
||||
}
|
||||
else if (GTK_IS_CSS_IMPORT_RULE (rule))
|
||||
{
|
||||
GtkCssStyleSheet *style_sheet = gtk_css_import_rule_get_style_sheet (GTK_CSS_IMPORT_RULE (rule));
|
||||
gtk_css_provider_load_rules (provider, gtk_css_style_sheet_get_css_rules (style_sheet));
|
||||
}
|
||||
else if (GTK_IS_CSS_KEYFRAMES_RULE (rule))
|
||||
{
|
||||
g_hash_table_insert (provider->priv->keyframes,
|
||||
g_strdup (gtk_css_keyframes_rule_get_name (GTK_CSS_KEYFRAMES_RULE (rule))),
|
||||
gtk_css_keyframes_new_from_rule (GTK_CSS_KEYFRAMES_RULE (rule)));
|
||||
}
|
||||
else if (GTK_IS_CSS_STYLE_RULE (rule))
|
||||
{
|
||||
GtkCssStyleDeclaration *style = gtk_css_style_rule_get_style (GTK_CSS_STYLE_RULE (rule));
|
||||
GtkCssRuleset ruleset = { 0, };
|
||||
guint j;
|
||||
|
||||
for (j = 0; j < gtk_css_style_declaration_get_length (style); j++)
|
||||
{
|
||||
GtkCssDeclaration *decl = gtk_css_style_declaration_get_declaration (style, j);
|
||||
|
||||
if (GTK_IS_CSS_LONGHAND_DECLARATION (decl))
|
||||
{
|
||||
GtkCssLonghandDeclaration *longhand = GTK_CSS_LONGHAND_DECLARATION (decl);
|
||||
gtk_css_ruleset_add (&ruleset,
|
||||
gtk_css_longhand_declaration_get_property (longhand),
|
||||
_gtk_css_value_ref (gtk_css_longhand_declaration_get_value (longhand)),
|
||||
NULL);
|
||||
}
|
||||
else if (GTK_IS_CSS_SHORTHAND_DECLARATION (decl))
|
||||
{
|
||||
GtkCssShorthandDeclaration *shorthand = GTK_CSS_SHORTHAND_DECLARATION (decl);
|
||||
guint k;
|
||||
|
||||
for (k = 0; k < gtk_css_shorthand_declaration_get_length (shorthand); k++)
|
||||
{
|
||||
gtk_css_ruleset_add (&ruleset,
|
||||
gtk_css_shorthand_declaration_get_subproperty (shorthand, k),
|
||||
_gtk_css_value_ref (gtk_css_shorthand_declaration_get_value (shorthand, k)),
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
else if (GTK_IS_CSS_WIDGET_STYLE_DECLARATION (decl))
|
||||
{
|
||||
WidgetPropertyValue *val;
|
||||
|
||||
val = widget_property_value_new (g_strdup (gtk_css_declaration_get_name (decl)), NULL);
|
||||
val->value = gtk_css_declaration_get_value_string (decl);
|
||||
|
||||
gtk_css_ruleset_add_style (&ruleset, val->name, val);
|
||||
}
|
||||
}
|
||||
|
||||
if (ruleset.styles != NULL || ruleset.widget_style != NULL)
|
||||
{
|
||||
for (j = 0; j < gtk_css_style_rule_get_n_selectors (GTK_CSS_STYLE_RULE (rule)); j++)
|
||||
{
|
||||
GtkCssRuleset new;
|
||||
|
||||
gtk_css_ruleset_init_copy (&new,
|
||||
&ruleset,
|
||||
gtk_css_style_rule_get_selector (GTK_CSS_STYLE_RULE (rule), j));
|
||||
|
||||
g_array_append_val (provider->priv->rulesets, new);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_css_ruleset_clear (&ruleset);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("No code to deal with %s", G_OBJECT_TYPE_NAME (rule));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_provider_load_style_sheet (GtkCssProvider *provider,
|
||||
GtkCssStyleSheet *style_sheet)
|
||||
{
|
||||
gtk_css_provider_reset (provider);
|
||||
|
||||
gtk_css_provider_load_rules (provider, gtk_css_style_sheet_get_css_rules (style_sheet));
|
||||
|
||||
gtk_css_provider_postprocess (provider);
|
||||
|
||||
_gtk_style_provider_private_changed (GTK_STYLE_PROVIDER_PRIVATE (provider));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_provider_load_internal (GtkCssProvider *css_provider,
|
||||
GtkCssScanner *parent,
|
||||
|
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "gtkcssprovider.h"
|
||||
|
||||
#include "gtkcssstylesheetprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gchar *_gtk_get_theme_dir (void);
|
||||
@@ -30,6 +32,9 @@ void _gtk_css_provider_load_named (GtkCssProvider *provider,
|
||||
const gchar *name,
|
||||
const gchar *variant);
|
||||
|
||||
void gtk_css_provider_load_style_sheet (GtkCssProvider *provider,
|
||||
GtkCssStyleSheet *style_sheet);
|
||||
|
||||
void gtk_css_provider_set_keep_css_sections (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
750
gtk/gtkcssrbtree.c
Normal file
750
gtk/gtkcssrbtree.c
Normal file
@@ -0,0 +1,750 @@
|
||||
/* gtkrbtree.c
|
||||
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssrbtreeprivate.h"
|
||||
|
||||
#include "gtkdebug.h"
|
||||
|
||||
typedef struct _GtkCssRbNode GtkCssRbNode;
|
||||
|
||||
struct _GtkCssRbTree
|
||||
{
|
||||
guint ref_count;
|
||||
|
||||
gsize element_size;
|
||||
gsize augment_size;
|
||||
GtkCssRbTreeAugmentFunc augment_func;
|
||||
GDestroyNotify clear_func;
|
||||
GDestroyNotify clear_augment_func;
|
||||
|
||||
GtkCssRbNode *root;
|
||||
};
|
||||
|
||||
struct _GtkCssRbNode
|
||||
{
|
||||
guint red :1;
|
||||
guint dirty :1;
|
||||
|
||||
GtkCssRbNode *left;
|
||||
GtkCssRbNode *right;
|
||||
GtkCssRbNode *parent;
|
||||
};
|
||||
|
||||
#define NODE_FROM_POINTER(ptr) ((GtkCssRbNode *) ((ptr) ? (((guchar *) (ptr)) - sizeof (GtkCssRbNode)) : NULL))
|
||||
#define NODE_TO_POINTER(node) ((gpointer) ((node) ? (((guchar *) (node)) + sizeof (GtkCssRbNode)) : NULL))
|
||||
#define NODE_TO_AUG_POINTER(tree, node) ((gpointer) ((node) ? (((guchar *) (node)) + sizeof (GtkCssRbNode) + (tree)->element_size) : NULL))
|
||||
|
||||
static inline gsize
|
||||
gtk_css_rb_node_get_size (GtkCssRbTree *tree)
|
||||
{
|
||||
return sizeof (GtkCssRbNode) + tree->element_size + tree->augment_size;
|
||||
}
|
||||
|
||||
static GtkCssRbNode *
|
||||
gtk_css_rb_node_new (GtkCssRbTree *tree)
|
||||
{
|
||||
GtkCssRbNode *result;
|
||||
|
||||
result = g_slice_alloc0 (gtk_css_rb_node_get_size (tree));
|
||||
|
||||
result->red = TRUE;
|
||||
result->dirty = TRUE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_free (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
if (tree->clear_func)
|
||||
tree->clear_func (NODE_TO_POINTER (node));
|
||||
if (tree->clear_augment_func)
|
||||
tree->clear_augment_func (NODE_TO_AUG_POINTER (tree, node));
|
||||
|
||||
g_slice_free1 (gtk_css_rb_node_get_size (tree), node);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_free_deep (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
GtkCssRbNode *right = node->right;
|
||||
|
||||
if (node->left)
|
||||
gtk_css_rb_node_free_deep (tree, node->left);
|
||||
|
||||
gtk_css_rb_node_free (tree, node);
|
||||
|
||||
if (right)
|
||||
gtk_css_rb_node_free_deep (tree, right);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_mark_dirty (GtkCssRbNode *node,
|
||||
gboolean mark_parent)
|
||||
{
|
||||
if (node->dirty)
|
||||
return;
|
||||
|
||||
node->dirty = TRUE;
|
||||
|
||||
if (mark_parent && node->parent)
|
||||
gtk_css_rb_node_mark_dirty (node->parent, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_clean (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
if (!node->dirty)
|
||||
return;
|
||||
|
||||
node->dirty = FALSE;
|
||||
if (tree->augment_func)
|
||||
tree->augment_func (tree,
|
||||
NODE_TO_AUG_POINTER (tree, node),
|
||||
NODE_TO_POINTER (node),
|
||||
NODE_TO_POINTER (node->left),
|
||||
NODE_TO_POINTER (node->right));
|
||||
}
|
||||
|
||||
static GtkCssRbNode *
|
||||
gtk_css_rb_node_get_first (GtkCssRbNode *node)
|
||||
{
|
||||
while (node->left)
|
||||
node = node->left;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GtkCssRbNode *
|
||||
gtk_css_rb_node_get_last (GtkCssRbNode *node)
|
||||
{
|
||||
while (node->right)
|
||||
node = node->right;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GtkCssRbNode *
|
||||
gtk_css_rb_node_get_previous (GtkCssRbNode *node)
|
||||
{
|
||||
GtkCssRbNode *parent;
|
||||
|
||||
if (node->left)
|
||||
return gtk_css_rb_node_get_last (node->left);
|
||||
|
||||
for (parent = node->parent; parent != NULL; parent = node->parent)
|
||||
{
|
||||
if (parent->right == node)
|
||||
return parent;
|
||||
|
||||
node = parent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GtkCssRbNode *
|
||||
gtk_css_rb_node_get_next (GtkCssRbNode *node)
|
||||
{
|
||||
GtkCssRbNode *parent;
|
||||
|
||||
if (node->right)
|
||||
return gtk_css_rb_node_get_first (node->right);
|
||||
|
||||
for (parent = node->parent; parent != NULL; parent = node->parent)
|
||||
{
|
||||
if (parent->left == node)
|
||||
return parent;
|
||||
|
||||
node = parent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_rotate_left (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
GtkCssRbNode *right;
|
||||
|
||||
right = node->right;
|
||||
|
||||
node->right = right->left;
|
||||
if (right->left)
|
||||
right->left->parent = node;
|
||||
|
||||
right->parent = node->parent;
|
||||
if (node->parent)
|
||||
{
|
||||
if (node == node->parent->left)
|
||||
node->parent->left = right;
|
||||
else
|
||||
node->parent->right = right;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree->root = right;
|
||||
}
|
||||
|
||||
right->left = node;
|
||||
node->parent = right;
|
||||
|
||||
gtk_css_rb_node_mark_dirty (node, FALSE);
|
||||
gtk_css_rb_node_mark_dirty (right, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_node_rotate_right (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
GtkCssRbNode *left;
|
||||
|
||||
left = node->left;
|
||||
|
||||
node->left = left->right;
|
||||
if (left->right)
|
||||
left->right->parent = node;
|
||||
|
||||
left->parent = node->parent;
|
||||
if (node->parent)
|
||||
{
|
||||
if (node == node->parent->right)
|
||||
node->parent->right = left;
|
||||
else
|
||||
node->parent->left = left;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree->root = left;
|
||||
}
|
||||
|
||||
/* link node and left */
|
||||
left->right = node;
|
||||
node->parent = left;
|
||||
|
||||
gtk_css_rb_node_mark_dirty (node, FALSE);
|
||||
gtk_css_rb_node_mark_dirty (left, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_red (GtkCssRbNode *node_or_null)
|
||||
{
|
||||
if (node_or_null == NULL)
|
||||
return FALSE;
|
||||
else
|
||||
return node_or_null->red;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_black (GtkCssRbNode *node_or_null)
|
||||
{
|
||||
return !is_red (node_or_null);
|
||||
}
|
||||
|
||||
static void
|
||||
set_black (GtkCssRbNode *node_or_null)
|
||||
{
|
||||
if (node_or_null == NULL)
|
||||
return;
|
||||
|
||||
node_or_null->red = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_red (GtkCssRbNode *node_or_null)
|
||||
{
|
||||
if (node_or_null == NULL)
|
||||
return;
|
||||
|
||||
node_or_null->red = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_tree_insert_fixup (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node)
|
||||
{
|
||||
|
||||
/* check Red-Black properties */
|
||||
while (node->parent && is_red (node->parent))
|
||||
{
|
||||
/* we have a violation */
|
||||
g_assert (node->parent->parent);
|
||||
|
||||
if (node->parent == node->parent->parent->left)
|
||||
{
|
||||
GtkCssRbNode *uncle = node->parent->parent->right;
|
||||
|
||||
if (is_red (uncle))
|
||||
{
|
||||
/* uncle is red */
|
||||
set_black (node->parent);
|
||||
set_black (uncle);
|
||||
set_red (node->parent->parent);
|
||||
node = node->parent->parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* uncle is black */
|
||||
if (node == node->parent->right)
|
||||
{
|
||||
/* make node a left child */
|
||||
node = node->parent;
|
||||
gtk_css_rb_node_rotate_left (tree, node);
|
||||
}
|
||||
/* recolor and rotate */
|
||||
set_black (node->parent);
|
||||
set_red (node->parent->parent);
|
||||
gtk_css_rb_node_rotate_right (tree, node->parent->parent);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* mirror image of above code */
|
||||
GtkCssRbNode *uncle = node->parent->parent->left;
|
||||
|
||||
if (is_red (uncle))
|
||||
{
|
||||
/* uncle is red */
|
||||
set_black (node->parent);
|
||||
set_black (uncle);
|
||||
set_red (node->parent->parent);
|
||||
node = node->parent->parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* uncle is black */
|
||||
if (node == node->parent->left)
|
||||
{
|
||||
node = node->parent;
|
||||
gtk_css_rb_node_rotate_right (tree, node);
|
||||
}
|
||||
set_black (node->parent);
|
||||
set_red (node->parent->parent);
|
||||
gtk_css_rb_node_rotate_left (tree, node->parent->parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_black (tree->root);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rb_tree_remove_node_fixup (GtkCssRbTree *tree,
|
||||
GtkCssRbNode *node,
|
||||
GtkCssRbNode *parent)
|
||||
{
|
||||
while (node->parent && is_black (node))
|
||||
{
|
||||
if (node == parent->left)
|
||||
{
|
||||
GtkCssRbNode *w = parent->right;
|
||||
|
||||
if (is_red (w))
|
||||
{
|
||||
set_black (w);
|
||||
set_red (parent);
|
||||
gtk_css_rb_node_rotate_left (tree, parent);
|
||||
w = parent->right;
|
||||
}
|
||||
if (is_black (w->left) && is_black (w->right))
|
||||
{
|
||||
set_red (w);
|
||||
node = parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_black (w->right))
|
||||
{
|
||||
set_black (w->left);
|
||||
set_red (w);
|
||||
gtk_css_rb_node_rotate_right (tree, w);
|
||||
w = parent->right;
|
||||
}
|
||||
w->red = parent->red;
|
||||
set_black (parent);
|
||||
set_black (w->right);
|
||||
gtk_css_rb_node_rotate_left (tree, parent);
|
||||
node = tree->root;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkCssRbNode *w = parent->left;
|
||||
if (is_red (w))
|
||||
{
|
||||
set_black (w);
|
||||
set_red (parent);
|
||||
gtk_css_rb_node_rotate_right (tree, parent);
|
||||
w = parent->left;
|
||||
}
|
||||
if (is_black (w->right) && is_black (w->left))
|
||||
{
|
||||
set_red (w);
|
||||
node = parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_black (w->left))
|
||||
{
|
||||
set_black (w->right);
|
||||
set_red (w);
|
||||
gtk_css_rb_node_rotate_left (tree, w);
|
||||
w = parent->left;
|
||||
}
|
||||
w->red = parent->red;
|
||||
set_black (parent);
|
||||
set_black (w->left);
|
||||
gtk_css_rb_node_rotate_right (tree, parent);
|
||||
node = tree->root;
|
||||
}
|
||||
}
|
||||
|
||||
parent = node->parent;
|
||||
}
|
||||
|
||||
set_black (node);
|
||||
}
|
||||
|
||||
GtkCssRbTree *
|
||||
gtk_css_rb_tree_new_for_size (gsize element_size,
|
||||
gsize augment_size,
|
||||
GtkCssRbTreeAugmentFunc augment_func,
|
||||
GDestroyNotify clear_func,
|
||||
GDestroyNotify clear_augment_func)
|
||||
{
|
||||
GtkCssRbTree *tree;
|
||||
|
||||
tree = g_slice_new0 (GtkCssRbTree);
|
||||
tree->ref_count = 1;
|
||||
|
||||
tree->element_size = element_size;
|
||||
tree->augment_size = augment_size;
|
||||
tree->augment_func = augment_func;
|
||||
tree->clear_func = clear_func;
|
||||
tree->clear_augment_func = clear_augment_func;
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
GtkCssRbTree *
|
||||
gtk_css_rb_tree_ref (GtkCssRbTree *tree)
|
||||
{
|
||||
tree->ref_count++;
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_rb_tree_unref (GtkCssRbTree *tree)
|
||||
{
|
||||
tree->ref_count--;
|
||||
if (tree->ref_count > 0)
|
||||
return;
|
||||
|
||||
if (tree->root)
|
||||
gtk_css_rb_node_free_deep (tree, tree->root);
|
||||
|
||||
g_slice_free (GtkCssRbTree, tree);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_first (GtkCssRbTree *tree)
|
||||
{
|
||||
if (tree->root == NULL)
|
||||
return NULL;
|
||||
|
||||
return NODE_TO_POINTER (gtk_css_rb_node_get_first (tree->root));
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_last (GtkCssRbTree *tree)
|
||||
{
|
||||
if (tree->root == NULL)
|
||||
return NULL;
|
||||
|
||||
return NODE_TO_POINTER (gtk_css_rb_node_get_last (tree->root));
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_previous (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
return NODE_TO_POINTER (gtk_css_rb_node_get_previous (NODE_FROM_POINTER (node)));
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_next (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
return NODE_TO_POINTER (gtk_css_rb_node_get_next (NODE_FROM_POINTER (node)));
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_root (GtkCssRbTree *tree)
|
||||
{
|
||||
return NODE_TO_POINTER (tree->root);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_parent (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
return NODE_TO_POINTER (NODE_FROM_POINTER (node)->parent);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_left (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
return NODE_TO_POINTER (NODE_FROM_POINTER (node)->left);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_right (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
return NODE_TO_POINTER (NODE_FROM_POINTER (node)->right);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_get_augment (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
GtkCssRbNode *rbnode = NODE_FROM_POINTER (node);
|
||||
|
||||
gtk_css_rb_node_clean (tree, rbnode);
|
||||
|
||||
return NODE_TO_AUG_POINTER (tree, rbnode);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_rb_tree_mark_dirty (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
gtk_css_rb_node_mark_dirty (NODE_FROM_POINTER (node), TRUE);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_insert_before (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
GtkCssRbNode *result;
|
||||
|
||||
/* setup new node */
|
||||
result = gtk_css_rb_node_new (tree);
|
||||
|
||||
if (tree->root == NULL)
|
||||
{
|
||||
g_assert (node == NULL);
|
||||
tree->root = result;
|
||||
}
|
||||
else if (node == NULL)
|
||||
{
|
||||
return gtk_css_rb_tree_insert_after (tree, gtk_css_rb_tree_get_last (tree));
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkCssRbNode *current = NODE_FROM_POINTER (node);
|
||||
|
||||
if (current->left)
|
||||
{
|
||||
current = gtk_css_rb_node_get_last (current);
|
||||
current->right = result;
|
||||
}
|
||||
else
|
||||
{
|
||||
current->left = result;
|
||||
}
|
||||
result->parent = current;
|
||||
gtk_css_rb_node_mark_dirty (current, TRUE);
|
||||
}
|
||||
|
||||
gtk_css_rb_tree_insert_fixup (tree, result);
|
||||
|
||||
return NODE_TO_POINTER (result);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_insert_after (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
GtkCssRbNode *result;
|
||||
|
||||
/* setup new node */
|
||||
result = gtk_css_rb_node_new (tree);
|
||||
|
||||
if (tree->root == NULL)
|
||||
{
|
||||
g_assert (node == NULL);
|
||||
tree->root = result;
|
||||
}
|
||||
else if (node == NULL)
|
||||
{
|
||||
return gtk_css_rb_tree_insert_before (tree, gtk_css_rb_tree_get_first (tree));
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkCssRbNode *current = NODE_FROM_POINTER (node);
|
||||
|
||||
if (current->right )
|
||||
{
|
||||
current = gtk_css_rb_node_get_first (current);
|
||||
current->left = result;
|
||||
}
|
||||
else
|
||||
{
|
||||
current->right = result;
|
||||
}
|
||||
result->parent = current;
|
||||
gtk_css_rb_node_mark_dirty (current, TRUE);
|
||||
}
|
||||
|
||||
gtk_css_rb_tree_insert_fixup (tree, result);
|
||||
|
||||
return NODE_TO_POINTER (result);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_rb_tree_remove (GtkCssRbTree *tree,
|
||||
gpointer node)
|
||||
{
|
||||
GtkCssRbNode *x, *y, *real_node;
|
||||
|
||||
real_node = NODE_FROM_POINTER (node);
|
||||
y = real_node;
|
||||
if (y->left && y->right)
|
||||
{
|
||||
y = y->right;
|
||||
|
||||
while (y->left)
|
||||
y = y->left;
|
||||
}
|
||||
|
||||
/* x is y's only child, or nil */
|
||||
if (y->left)
|
||||
x = y->left;
|
||||
else
|
||||
x = y->right;
|
||||
|
||||
/* remove y from the parent chain */
|
||||
if (x != NULL)
|
||||
x->parent = y->parent;
|
||||
if (y->parent)
|
||||
{
|
||||
if (y == y->parent->left)
|
||||
y->parent->left = x;
|
||||
else
|
||||
y->parent->right = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree->root = x;
|
||||
}
|
||||
|
||||
/* We need to clean up the validity of the tree.
|
||||
*/
|
||||
if (x && is_black (y))
|
||||
gtk_css_rb_tree_remove_node_fixup (tree, x, y->parent);
|
||||
|
||||
if (y != real_node)
|
||||
{
|
||||
/* Move the node over */
|
||||
if (is_red (real_node) != is_red (y))
|
||||
y->red = !y->red;
|
||||
|
||||
y->left = real_node->left;
|
||||
if (y->left)
|
||||
y->left->parent = y;
|
||||
y->right = real_node->right;
|
||||
if (y->right)
|
||||
y->right->parent = y;
|
||||
y->parent = real_node->parent;
|
||||
if (y->parent)
|
||||
{
|
||||
if (y->parent->left == real_node)
|
||||
y->parent->left = y;
|
||||
else
|
||||
y->parent->right = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree->root = y;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_css_rb_node_free (tree, real_node);
|
||||
}
|
||||
|
||||
|
||||
gpointer
|
||||
gtk_css_rb_tree_find (GtkCssRbTree *tree,
|
||||
gpointer *out_before,
|
||||
gpointer *out_after,
|
||||
GtkCssRbTreeFindFunc find_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkCssRbNode *node, *before = NULL, *after = NULL;
|
||||
int cmp;
|
||||
|
||||
if (tree->root == NULL)
|
||||
{
|
||||
if (out_before)
|
||||
*out_before = NULL;
|
||||
if (out_after)
|
||||
*out_after = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = tree->root;
|
||||
for (cmp = find_func (tree, NODE_TO_POINTER (node), user_data);
|
||||
cmp != 0;
|
||||
cmp = find_func (tree, NODE_TO_POINTER (node), user_data))
|
||||
{
|
||||
if (cmp < 0)
|
||||
{
|
||||
before = node;
|
||||
node = node->right;
|
||||
}
|
||||
else /* cmp > 0 */
|
||||
{
|
||||
after = node;
|
||||
node = node->left;
|
||||
}
|
||||
if (node == NULL)
|
||||
{
|
||||
if (out_before)
|
||||
*out_before = NODE_TO_POINTER (before);
|
||||
if (out_after)
|
||||
*out_after = NODE_TO_POINTER (after);
|
||||
return NULL;;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_before)
|
||||
*out_before = NODE_TO_POINTER (gtk_css_rb_node_get_previous (node));
|
||||
if (out_after)
|
||||
*out_after = NODE_TO_POINTER (gtk_css_rb_node_get_next (node));
|
||||
|
||||
return NODE_TO_POINTER (node);
|
||||
}
|
89
gtk/gtkcssrbtreeprivate.h
Normal file
89
gtk/gtkcssrbtreeprivate.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* gtkrb_tree.h
|
||||
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* A Red-Black Tree implementation used specifically by GtkTreeView.
|
||||
*/
|
||||
#ifndef __GTK_CSS_RB_TREE_H__
|
||||
#define __GTK_CSS_RB_TREE_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
typedef struct _GtkCssRbTree GtkCssRbTree;
|
||||
|
||||
typedef void (* GtkCssRbTreeAugmentFunc) (GtkCssRbTree *tree,
|
||||
gpointer node_augment,
|
||||
gpointer node,
|
||||
gpointer left,
|
||||
gpointer right);
|
||||
typedef int (* GtkCssRbTreeFindFunc) (GtkCssRbTree *tree,
|
||||
gpointer node,
|
||||
gpointer user_data);
|
||||
|
||||
GtkCssRbTree * gtk_css_rb_tree_new_for_size (gsize element_size,
|
||||
gsize augment_size,
|
||||
GtkCssRbTreeAugmentFunc augment_func,
|
||||
GDestroyNotify clear_func,
|
||||
GDestroyNotify clear_augment_func);
|
||||
#define gtk_css_rb_tree_new(type, augment_type, augment_func, clear_func, clear_augment_func) \
|
||||
gtk_css_rb_tree_new_for_size (sizeof (type), sizeof (augment_type), (augment_func), (clear_func), (clear_augment_func))
|
||||
|
||||
GtkCssRbTree * gtk_css_rb_tree_ref (GtkCssRbTree *tree);
|
||||
void gtk_css_rb_tree_unref (GtkCssRbTree *tree);
|
||||
|
||||
gpointer gtk_css_rb_tree_get_first (GtkCssRbTree *tree);
|
||||
gpointer gtk_css_rb_tree_get_last (GtkCssRbTree *tree);
|
||||
gpointer gtk_css_rb_tree_get_previous (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
gpointer gtk_css_rb_tree_get_next (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
|
||||
gpointer gtk_css_rb_tree_get_root (GtkCssRbTree *tree);
|
||||
gpointer gtk_css_rb_tree_get_parent (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
gpointer gtk_css_rb_tree_get_left (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
gpointer gtk_css_rb_tree_get_right (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
gpointer gtk_css_rb_tree_get_augment (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
|
||||
void gtk_css_rb_tree_mark_dirty (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
|
||||
gpointer gtk_css_rb_tree_insert_before (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
gpointer gtk_css_rb_tree_insert_after (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
void gtk_css_rb_tree_remove (GtkCssRbTree *tree,
|
||||
gpointer node);
|
||||
|
||||
gpointer gtk_css_rb_tree_find (GtkCssRbTree *tree,
|
||||
gpointer *out_before,
|
||||
gpointer *out_after,
|
||||
GtkCssRbTreeFindFunc find_func,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
#endif /* __GTK_CSS_RB_TREE_H__ */
|
@@ -205,6 +205,59 @@ _gtk_css_background_repeat_value_try_parse (GtkCssParser *parser)
|
||||
return _gtk_css_background_repeat_value_new (x, y);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_background_repeat_value_from_token (const GtkCssToken *token,
|
||||
GtkCssRepeatStyle *style)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, "repeat"))
|
||||
*style = GTK_CSS_REPEAT_STYLE_REPEAT;
|
||||
else if (gtk_css_token_is_ident (token, "space"))
|
||||
*style = GTK_CSS_REPEAT_STYLE_SPACE;
|
||||
else if (gtk_css_token_is_ident (token, "round"))
|
||||
*style = GTK_CSS_REPEAT_STYLE_ROUND;
|
||||
else if (gtk_css_token_is_ident (token, "no-repeat"))
|
||||
*style = GTK_CSS_REPEAT_STYLE_NO_REPEAT;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_background_repeat_value_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssRepeatStyle x, y;
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "repeat-x"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return _gtk_css_background_repeat_value_new (GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT);
|
||||
}
|
||||
if (gtk_css_token_is_ident (token, "repeat-y"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return _gtk_css_background_repeat_value_new (GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT);
|
||||
}
|
||||
|
||||
if (!gtk_css_background_repeat_value_from_token (token, &x))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Not a repeat-style");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_background_repeat_value_from_token (token, &y))
|
||||
gtk_css_token_source_consume_token (source);
|
||||
else
|
||||
y = x;
|
||||
|
||||
return _gtk_css_background_repeat_value_new (x, y);
|
||||
}
|
||||
|
||||
GtkCssRepeatStyle
|
||||
_gtk_css_background_repeat_value_get_x (const GtkCssValue *repeat)
|
||||
{
|
||||
@@ -294,6 +347,48 @@ _gtk_css_border_repeat_value_try_parse (GtkCssParser *parser)
|
||||
return _gtk_css_border_repeat_value_new (x, y);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_border_repeat_value_from_token (const GtkCssToken *token,
|
||||
GtkCssRepeatStyle *style)
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, "repeat"))
|
||||
*style = GTK_CSS_REPEAT_STYLE_REPEAT;
|
||||
else if (gtk_css_token_is_ident (token, "space"))
|
||||
*style = GTK_CSS_REPEAT_STYLE_SPACE;
|
||||
else if (gtk_css_token_is_ident (token, "round"))
|
||||
*style = GTK_CSS_REPEAT_STYLE_ROUND;
|
||||
else if (gtk_css_token_is_ident (token, "stretch"))
|
||||
*style = GTK_CSS_REPEAT_STYLE_STRETCH;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_border_repeat_value_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssRepeatStyle x, y;
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_border_repeat_value_from_token (token, &x))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Not a repeat style");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_border_repeat_value_from_token (token, &y))
|
||||
gtk_css_token_source_consume_token (source);
|
||||
else
|
||||
y = x;
|
||||
|
||||
return _gtk_css_border_repeat_value_new (x, y);
|
||||
}
|
||||
|
||||
GtkCssRepeatStyle
|
||||
_gtk_css_border_repeat_value_get_x (const GtkCssValue *repeat)
|
||||
{
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_CSS_REPEAT_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -36,12 +37,14 @@ typedef enum {
|
||||
GtkCssValue * _gtk_css_background_repeat_value_new (GtkCssRepeatStyle x,
|
||||
GtkCssRepeatStyle y);
|
||||
GtkCssValue * _gtk_css_background_repeat_value_try_parse (GtkCssParser *parser);
|
||||
GtkCssValue * gtk_css_background_repeat_value_token_parse (GtkCssTokenSource *source);
|
||||
GtkCssRepeatStyle _gtk_css_background_repeat_value_get_x (const GtkCssValue *repeat);
|
||||
GtkCssRepeatStyle _gtk_css_background_repeat_value_get_y (const GtkCssValue *repeat);
|
||||
|
||||
GtkCssValue * _gtk_css_border_repeat_value_new (GtkCssRepeatStyle x,
|
||||
GtkCssRepeatStyle y);
|
||||
GtkCssValue * _gtk_css_border_repeat_value_try_parse (GtkCssParser *parser);
|
||||
GtkCssValue * gtk_css_border_repeat_value_token_parse (GtkCssTokenSource *source);
|
||||
GtkCssRepeatStyle _gtk_css_border_repeat_value_get_x (const GtkCssValue *repeat);
|
||||
GtkCssRepeatStyle _gtk_css_border_repeat_value_get_y (const GtkCssValue *repeat);
|
||||
|
||||
|
355
gtk/gtkcssrule.c
Normal file
355
gtk/gtkcssrule.c
Normal file
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssruleprivate.h"
|
||||
|
||||
#include "gtkcssdefinecolorruleprivate.h"
|
||||
#include "gtkcssimportruleprivate.h"
|
||||
#include "gtkcsskeyframesruleprivate.h"
|
||||
#include "gtkcssstylesheetprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CSS_TEXT,
|
||||
PROP_PARENT_RULE,
|
||||
PROP_PARENT_STYLESHEET,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
typedef struct _GtkCssRulePrivate GtkCssRulePrivate;
|
||||
struct _GtkCssRulePrivate {
|
||||
GtkCssRule *parent_rule;
|
||||
GtkCssStyleSheet *parent_style_sheet;
|
||||
};
|
||||
|
||||
typedef struct _GtkCssTokenSourceAt GtkCssTokenSourceAt;
|
||||
struct _GtkCssTokenSourceAt {
|
||||
GtkCssTokenSource parent;
|
||||
GtkCssTokenSource *source;
|
||||
GSList *blocks;
|
||||
guint done :1;
|
||||
};
|
||||
|
||||
static GParamSpec *rule_props[NUM_PROPERTIES] = { NULL, };
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkCssRule, gtk_css_rule, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_css_token_source_at_finalize (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourceAt *at = (GtkCssTokenSourceAt *) source;
|
||||
|
||||
g_slist_free (at->blocks);
|
||||
|
||||
gtk_css_token_source_unref (at->source);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_token_source_at_consume_token (GtkCssTokenSource *source,
|
||||
GObject *consumer)
|
||||
{
|
||||
GtkCssTokenSourceAt *at = (GtkCssTokenSourceAt *) source;
|
||||
const GtkCssToken *token;
|
||||
|
||||
if (at->done)
|
||||
return;
|
||||
|
||||
token = gtk_css_token_source_peek_token (at->source);
|
||||
switch (token->type)
|
||||
{
|
||||
case GTK_CSS_TOKEN_FUNCTION:
|
||||
case GTK_CSS_TOKEN_OPEN_PARENS:
|
||||
at->blocks = g_slist_prepend (at->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_PARENS));
|
||||
break;
|
||||
case GTK_CSS_TOKEN_OPEN_SQUARE:
|
||||
at->blocks = g_slist_prepend (at->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_SQUARE));
|
||||
break;
|
||||
case GTK_CSS_TOKEN_OPEN_CURLY:
|
||||
at->blocks = g_slist_prepend (at->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_CURLY));
|
||||
break;
|
||||
case GTK_CSS_TOKEN_CLOSE_PARENS:
|
||||
case GTK_CSS_TOKEN_CLOSE_SQUARE:
|
||||
case GTK_CSS_TOKEN_CLOSE_CURLY:
|
||||
if (at->blocks && GPOINTER_TO_UINT (at->blocks->data) == token->type)
|
||||
{
|
||||
at->blocks = g_slist_remove (at->blocks, at->blocks->data);
|
||||
if (token->type == GTK_CSS_TOKEN_CLOSE_CURLY && at->blocks == NULL)
|
||||
at->done = TRUE;
|
||||
}
|
||||
break;
|
||||
case GTK_CSS_TOKEN_SEMICOLON:
|
||||
if (at->blocks == NULL)
|
||||
at->done = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token_as (at->source, consumer);
|
||||
}
|
||||
|
||||
const GtkCssToken *
|
||||
gtk_css_token_source_at_peek_token (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourceAt *at = (GtkCssTokenSourceAt *) source;
|
||||
static GtkCssToken eof_token = { GTK_CSS_TOKEN_EOF };
|
||||
|
||||
if (at->done)
|
||||
return &eof_token;
|
||||
|
||||
return gtk_css_token_source_peek_token (at->source);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_token_source_at_error (GtkCssTokenSource *source,
|
||||
const GError *error)
|
||||
{
|
||||
GtkCssTokenSourceAt *at = (GtkCssTokenSourceAt *) source;
|
||||
|
||||
gtk_css_token_source_emit_error (at->source, error);
|
||||
}
|
||||
|
||||
static GFile *
|
||||
gtk_css_token_source_at_get_location (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourceAt *at = (GtkCssTokenSourceAt *) source;
|
||||
|
||||
return gtk_css_token_source_get_location (at->source);
|
||||
}
|
||||
|
||||
static const GtkCssTokenSourceClass GTK_CSS_TOKEN_SOURCE_AT = {
|
||||
gtk_css_token_source_at_finalize,
|
||||
gtk_css_token_source_at_consume_token,
|
||||
gtk_css_token_source_at_peek_token,
|
||||
gtk_css_token_source_at_error,
|
||||
gtk_css_token_source_at_get_location,
|
||||
};
|
||||
|
||||
static GtkCssTokenSource *
|
||||
gtk_css_token_source_new_at (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourceAt *at = gtk_css_token_source_new (GtkCssTokenSourceAt, >K_CSS_TOKEN_SOURCE_AT);
|
||||
|
||||
at->source = gtk_css_token_source_ref (source);
|
||||
gtk_css_token_source_set_consumer (&at->parent,
|
||||
gtk_css_token_source_get_consumer (source));
|
||||
|
||||
return &at->parent;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rule_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkCssRule *rule = GTK_CSS_RULE (gobject);
|
||||
GtkCssRulePrivate *priv = gtk_css_rule_get_instance_private (rule);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PARENT_RULE:
|
||||
priv->parent_rule = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_PARENT_STYLESHEET:
|
||||
priv->parent_style_sheet = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rule_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkCssRule *rule = GTK_CSS_RULE (gobject);
|
||||
GtkCssRulePrivate *priv = gtk_css_rule_get_instance_private (rule);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CSS_TEXT:
|
||||
g_value_take_string (value, gtk_css_rule_get_css_text (rule));
|
||||
break;
|
||||
|
||||
case PROP_PARENT_RULE:
|
||||
g_value_set_object (value, priv->parent_rule);
|
||||
break;
|
||||
|
||||
case PROP_PARENT_STYLESHEET:
|
||||
g_value_set_object (value, priv->parent_style_sheet);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rule_class_init (GtkCssRuleClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = gtk_css_rule_set_property;
|
||||
object_class->get_property = gtk_css_rule_get_property;
|
||||
|
||||
rule_props[PROP_CSS_TEXT] =
|
||||
g_param_spec_string ("css-text",
|
||||
P_("CSS text"),
|
||||
P_("Conversion this rule to text"),
|
||||
NULL,
|
||||
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
rule_props[PROP_PARENT_RULE] =
|
||||
g_param_spec_object ("parent-rule",
|
||||
P_("parent rule"),
|
||||
P_("The parent CSS rule if it exists"),
|
||||
GTK_TYPE_CSS_RULE,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY);
|
||||
rule_props[PROP_PARENT_STYLESHEET] =
|
||||
g_param_spec_object ("parent-stylesheet",
|
||||
P_("parent style sheet"),
|
||||
P_("The parent style sheet that contains this rule"),
|
||||
GTK_TYPE_CSS_STYLE_SHEET,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, rule_props);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rule_init (GtkCssRule *rule)
|
||||
{
|
||||
}
|
||||
|
||||
GtkCssRule *
|
||||
gtk_css_rule_new_from_at_rule (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
GtkCssTokenSource *at_source;
|
||||
const GtkCssToken *token;
|
||||
GtkCssRule *rule;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
g_return_val_if_fail (parent_rule == NULL || GTK_IS_CSS_RULE (parent_rule), NULL);
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (parent_style_sheet), NULL);
|
||||
|
||||
at_source = gtk_css_token_source_new_at (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (at_source);
|
||||
if (token->type != GTK_CSS_TOKEN_AT_KEYWORD)
|
||||
{
|
||||
gtk_css_token_source_error (at_source, "Expected an '@'");
|
||||
gtk_css_token_source_consume_all (at_source);
|
||||
gtk_css_token_source_unref (at_source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (g_ascii_strcasecmp (token->string.string, "import") == 0)
|
||||
{
|
||||
rule = gtk_css_import_rule_new_parse (at_source, parent_rule, parent_style_sheet);
|
||||
}
|
||||
else if (g_ascii_strcasecmp (token->string.string, "define-color") == 0)
|
||||
{
|
||||
rule = gtk_css_define_color_rule_new_parse (at_source, parent_rule, parent_style_sheet);
|
||||
}
|
||||
else if (g_ascii_strcasecmp (token->string.string, "keyframes") == 0)
|
||||
{
|
||||
rule = gtk_css_keyframes_rule_new_parse (at_source, parent_rule, parent_style_sheet);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_unknown (at_source, "Unknown rule @%s", token->string.string);
|
||||
gtk_css_token_source_consume_all (at_source);
|
||||
rule = NULL;
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (at_source);
|
||||
if (rule != NULL && !gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
|
||||
{
|
||||
gtk_css_token_source_unknown (at_source, "Junk at end of @-rule");
|
||||
gtk_css_token_source_consume_all (at_source);
|
||||
g_object_unref (rule);
|
||||
rule = NULL;
|
||||
}
|
||||
gtk_css_token_source_unref (at_source);
|
||||
|
||||
return rule;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_rule_print_css_text (GtkCssRule *rule,
|
||||
GString *string)
|
||||
{
|
||||
GtkCssRuleClass *klass;
|
||||
|
||||
g_return_if_fail (GTK_IS_CSS_RULE (rule));
|
||||
g_return_if_fail (string != NULL);
|
||||
|
||||
klass = GTK_CSS_RULE_GET_CLASS (rule);
|
||||
|
||||
klass->get_css_text (rule, string);
|
||||
}
|
||||
|
||||
char *
|
||||
gtk_css_rule_get_css_text (GtkCssRule *rule)
|
||||
{
|
||||
GString *string;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_RULE (rule), NULL);
|
||||
|
||||
string = g_string_new (NULL);
|
||||
|
||||
gtk_css_rule_print_css_text (rule, string);
|
||||
|
||||
return g_string_free (string, FALSE);
|
||||
}
|
||||
|
||||
GtkCssRule *
|
||||
gtk_css_rule_get_parent_rule (GtkCssRule *rule)
|
||||
{
|
||||
GtkCssRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_RULE (rule), NULL);
|
||||
|
||||
priv = gtk_css_rule_get_instance_private (rule);
|
||||
|
||||
return priv->parent_rule;
|
||||
}
|
||||
|
||||
GtkCssStyleSheet *
|
||||
gtk_css_rule_get_parent_style_sheet (GtkCssRule *rule)
|
||||
{
|
||||
GtkCssRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_RULE (rule), NULL);
|
||||
|
||||
priv = gtk_css_rule_get_instance_private (rule);
|
||||
|
||||
return priv->parent_style_sheet;
|
||||
}
|
168
gtk/gtkcssrulelist.c
Normal file
168
gtk/gtkcssrulelist.c
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssrulelistprivate.h"
|
||||
#include "gtkcssstyleruleprivate.h"
|
||||
#include "gtkcssstylesheetprivate.h"
|
||||
|
||||
typedef struct _GtkCssRuleListPrivate GtkCssRuleListPrivate;
|
||||
struct _GtkCssRuleListPrivate {
|
||||
GPtrArray *items;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssRuleList, gtk_css_rule_list, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_css_rule_list_finalize (GObject *object)
|
||||
{
|
||||
GtkCssRuleList *rule_list = GTK_CSS_RULE_LIST (object);
|
||||
GtkCssRuleListPrivate *priv = gtk_css_rule_list_get_instance_private (rule_list);
|
||||
|
||||
g_ptr_array_unref (priv->items);
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_rule_list_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rule_list_class_init (GtkCssRuleListClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_rule_list_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_rule_list_init (GtkCssRuleList *rule_list)
|
||||
{
|
||||
GtkCssRuleListPrivate *priv = gtk_css_rule_list_get_instance_private (rule_list);
|
||||
|
||||
priv->items = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
}
|
||||
|
||||
GtkCssRuleList *
|
||||
gtk_css_rule_list_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_CSS_RULE_LIST, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_rule_list_parse (GtkCssRuleList *rule_list,
|
||||
GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
GtkCssRule *rule;
|
||||
const GtkCssToken *token;
|
||||
|
||||
g_return_if_fail (GTK_IS_CSS_RULE_LIST (rule_list));
|
||||
g_return_if_fail (source != NULL);
|
||||
g_return_if_fail (parent_rule == NULL || GTK_IS_CSS_RULE (parent_rule));
|
||||
g_return_if_fail (GTK_IS_CSS_STYLE_SHEET (parent_style_sheet));
|
||||
|
||||
gtk_css_token_source_set_consumer (source, G_OBJECT (rule_list));
|
||||
|
||||
for (token = gtk_css_token_source_get_token (source);
|
||||
token->type != GTK_CSS_TOKEN_EOF;
|
||||
token = gtk_css_token_source_get_token (source))
|
||||
{
|
||||
switch (token->type)
|
||||
{
|
||||
case GTK_CSS_TOKEN_WHITESPACE:
|
||||
gtk_css_token_source_consume_token (source);
|
||||
break;
|
||||
|
||||
case GTK_CSS_TOKEN_AT_KEYWORD:
|
||||
rule = gtk_css_rule_new_from_at_rule (source, parent_rule, parent_style_sheet);
|
||||
if (rule)
|
||||
gtk_css_rule_list_append (rule_list, rule);
|
||||
break;
|
||||
|
||||
case GTK_CSS_TOKEN_CDO:
|
||||
case GTK_CSS_TOKEN_CDC:
|
||||
if (parent_rule == NULL)
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
break;
|
||||
}
|
||||
/* else fall through */
|
||||
default:
|
||||
rule = gtk_css_style_rule_new_parse (source, parent_rule, parent_style_sheet);
|
||||
if (rule)
|
||||
gtk_css_rule_list_append (rule_list, rule);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_rule_list_insert (GtkCssRuleList *rule_list,
|
||||
gsize id,
|
||||
GtkCssRule *rule)
|
||||
{
|
||||
GtkCssRuleListPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_CSS_RULE_LIST (rule_list));
|
||||
g_return_if_fail (GTK_IS_CSS_RULE (rule));
|
||||
|
||||
priv = gtk_css_rule_list_get_instance_private (rule_list);
|
||||
|
||||
g_ptr_array_insert (priv->items, id, g_object_ref (rule));
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_rule_list_append (GtkCssRuleList *rule_list,
|
||||
GtkCssRule *rule)
|
||||
{
|
||||
GtkCssRuleListPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_CSS_RULE_LIST (rule_list));
|
||||
g_return_if_fail (GTK_IS_CSS_RULE (rule));
|
||||
|
||||
priv = gtk_css_rule_list_get_instance_private (rule_list);
|
||||
|
||||
g_ptr_array_add (priv->items, g_object_ref (rule));
|
||||
}
|
||||
|
||||
GtkCssRule *
|
||||
gtk_css_rule_list_get_item (GtkCssRuleList *rule_list,
|
||||
gsize id)
|
||||
{
|
||||
GtkCssRuleListPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_RULE_LIST (rule_list), NULL);
|
||||
|
||||
priv = gtk_css_rule_list_get_instance_private (rule_list);
|
||||
g_return_val_if_fail (id < priv->items->len, NULL);
|
||||
|
||||
return g_ptr_array_index (priv->items, id);
|
||||
}
|
||||
|
||||
gsize
|
||||
gtk_css_rule_list_get_length (GtkCssRuleList *rule_list)
|
||||
{
|
||||
GtkCssRuleListPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_RULE_LIST (rule_list), 0);
|
||||
|
||||
priv = gtk_css_rule_list_get_instance_private (rule_list);
|
||||
|
||||
return priv->items->len;
|
||||
}
|
69
gtk/gtkcssrulelistprivate.h
Normal file
69
gtk/gtkcssrulelistprivate.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_RULE_LIST_PRIVATE_H__
|
||||
#define __GTK_CSS_RULE_LIST_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssruleprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_RULE_LIST (gtk_css_rule_list_get_type ())
|
||||
#define GTK_CSS_RULE_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_RULE_LIST, GtkCssRuleList))
|
||||
#define GTK_CSS_RULE_LIST_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_RULE_LIST, GtkCssRuleListClass))
|
||||
#define GTK_IS_CSS_RULE_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_RULE_LIST))
|
||||
#define GTK_IS_CSS_RULE_LIST_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_RULE_LIST))
|
||||
#define GTK_CSS_RULE_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_RULE_LIST, GtkCssRuleListClass))
|
||||
|
||||
typedef struct _GtkCssRuleList GtkCssRuleList;
|
||||
typedef struct _GtkCssRuleListClass GtkCssRuleListClass;
|
||||
|
||||
struct _GtkCssRuleList
|
||||
{
|
||||
GObject parent;
|
||||
};
|
||||
|
||||
struct _GtkCssRuleListClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_rule_list_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssRuleList * gtk_css_rule_list_new (void);
|
||||
|
||||
void gtk_css_rule_list_parse (GtkCssRuleList *rule_list,
|
||||
GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet);
|
||||
void gtk_css_rule_list_insert (GtkCssRuleList *rule_list,
|
||||
gsize id,
|
||||
GtkCssRule *rule);
|
||||
void gtk_css_rule_list_append (GtkCssRuleList *rule_list,
|
||||
GtkCssRule *rule);
|
||||
|
||||
/* GtkCSSRule DOM */
|
||||
GtkCssRule * gtk_css_rule_list_get_item (GtkCssRuleList *rule_list,
|
||||
gsize id);
|
||||
gsize gtk_css_rule_list_get_length (GtkCssRuleList *rule_list);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_RULE_LIST_PRIVATE_H__ */
|
70
gtk/gtkcssruleprivate.h
Normal file
70
gtk/gtkcssruleprivate.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_RULE_PRIVATE_H__
|
||||
#define __GTK_CSS_RULE_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcsstokensourceprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_RULE (gtk_css_rule_get_type ())
|
||||
#define GTK_CSS_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_RULE, GtkCssRule))
|
||||
#define GTK_CSS_RULE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_RULE, GtkCssRuleClass))
|
||||
#define GTK_IS_CSS_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_RULE))
|
||||
#define GTK_IS_CSS_RULE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_RULE))
|
||||
#define GTK_CSS_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_RULE, GtkCssRuleClass))
|
||||
|
||||
/* forward declaration */
|
||||
typedef struct _GtkCssStyleSheet GtkCssStyleSheet;
|
||||
|
||||
typedef struct _GtkCssRule GtkCssRule;
|
||||
typedef struct _GtkCssRuleClass GtkCssRuleClass;
|
||||
|
||||
struct _GtkCssRule
|
||||
{
|
||||
GObject parent;
|
||||
};
|
||||
|
||||
struct _GtkCssRuleClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* gets the cssText for this rule */
|
||||
void (* get_css_text) (GtkCssRule *rule,
|
||||
GString *string);
|
||||
};
|
||||
|
||||
GType gtk_css_rule_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssRule * gtk_css_rule_new_from_at_rule (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet);
|
||||
|
||||
void gtk_css_rule_print_css_text (GtkCssRule *rule,
|
||||
GString *string);
|
||||
char * gtk_css_rule_get_css_text (GtkCssRule *rule);
|
||||
|
||||
GtkCssRule * gtk_css_rule_get_parent_rule (GtkCssRule *rule);
|
||||
GtkCssStyleSheet * gtk_css_rule_get_parent_style_sheet (GtkCssRule *rule);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_RULE_PRIVATE_H__ */
|
@@ -25,6 +25,8 @@
|
||||
#include "gtkcssprovider.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1500
|
||||
# include <intrin.h>
|
||||
#endif
|
||||
@@ -1102,42 +1104,42 @@ parse_selector_pseudo_class_nth_child (GtkCssParser *parser,
|
||||
return selector;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
gboolean deprecated;
|
||||
GtkStateFlags state_flag;
|
||||
PositionType position_type;
|
||||
int position_a;
|
||||
int position_b;
|
||||
} pseudo_classes[] = {
|
||||
{ "first-child", 0, 0, POSITION_FORWARD, 0, 1 },
|
||||
{ "last-child", 0, 0, POSITION_BACKWARD, 0, 1 },
|
||||
{ "only-child", 0, 0, POSITION_ONLY, 0, 0 },
|
||||
{ "sorted", 1, 0, POSITION_SORTED, 0, 0 },
|
||||
{ "active", 0, GTK_STATE_FLAG_ACTIVE, },
|
||||
{ "prelight", 1, GTK_STATE_FLAG_PRELIGHT, },
|
||||
{ "hover", 0, GTK_STATE_FLAG_PRELIGHT, },
|
||||
{ "selected", 0, GTK_STATE_FLAG_SELECTED, },
|
||||
{ "insensitive", 1, GTK_STATE_FLAG_INSENSITIVE, },
|
||||
{ "disabled", 0, GTK_STATE_FLAG_INSENSITIVE, },
|
||||
{ "inconsistent", 1, GTK_STATE_FLAG_INCONSISTENT, },
|
||||
{ "indeterminate", 0, GTK_STATE_FLAG_INCONSISTENT, },
|
||||
{ "focused", 1, GTK_STATE_FLAG_FOCUSED, },
|
||||
{ "focus", 0, GTK_STATE_FLAG_FOCUSED, },
|
||||
{ "backdrop", 0, GTK_STATE_FLAG_BACKDROP, },
|
||||
{ "dir(ltr)", 0, GTK_STATE_FLAG_DIR_LTR, },
|
||||
{ "dir(rtl)", 0, GTK_STATE_FLAG_DIR_RTL, },
|
||||
{ "link", 0, GTK_STATE_FLAG_LINK, },
|
||||
{ "visited", 0, GTK_STATE_FLAG_VISITED, },
|
||||
{ "checked", 0, GTK_STATE_FLAG_CHECKED, },
|
||||
{ "drop(active)", 0, GTK_STATE_FLAG_DROP_ACTIVE, }
|
||||
};
|
||||
|
||||
static GtkCssSelector *
|
||||
parse_selector_pseudo_class (GtkCssParser *parser,
|
||||
GtkCssSelector *selector,
|
||||
gboolean negate)
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
gboolean deprecated;
|
||||
GtkStateFlags state_flag;
|
||||
PositionType position_type;
|
||||
int position_a;
|
||||
int position_b;
|
||||
} pseudo_classes[] = {
|
||||
{ "first-child", 0, 0, POSITION_FORWARD, 0, 1 },
|
||||
{ "last-child", 0, 0, POSITION_BACKWARD, 0, 1 },
|
||||
{ "only-child", 0, 0, POSITION_ONLY, 0, 0 },
|
||||
{ "sorted", 1, 0, POSITION_SORTED, 0, 0 },
|
||||
{ "active", 0, GTK_STATE_FLAG_ACTIVE, },
|
||||
{ "prelight", 1, GTK_STATE_FLAG_PRELIGHT, },
|
||||
{ "hover", 0, GTK_STATE_FLAG_PRELIGHT, },
|
||||
{ "selected", 0, GTK_STATE_FLAG_SELECTED, },
|
||||
{ "insensitive", 1, GTK_STATE_FLAG_INSENSITIVE, },
|
||||
{ "disabled", 0, GTK_STATE_FLAG_INSENSITIVE, },
|
||||
{ "inconsistent", 1, GTK_STATE_FLAG_INCONSISTENT, },
|
||||
{ "indeterminate", 0, GTK_STATE_FLAG_INCONSISTENT, },
|
||||
{ "focused", 1, GTK_STATE_FLAG_FOCUSED, },
|
||||
{ "focus", 0, GTK_STATE_FLAG_FOCUSED, },
|
||||
{ "backdrop", 0, GTK_STATE_FLAG_BACKDROP, },
|
||||
{ "dir(ltr)", 0, GTK_STATE_FLAG_DIR_LTR, },
|
||||
{ "dir(rtl)", 0, GTK_STATE_FLAG_DIR_RTL, },
|
||||
{ "link", 0, GTK_STATE_FLAG_LINK, },
|
||||
{ "visited", 0, GTK_STATE_FLAG_VISITED, },
|
||||
{ "checked", 0, GTK_STATE_FLAG_CHECKED, },
|
||||
{ "drop(active)", 0, GTK_STATE_FLAG_DROP_ACTIVE, }
|
||||
|
||||
};
|
||||
guint i;
|
||||
|
||||
if (_gtk_css_parser_try (parser, "nth-child", FALSE))
|
||||
@@ -1305,6 +1307,660 @@ _gtk_css_selector_parse (GtkCssParser *parser)
|
||||
return selector;
|
||||
}
|
||||
|
||||
GtkCssSelector *
|
||||
token_parse_selector_class (GtkCssTokenSource *source,
|
||||
GtkCssSelector *selector,
|
||||
gboolean negate)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
for (token = gtk_css_token_source_peek_token (source);
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_COMMENT);
|
||||
token = gtk_css_token_source_peek_token (source))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
selector = gtk_css_selector_new (negate ? >K_CSS_SELECTOR_NOT_CLASS
|
||||
: >K_CSS_SELECTOR_CLASS,
|
||||
selector);
|
||||
selector->style_class.style_class = g_quark_from_string (token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return selector;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "No class name after '.' in selector");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
string_has_number (const char *string,
|
||||
const char *prefix,
|
||||
int *number)
|
||||
{
|
||||
gsize len = strlen (prefix);
|
||||
char *end;
|
||||
|
||||
if (g_ascii_strncasecmp (string, prefix, len) != 0)
|
||||
return FALSE;
|
||||
|
||||
errno = 0;
|
||||
*number = strtoul (string + len, &end, 10);
|
||||
if (*end != '\0' || errno != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_plus_b (GtkCssTokenSource *source,
|
||||
gboolean negate,
|
||||
gint *b)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
gboolean has_seen_sign;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
|
||||
if (negate)
|
||||
{
|
||||
has_seen_sign = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gtk_css_token_is_delim (token, '+'))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
has_seen_sign = TRUE;
|
||||
}
|
||||
else if (gtk_css_token_is_delim (token, '-'))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
negate = TRUE;
|
||||
has_seen_sign = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!has_seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER))
|
||||
{
|
||||
*b = token->number.number;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
else if (has_seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER))
|
||||
{
|
||||
*b = token->number.number;
|
||||
if (negate)
|
||||
*b = - *b;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
else if (!has_seen_sign)
|
||||
{
|
||||
*b = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gtk_css_token_source_error (source, "Not a valid an+b type");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
parse_n_plus_b (GtkCssTokenSource *source,
|
||||
gint before,
|
||||
gint *a,
|
||||
gint *b)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
|
||||
if (gtk_css_token_is_ident (token, "n"))
|
||||
{
|
||||
*a = before;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return parse_plus_b (source, FALSE, b);
|
||||
}
|
||||
else if (gtk_css_token_is_ident (token, "n-"))
|
||||
{
|
||||
*a = before;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return parse_plus_b (source, TRUE, b);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) &&
|
||||
string_has_number (token->string.string, "n-", b))
|
||||
{
|
||||
*a = before;
|
||||
*b = -*b;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*b = before;
|
||||
*a = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gtk_css_token_source_error (source, "Not a valid an+b type");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
parse_a_n_plus_b (GtkCssTokenSource *source,
|
||||
gint seen_sign,
|
||||
gint *a,
|
||||
gint *b)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
|
||||
if (!seen_sign && gtk_css_token_is_ident (token, "even"))
|
||||
{
|
||||
*a = 2;
|
||||
*b = 0;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
else if (!seen_sign && gtk_css_token_is_ident (token, "odd"))
|
||||
{
|
||||
*a = 2;
|
||||
*b = 1;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
else if (!seen_sign && gtk_css_token_is_delim (token, '+'))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return parse_a_n_plus_b (source, 1, a, b);
|
||||
}
|
||||
else if (!seen_sign && gtk_css_token_is_delim (token, '-'))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return parse_a_n_plus_b (source, -1, a, b);
|
||||
}
|
||||
else if ((!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER)) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER))
|
||||
{
|
||||
int x = token->number.number * (seen_sign ? seen_sign : 1);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
return parse_n_plus_b (source, x , a, b);
|
||||
}
|
||||
else if (((!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION)) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION)) &&
|
||||
g_ascii_strcasecmp (token->dimension.dimension, "n") == 0)
|
||||
{
|
||||
*a = token->dimension.value * (seen_sign ? seen_sign : 1);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return parse_plus_b (source, FALSE, b);
|
||||
}
|
||||
else if (((!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION)) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION)) &&
|
||||
g_ascii_strcasecmp (token->dimension.dimension, "n-") == 0)
|
||||
{
|
||||
*a = token->dimension.value * (seen_sign ? seen_sign : 1);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return parse_plus_b (source, TRUE, b);
|
||||
}
|
||||
else if (((!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION)) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION)) &&
|
||||
string_has_number (token->dimension.dimension, "n-", b))
|
||||
{
|
||||
*a = token->dimension.value * (seen_sign ? seen_sign : 1);
|
||||
*b = -*b;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
else if (!seen_sign && gtk_css_token_is_ident (token, "-n"))
|
||||
{
|
||||
*a = -1;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return parse_plus_b (source, FALSE, b);
|
||||
}
|
||||
else if (!seen_sign && gtk_css_token_is_ident (token, "-n-"))
|
||||
{
|
||||
*a = -1;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return parse_plus_b (source, TRUE, b);
|
||||
}
|
||||
else if (!seen_sign &&
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) &&
|
||||
string_has_number (token->string.string, "-n-", b))
|
||||
{
|
||||
*a = -1;
|
||||
*b = -*b;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
else if (gtk_css_token_is_ident (token, "n") ||
|
||||
gtk_css_token_is_ident (token, "n-"))
|
||||
{
|
||||
return parse_n_plus_b (source, seen_sign ? seen_sign : 1, a, b);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) &&
|
||||
string_has_number (token->string.string, "n-", b))
|
||||
{
|
||||
*a = seen_sign ? seen_sign : 1;
|
||||
*b = -*b;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
else if (!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) &&
|
||||
string_has_number (token->string.string, "-n-", b))
|
||||
{
|
||||
*a = -1;
|
||||
*b = -*b;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gtk_css_token_source_error (source, "Not a valid an+b type");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GtkCssSelector *
|
||||
token_parse_selector_pseudo_class (GtkCssTokenSource *source,
|
||||
GtkCssSelector *selector,
|
||||
gboolean negate)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
for (token = gtk_css_token_source_peek_token (source);
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_COMMENT);
|
||||
token = gtk_css_token_source_peek_token (source))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (pseudo_classes); i++)
|
||||
{
|
||||
if (g_ascii_strcasecmp (pseudo_classes[i].name, token->string.string) == 0)
|
||||
{
|
||||
if (pseudo_classes[i].state_flag)
|
||||
{
|
||||
selector = gtk_css_selector_new (negate ? >K_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
|
||||
: >K_CSS_SELECTOR_PSEUDOCLASS_STATE,
|
||||
selector);
|
||||
selector->state.state = pseudo_classes[i].state_flag;
|
||||
if (pseudo_classes[i].deprecated)
|
||||
{
|
||||
if (pseudo_classes[i + 1].state_flag == pseudo_classes[i].state_flag)
|
||||
gtk_css_token_source_deprecated (source,
|
||||
"The :%s pseudo-class is deprecated. Use :%s instead.",
|
||||
pseudo_classes[i].name,
|
||||
pseudo_classes[i + 1].name);
|
||||
else
|
||||
gtk_css_token_source_deprecated (source,
|
||||
"The :%s pseudo-class is deprecated.",
|
||||
pseudo_classes[i].name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
selector = gtk_css_selector_new (negate ? >K_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
|
||||
: >K_CSS_SELECTOR_PSEUDOCLASS_POSITION,
|
||||
selector);
|
||||
selector->position.type = pseudo_classes[i].position_type;
|
||||
selector->position.a = pseudo_classes[i].position_a;
|
||||
selector->position.b = pseudo_classes[i].position_b;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return selector;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_css_token_source_unknown (source, "Unknown name of pseudo-class");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
return NULL;
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_FUNCTION))
|
||||
{
|
||||
gint a, b;
|
||||
|
||||
if (gtk_css_token_is_function (token, "nth-child"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
if (parse_a_n_plus_b (source, 0, &a, &b))
|
||||
{
|
||||
selector = gtk_css_selector_new (negate ? >K_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
|
||||
: >K_CSS_SELECTOR_PSEUDOCLASS_POSITION,
|
||||
selector);
|
||||
selector->position.type = POSITION_FORWARD;
|
||||
selector->position.a = a;
|
||||
selector->position.b = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
return NULL;
|
||||
}
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected ')' at end of :nth-child()");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "nth-last-child"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
if (parse_a_n_plus_b (source, 0, &a, &b))
|
||||
{
|
||||
selector = gtk_css_selector_new (negate ? >K_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
|
||||
: >K_CSS_SELECTOR_PSEUDOCLASS_POSITION,
|
||||
selector);
|
||||
selector->position.type = POSITION_BACKWARD;
|
||||
selector->position.a = a;
|
||||
selector->position.b = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
return NULL;
|
||||
}
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected ')' at end of :nth-last-child()");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "not"))
|
||||
{
|
||||
if (negate)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Nesting of :not() not allowed");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
|
||||
if (gtk_css_token_is_delim (token, '*'))
|
||||
{
|
||||
selector = gtk_css_selector_new (>K_CSS_SELECTOR_NOT_ANY, selector);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
selector = gtk_css_selector_new (>K_CSS_SELECTOR_NOT_NAME, selector);
|
||||
selector->name.name = g_intern_string (token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID))
|
||||
{
|
||||
selector = gtk_css_selector_new (>K_CSS_SELECTOR_NOT_ID, selector);
|
||||
selector->id.name = g_intern_string (token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_delim (token, '.'))
|
||||
{
|
||||
selector = token_parse_selector_class (source, selector, TRUE);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_COLON))
|
||||
{
|
||||
selector = token_parse_selector_pseudo_class (source, selector, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Invalid contents of :not() selector");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
selector = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Invalid contents of :not() selector");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
selector = NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "dir"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "ltr"))
|
||||
{
|
||||
selector = gtk_css_selector_new (negate ? >K_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
|
||||
: >K_CSS_SELECTOR_PSEUDOCLASS_STATE,
|
||||
selector);
|
||||
selector->state.state = GTK_STATE_FLAG_DIR_LTR;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_ident (token, "rtl"))
|
||||
{
|
||||
selector = gtk_css_selector_new (negate ? >K_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
|
||||
: >K_CSS_SELECTOR_PSEUDOCLASS_STATE,
|
||||
selector);
|
||||
selector->state.state = GTK_STATE_FLAG_DIR_LTR;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected :dir(ltr) or :dir(rtl)");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
selector = NULL;
|
||||
return NULL;
|
||||
}
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected ')' at end of :dir()");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "drop"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "active"))
|
||||
{
|
||||
selector = gtk_css_selector_new (negate ? >K_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
|
||||
: >K_CSS_SELECTOR_PSEUDOCLASS_STATE,
|
||||
selector);
|
||||
selector->state.state = GTK_STATE_FLAG_DROP_ACTIVE;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected :drop(active)");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
selector = NULL;
|
||||
return NULL;
|
||||
}
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected ')' at end of :drop()");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_unknown (source, "Unknown pseudoclass");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Unknown pseudoclass");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
||||
GtkCssSelector *
|
||||
token_parse_simple_selector (GtkCssTokenSource *source,
|
||||
GtkCssSelector *selector)
|
||||
{
|
||||
gboolean parsed_something = FALSE;
|
||||
const GtkCssToken *token;
|
||||
|
||||
do {
|
||||
for (token = gtk_css_token_source_peek_token (source);
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_COMMENT);
|
||||
token = gtk_css_token_source_peek_token (source))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
if (!parsed_something && gtk_css_token_is_delim (token, '*'))
|
||||
{
|
||||
selector = gtk_css_selector_new (>K_CSS_SELECTOR_ANY, selector);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (!parsed_something && gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
selector = gtk_css_selector_new (>K_CSS_SELECTOR_NAME, selector);
|
||||
selector->name.name = g_intern_string (token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID))
|
||||
{
|
||||
selector = gtk_css_selector_new (>K_CSS_SELECTOR_ID, selector);
|
||||
selector->id.name = g_intern_string (token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_delim (token, '.'))
|
||||
{
|
||||
selector = token_parse_selector_class (source, selector, FALSE);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_COLON))
|
||||
{
|
||||
selector = token_parse_selector_pseudo_class (source, selector, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!parsed_something)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a valid selector");
|
||||
if (selector)
|
||||
_gtk_css_selector_free (selector);
|
||||
selector = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
parsed_something = TRUE;
|
||||
}
|
||||
while (TRUE);
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
||||
GtkCssSelector *
|
||||
gtk_css_selector_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssSelector *selector = NULL;
|
||||
const GtkCssToken *token;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
gboolean seen_whitespace = FALSE;
|
||||
|
||||
selector = token_parse_simple_selector (source, selector);
|
||||
if (selector == NULL)
|
||||
{
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (token = gtk_css_token_source_peek_token (source);
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_COMMENT) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_WHITESPACE);
|
||||
token = gtk_css_token_source_peek_token (source))
|
||||
{
|
||||
seen_whitespace |= gtk_css_token_is (token, GTK_CSS_TOKEN_WHITESPACE);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
if (gtk_css_token_is_delim (token, '+'))
|
||||
{
|
||||
selector = gtk_css_selector_new (>K_CSS_SELECTOR_ADJACENT, selector);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_delim (token, '~'))
|
||||
{
|
||||
selector = gtk_css_selector_new (>K_CSS_SELECTOR_SIBLING, selector);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_delim (token, '>'))
|
||||
{
|
||||
selector = gtk_css_selector_new (>K_CSS_SELECTOR_CHILD, selector);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (seen_whitespace)
|
||||
{
|
||||
selector = gtk_css_selector_new (>K_CSS_SELECTOR_DESCENDANT, selector);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a valid selector");
|
||||
_gtk_css_selector_free (selector);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
}
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_css_selector_free (GtkCssSelector *selector)
|
||||
{
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "gtk/gtkcssmatcherprivate.h"
|
||||
#include "gtk/gtkcssparserprivate.h"
|
||||
#include "gtk/gtkcsstokensourceprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -28,6 +29,7 @@ typedef struct _GtkCssSelectorTree GtkCssSelectorTree;
|
||||
typedef struct _GtkCssSelectorTreeBuilder GtkCssSelectorTreeBuilder;
|
||||
|
||||
GtkCssSelector * _gtk_css_selector_parse (GtkCssParser *parser);
|
||||
GtkCssSelector * gtk_css_selector_token_parse (GtkCssTokenSource *parser);
|
||||
void _gtk_css_selector_free (GtkCssSelector *selector);
|
||||
|
||||
char * _gtk_css_selector_to_string (const GtkCssSelector *selector);
|
||||
|
@@ -240,6 +240,46 @@ _gtk_css_shadows_value_parse (GtkCssParser *parser,
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_shadows_value_token_parse (GtkCssTokenSource *source,
|
||||
gboolean box_shadow_mode)
|
||||
{
|
||||
GtkCssValue *value, *result;
|
||||
const GtkCssToken *token;
|
||||
GPtrArray *values;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "none"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return _gtk_css_shadows_value_new_none ();
|
||||
}
|
||||
|
||||
values = g_ptr_array_new ();
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
value = gtk_css_shadow_value_token_parse (source, box_shadow_mode);
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
g_ptr_array_set_free_func (values, (GDestroyNotify) _gtk_css_value_unref);
|
||||
g_ptr_array_free (values, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_ptr_array_add (values, value);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COMMA))
|
||||
break;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
result = gtk_css_shadows_value_new ((GtkCssValue **) values->pdata, values->len);
|
||||
g_ptr_array_free (values, TRUE);
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_shadows_value_is_none (const GtkCssValue *shadows)
|
||||
{
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "gtktypes.h"
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
#include "gtkroundedboxprivate.h"
|
||||
|
||||
@@ -33,6 +34,8 @@ G_BEGIN_DECLS
|
||||
GtkCssValue * _gtk_css_shadows_value_new_none (void);
|
||||
GtkCssValue * _gtk_css_shadows_value_parse (GtkCssParser *parser,
|
||||
gboolean box_shadow_mode);
|
||||
GtkCssValue * gtk_css_shadows_value_token_parse (GtkCssTokenSource *source,
|
||||
gboolean box_shadow_mode);
|
||||
|
||||
gboolean _gtk_css_shadows_value_is_none (const GtkCssValue *shadows);
|
||||
|
||||
|
@@ -293,6 +293,104 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_shadow_value_token_parse (GtkCssTokenSource *source,
|
||||
gboolean box_shadow_mode)
|
||||
{
|
||||
enum {
|
||||
HOFFSET,
|
||||
VOFFSET,
|
||||
RADIUS,
|
||||
SPREAD,
|
||||
COLOR,
|
||||
N_VALUES
|
||||
};
|
||||
GtkCssValue *values[N_VALUES] = { NULL, };
|
||||
gboolean inset = FALSE;
|
||||
const GtkCssToken *token;
|
||||
guint i;
|
||||
|
||||
for (token = gtk_css_token_source_get_token (source);
|
||||
!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF);
|
||||
token = gtk_css_token_source_get_token (source))
|
||||
{
|
||||
if (box_shadow_mode && !inset &&
|
||||
gtk_css_token_is_ident (token, "inset"))
|
||||
{
|
||||
inset = TRUE;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (values[COLOR] == NULL && gtk_css_color_value_check_token (token))
|
||||
{
|
||||
values[COLOR] = gtk_css_color_value_token_parse (source);
|
||||
if (values[COLOR] == NULL)
|
||||
goto fail;
|
||||
}
|
||||
else if (values[HOFFSET] == NULL && gtk_css_number_value_check_token (token))
|
||||
{
|
||||
values[HOFFSET] = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_PARSE_LENGTH
|
||||
| GTK_CSS_NUMBER_AS_PIXELS);
|
||||
if (values[HOFFSET] == NULL)
|
||||
goto fail;
|
||||
|
||||
values[VOFFSET] = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_PARSE_LENGTH
|
||||
| GTK_CSS_NUMBER_AS_PIXELS);
|
||||
if (values[VOFFSET] == NULL)
|
||||
goto fail;
|
||||
|
||||
if (gtk_css_number_value_check_token (gtk_css_token_source_get_token (source)))
|
||||
{
|
||||
values[RADIUS] = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_PARSE_LENGTH
|
||||
| GTK_CSS_POSITIVE_ONLY
|
||||
| GTK_CSS_NUMBER_AS_PIXELS);
|
||||
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_check_token (gtk_css_token_source_get_token (source)))
|
||||
{
|
||||
values[SPREAD] = gtk_css_number_value_token_parse (source,
|
||||
GTK_CSS_PARSE_LENGTH
|
||||
| GTK_CSS_NUMBER_AS_PIXELS);
|
||||
if (values[SPREAD] == NULL)
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
values[SPREAD] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
|
||||
}
|
||||
else if (values[HOFFSET] == NULL)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a shadow definition");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (values[COLOR] == NULL)
|
||||
values[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]);
|
||||
|
||||
fail:
|
||||
for (i = 0; i < N_VALUES; i++)
|
||||
{
|
||||
if (values[i])
|
||||
_gtk_css_value_unref (values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
needs_blur (const GtkCssValue *shadow)
|
||||
{
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "gtktypes.h"
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
#include "gtkroundedboxprivate.h"
|
||||
|
||||
@@ -34,6 +35,8 @@ GtkCssValue * _gtk_css_shadow_value_new_for_transition (GtkCssValue
|
||||
|
||||
GtkCssValue * _gtk_css_shadow_value_parse (GtkCssParser *parser,
|
||||
gboolean box_shadow_mode);
|
||||
GtkCssValue * gtk_css_shadow_value_token_parse (GtkCssTokenSource *source,
|
||||
gboolean box_shadow_mode);
|
||||
|
||||
gboolean _gtk_css_shadow_value_get_inset (const GtkCssValue *shadow);
|
||||
|
||||
|
205
gtk/gtkcssshorthanddeclaration.c
Normal file
205
gtk/gtkcssshorthanddeclaration.c
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssshorthanddeclarationprivate.h"
|
||||
|
||||
#include "gtkcssarrayvalueprivate.h"
|
||||
#include "gtkcssshorthandpropertyprivate.h"
|
||||
|
||||
typedef struct _GtkCssShorthandDeclarationPrivate GtkCssShorthandDeclarationPrivate;
|
||||
struct _GtkCssShorthandDeclarationPrivate {
|
||||
GtkCssShorthandProperty *prop;
|
||||
GtkCssValue **values;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssShorthandDeclaration, gtk_css_shorthand_declaration, GTK_TYPE_CSS_DECLARATION)
|
||||
|
||||
static void
|
||||
gtk_css_shorthand_declaration_finalize (GObject *object)
|
||||
{
|
||||
GtkCssShorthandDeclaration *shorthand = GTK_CSS_SHORTHAND_DECLARATION (object);
|
||||
GtkCssShorthandDeclarationPrivate *priv = gtk_css_shorthand_declaration_get_instance_private (shorthand);
|
||||
guint i;
|
||||
|
||||
if (priv->values)
|
||||
{
|
||||
for (i = 0; i < gtk_css_shorthand_declaration_get_length (shorthand); i++)
|
||||
{
|
||||
_gtk_css_value_unref (priv->values[i]);
|
||||
}
|
||||
g_free (priv->values);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_shorthand_declaration_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static const char *
|
||||
gtk_css_shorthand_declaration_get_name (GtkCssDeclaration *decl)
|
||||
{
|
||||
GtkCssShorthandDeclaration *shorthand_declaration = GTK_CSS_SHORTHAND_DECLARATION (decl);
|
||||
GtkCssShorthandDeclarationPrivate *priv = gtk_css_shorthand_declaration_get_instance_private (shorthand_declaration);
|
||||
|
||||
return _gtk_style_property_get_name (GTK_STYLE_PROPERTY (priv->prop));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_shorthand_declaration_print_value (GtkCssDeclaration *decl,
|
||||
GString *string)
|
||||
{
|
||||
GtkCssShorthandDeclaration *shorthand = GTK_CSS_SHORTHAND_DECLARATION (decl);
|
||||
GtkCssShorthandDeclarationPrivate *priv = gtk_css_shorthand_declaration_get_instance_private (shorthand);
|
||||
guint i;
|
||||
|
||||
/* XXX */
|
||||
for (i = 0; i < gtk_css_shorthand_declaration_get_length (shorthand); i++)
|
||||
{
|
||||
if (i > 0)
|
||||
g_string_append (string, ", ");
|
||||
_gtk_css_value_print (priv->values[i], string);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_shorthand_declaration_class_init (GtkCssShorthandDeclarationClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkCssDeclarationClass *decl_class = GTK_CSS_DECLARATION_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_shorthand_declaration_finalize;
|
||||
|
||||
decl_class->get_name = gtk_css_shorthand_declaration_get_name;
|
||||
decl_class->print_value = gtk_css_shorthand_declaration_print_value;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_shorthand_declaration_init (GtkCssShorthandDeclaration *shorthand_declaration)
|
||||
{
|
||||
}
|
||||
|
||||
GtkCssDeclaration *
|
||||
gtk_css_shorthand_declaration_new_parse (GtkCssStyleDeclaration *style,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssShorthandDeclarationPrivate *priv;
|
||||
const GtkCssToken *token;
|
||||
GtkCssShorthandDeclaration *decl;
|
||||
GtkCssValue *array;
|
||||
guint i;
|
||||
char *name;
|
||||
|
||||
decl = g_object_new (GTK_TYPE_CSS_SHORTHAND_DECLARATION,
|
||||
"parent-style", style,
|
||||
NULL);
|
||||
priv = gtk_css_shorthand_declaration_get_instance_private (decl);
|
||||
|
||||
gtk_css_token_source_set_consumer (source, G_OBJECT (decl));
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a property name");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (decl);
|
||||
return NULL;
|
||||
}
|
||||
name = g_utf8_strdown (token->string.string, -1);
|
||||
priv->prop = (GtkCssShorthandProperty *) _gtk_style_property_lookup (name);
|
||||
if (!GTK_IS_CSS_SHORTHAND_PROPERTY (priv->prop))
|
||||
{
|
||||
gtk_css_token_source_unknown (source, "Property name '%s' is not a shorthand property", token->string.string);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (decl);
|
||||
g_free (name);
|
||||
return NULL;
|
||||
}
|
||||
else if (!g_str_equal (name, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (priv->prop))))
|
||||
gtk_css_token_source_deprecated (source,
|
||||
"The '%s' property has been renamed to '%s'",
|
||||
name, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (priv->prop)));
|
||||
gtk_css_token_source_consume_token (source);
|
||||
g_free (name);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COLON))
|
||||
{
|
||||
gtk_css_token_source_error (source, "No colon following property name");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (decl);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
array = gtk_style_property_token_parse (GTK_STYLE_PROPERTY (priv->prop), source);
|
||||
if (array == NULL)
|
||||
{
|
||||
g_object_unref (decl);
|
||||
return NULL;
|
||||
}
|
||||
priv->values = g_new (GtkCssValue *, gtk_css_shorthand_declaration_get_length (decl));
|
||||
for (i = 0; i < gtk_css_shorthand_declaration_get_length (decl); i++)
|
||||
{
|
||||
priv->values[i] = _gtk_css_value_ref (_gtk_css_array_value_get_nth (array, i));
|
||||
}
|
||||
_gtk_css_value_unref (array);
|
||||
|
||||
return GTK_CSS_DECLARATION (decl);
|
||||
}
|
||||
|
||||
guint
|
||||
gtk_css_shorthand_declaration_get_length (GtkCssShorthandDeclaration *decl)
|
||||
{
|
||||
GtkCssShorthandDeclarationPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_SHORTHAND_DECLARATION (decl), 0);
|
||||
|
||||
priv = gtk_css_shorthand_declaration_get_instance_private (decl);
|
||||
|
||||
return _gtk_css_shorthand_property_get_n_subproperties (priv->prop);
|
||||
}
|
||||
|
||||
GtkCssStyleProperty *
|
||||
gtk_css_shorthand_declaration_get_subproperty (GtkCssShorthandDeclaration *decl,
|
||||
guint id)
|
||||
{
|
||||
GtkCssShorthandDeclarationPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_SHORTHAND_DECLARATION (decl), NULL);
|
||||
g_return_val_if_fail (id < gtk_css_shorthand_declaration_get_length (decl), NULL);
|
||||
|
||||
priv = gtk_css_shorthand_declaration_get_instance_private (decl);
|
||||
|
||||
return _gtk_css_shorthand_property_get_subproperty (priv->prop, id);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_shorthand_declaration_get_value (GtkCssShorthandDeclaration *decl,
|
||||
guint id)
|
||||
{
|
||||
GtkCssShorthandDeclarationPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_SHORTHAND_DECLARATION (decl), NULL);
|
||||
g_return_val_if_fail (id < gtk_css_shorthand_declaration_get_length (decl), NULL);
|
||||
|
||||
priv = gtk_css_shorthand_declaration_get_instance_private (decl);
|
||||
|
||||
return priv->values[id];
|
||||
}
|
||||
|
64
gtk/gtkcssshorthanddeclarationprivate.h
Normal file
64
gtk/gtkcssshorthanddeclarationprivate.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_SHORTHAND_DECLARATION_PRIVATE_H__
|
||||
#define __GTK_CSS_SHORTHAND_DECLARATION_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssdeclarationprivate.h"
|
||||
|
||||
#include "gtk/gtkcssshorthandpropertyprivate.h"
|
||||
#include "gtk/gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_SHORTHAND_DECLARATION (gtk_css_shorthand_declaration_get_type ())
|
||||
#define GTK_CSS_SHORTHAND_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_SHORTHAND_DECLARATION, GtkCssShorthandDeclaration))
|
||||
#define GTK_CSS_SHORTHAND_DECLARATION_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_SHORTHAND_DECLARATION, GtkCssShorthandDeclarationClass))
|
||||
#define GTK_IS_CSS_SHORTHAND_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_SHORTHAND_DECLARATION))
|
||||
#define GTK_IS_CSS_SHORTHAND_DECLARATION_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_SHORTHAND_DECLARATION))
|
||||
#define GTK_CSS_SHORTHAND_DECLARATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_SHORTHAND_DECLARATION, GtkCssShorthandDeclarationClass))
|
||||
|
||||
typedef struct _GtkCssShorthandDeclaration GtkCssShorthandDeclaration;
|
||||
typedef struct _GtkCssShorthandDeclarationClass GtkCssShorthandDeclarationClass;
|
||||
|
||||
struct _GtkCssShorthandDeclaration
|
||||
{
|
||||
GtkCssDeclaration parent;
|
||||
};
|
||||
|
||||
struct _GtkCssShorthandDeclarationClass
|
||||
{
|
||||
GtkCssDeclarationClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_shorthand_declaration_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssDeclaration * gtk_css_shorthand_declaration_new_parse (GtkCssStyleDeclaration *style,
|
||||
GtkCssTokenSource *source);
|
||||
|
||||
guint gtk_css_shorthand_declaration_get_length (GtkCssShorthandDeclaration *decl);
|
||||
GtkCssStyleProperty * gtk_css_shorthand_declaration_get_subproperty (GtkCssShorthandDeclaration *decl,
|
||||
guint id);
|
||||
GtkCssValue * gtk_css_shorthand_declaration_get_value (GtkCssShorthandDeclaration *decl,
|
||||
guint id);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_SHORTHAND_DECLARATION_PRIVATE_H__ */
|
@@ -156,6 +156,112 @@ gtk_css_shorthand_property_parse_value (GtkStyleProperty *property,
|
||||
return result;
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
gtk_css_shorthand_property_token_parse (GtkStyleProperty *property,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
|
||||
const GtkCssToken *token;
|
||||
GtkCssValue **data;
|
||||
GtkCssValue *result;
|
||||
guint i;
|
||||
|
||||
data = g_new0 (GtkCssValue *, shorthand->subproperties->len);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "initial"))
|
||||
{
|
||||
/* the initial value can be explicitly specified with the
|
||||
* ‘initial’ keyword which all properties accept.
|
||||
*/
|
||||
for (i = 0; i < shorthand->subproperties->len; i++)
|
||||
{
|
||||
data[i] = _gtk_css_initial_value_new ();
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_ident (token, "inherit"))
|
||||
{
|
||||
/* All properties accept the ‘inherit’ value which
|
||||
* explicitly specifies that the value will be determined
|
||||
* by inheritance. The ‘inherit’ value can be used to
|
||||
* strengthen inherited values in the cascade, and it can
|
||||
* also be used on properties that are not normally inherited.
|
||||
*/
|
||||
for (i = 0; i < shorthand->subproperties->len; i++)
|
||||
{
|
||||
data[i] = _gtk_css_inherit_value_new ();
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_ident (token, "unset"))
|
||||
{
|
||||
/* If the cascaded value of a property is the unset keyword,
|
||||
* then if it is an inherited property, this is treated as
|
||||
* inherit, and if it is not, this is treated as initial.
|
||||
*/
|
||||
for (i = 0; i < shorthand->subproperties->len; i++)
|
||||
{
|
||||
data[i] = _gtk_css_unset_value_new ();
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (!shorthand->token_parse (shorthand, data, source))
|
||||
{
|
||||
for (i = 0; i < shorthand->subproperties->len; i++)
|
||||
{
|
||||
if (data[i] != NULL)
|
||||
_gtk_css_value_unref (data[i]);
|
||||
}
|
||||
g_free (data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* All values that aren't set by the parse func are set to their
|
||||
* default values here.
|
||||
* XXX: Is the default always initial or can it be inherit? */
|
||||
for (i = 0; i < shorthand->subproperties->len; i++)
|
||||
{
|
||||
if (data[i] == NULL)
|
||||
data[i] = _gtk_css_initial_value_new ();
|
||||
}
|
||||
|
||||
result = _gtk_css_array_value_new_from_array (data, shorthand->subproperties->len);
|
||||
g_free (data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
forward_error_to_source (GtkCssParser *parser,
|
||||
const GError *error,
|
||||
gpointer source)
|
||||
{
|
||||
/* XXX: This is bad because it doesn't emit the error on the right token */
|
||||
gtk_css_token_source_emit_error (source, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_shorthand_token_parse_default (GtkCssShorthandProperty *shorthand,
|
||||
GtkCssValue **values,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssParser *parser;
|
||||
char *str;
|
||||
gboolean result;
|
||||
|
||||
str = gtk_css_token_source_consume_to_string (source);
|
||||
parser = _gtk_css_parser_new (str,
|
||||
NULL,
|
||||
forward_error_to_source,
|
||||
source);
|
||||
result = shorthand->parse (shorthand, values, parser);
|
||||
_gtk_css_parser_free (parser);
|
||||
g_free (str);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_css_shorthand_property_class_init (GtkCssShorthandPropertyClass *klass)
|
||||
{
|
||||
@@ -175,12 +281,15 @@ _gtk_css_shorthand_property_class_init (GtkCssShorthandPropertyClass *klass)
|
||||
property_class->assign = _gtk_css_shorthand_property_assign;
|
||||
property_class->query = _gtk_css_shorthand_property_query;
|
||||
property_class->parse_value = gtk_css_shorthand_property_parse_value;
|
||||
property_class->token_parse = gtk_css_shorthand_property_token_parse;
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_css_shorthand_property_init (GtkCssShorthandProperty *shorthand)
|
||||
{
|
||||
shorthand->subproperties = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
|
||||
shorthand->token_parse = gtk_css_shorthand_token_parse_default;
|
||||
}
|
||||
|
||||
GtkCssStyleProperty *
|
||||
|
@@ -41,6 +41,9 @@ typedef struct _GtkCssShorthandPropertyClass GtkCssShorthandPropertyClass;
|
||||
typedef gboolean (* GtkCssShorthandPropertyParseFunc) (GtkCssShorthandProperty *shorthand,
|
||||
GtkCssValue **values,
|
||||
GtkCssParser *parser);
|
||||
typedef gboolean (* GtkCssShorthandPropertyTokenParseFunc) (GtkCssShorthandProperty *shorthand,
|
||||
GtkCssValue **values,
|
||||
GtkCssTokenSource *source);
|
||||
typedef void (* GtkCssShorthandPropertyAssignFunc) (GtkCssShorthandProperty *shorthand,
|
||||
GtkStyleProperties *props,
|
||||
GtkStateFlags state,
|
||||
@@ -57,6 +60,7 @@ struct _GtkCssShorthandProperty
|
||||
GPtrArray *subproperties;
|
||||
|
||||
GtkCssShorthandPropertyParseFunc parse;
|
||||
GtkCssShorthandPropertyTokenParseFunc token_parse;
|
||||
GtkCssShorthandPropertyAssignFunc assign;
|
||||
GtkCssShorthandPropertyQueryFunc query;
|
||||
};
|
||||
|
132
gtk/gtkcssstyledeclaration.c
Normal file
132
gtk/gtkcssstyledeclaration.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssstyledeclarationprivate.h"
|
||||
|
||||
#include "gtkcssdeclarationprivate.h"
|
||||
|
||||
typedef struct _GtkCssStyleDeclarationPrivate GtkCssStyleDeclarationPrivate;
|
||||
struct _GtkCssStyleDeclarationPrivate {
|
||||
GPtrArray *declarations;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssStyleDeclaration, gtk_css_style_declaration, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_css_style_declaration_finalize (GObject *object)
|
||||
{
|
||||
GtkCssStyleDeclaration *style_declaration = GTK_CSS_STYLE_DECLARATION (object);
|
||||
GtkCssStyleDeclarationPrivate *priv = gtk_css_style_declaration_get_instance_private (style_declaration);
|
||||
|
||||
g_ptr_array_unref (priv->declarations);
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_style_declaration_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_style_declaration_class_init (GtkCssStyleDeclarationClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_style_declaration_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_style_declaration_init (GtkCssStyleDeclaration *style_declaration)
|
||||
{
|
||||
GtkCssStyleDeclarationPrivate *priv = gtk_css_style_declaration_get_instance_private (style_declaration);
|
||||
|
||||
priv->declarations = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
}
|
||||
|
||||
GtkCssStyleDeclaration *
|
||||
gtk_css_style_declaration_new (GtkCssRule *parent_rule)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_CSS_STYLE_DECLARATION, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_style_declaration_parse (GtkCssStyleDeclaration *style,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssStyleDeclarationPrivate *priv;
|
||||
GtkCssTokenSource *decl_source;
|
||||
GtkCssDeclaration *declaration;
|
||||
const GtkCssToken *token;
|
||||
|
||||
priv = gtk_css_style_declaration_get_instance_private (style);
|
||||
gtk_css_token_source_set_consumer (source, G_OBJECT (style));
|
||||
|
||||
for (token = gtk_css_token_source_get_token (source);
|
||||
!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF);
|
||||
token = gtk_css_token_source_get_token (source))
|
||||
{
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_SEMICOLON) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_WHITESPACE))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
decl_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_SEMICOLON);
|
||||
declaration = gtk_css_declaration_new_parse (style, decl_source);
|
||||
if (declaration)
|
||||
g_ptr_array_add (priv->declarations, declaration);
|
||||
gtk_css_token_source_unref (decl_source);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected property declaration");
|
||||
decl_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_SEMICOLON);
|
||||
gtk_css_token_source_consume_all (decl_source);
|
||||
gtk_css_token_source_unref (decl_source);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GtkCssDeclaration *
|
||||
gtk_css_style_declaration_get_declaration (GtkCssStyleDeclaration *declaration,
|
||||
gssize id)
|
||||
{
|
||||
GtkCssStyleDeclarationPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_DECLARATION (declaration), NULL);
|
||||
|
||||
priv = gtk_css_style_declaration_get_instance_private (declaration);
|
||||
g_return_val_if_fail (id < priv->declarations->len, NULL);
|
||||
|
||||
return g_ptr_array_index (priv->declarations, id);
|
||||
}
|
||||
|
||||
gsize
|
||||
gtk_css_style_declaration_get_length (GtkCssStyleDeclaration *declaration)
|
||||
{
|
||||
GtkCssStyleDeclarationPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_DECLARATION (declaration), 0);
|
||||
|
||||
priv = gtk_css_style_declaration_get_instance_private (declaration);
|
||||
|
||||
return priv->declarations->len;
|
||||
}
|
||||
|
70
gtk/gtkcssstyledeclarationprivate.h
Normal file
70
gtk/gtkcssstyledeclarationprivate.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_STYLE_DECLARATION_PRIVATE_H__
|
||||
#define __GTK_CSS_STYLE_DECLARATION_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssruleprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_STYLE_DECLARATION (gtk_css_style_declaration_get_type ())
|
||||
#define GTK_CSS_STYLE_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_STYLE_DECLARATION, GtkCssStyleDeclaration))
|
||||
#define GTK_CSS_STYLE_DECLARATION_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_STYLE_DECLARATION, GtkCssStyleDeclarationClass))
|
||||
#define GTK_IS_CSS_STYLE_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_STYLE_DECLARATION))
|
||||
#define GTK_IS_CSS_STYLE_DECLARATION_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_STYLE_DECLARATION))
|
||||
#define GTK_CSS_STYLE_DECLARATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_STYLE_DECLARATION, GtkCssStyleDeclarationClass))
|
||||
|
||||
typedef struct _GtkCssDeclaration GtkCssDeclaration;
|
||||
|
||||
typedef struct _GtkCssStyleDeclaration GtkCssStyleDeclaration;
|
||||
typedef struct _GtkCssStyleDeclarationClass GtkCssStyleDeclarationClass;
|
||||
|
||||
struct _GtkCssStyleDeclaration
|
||||
{
|
||||
GObject parent;
|
||||
};
|
||||
|
||||
struct _GtkCssStyleDeclarationClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_style_declaration_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssStyleDeclaration *gtk_css_style_declaration_new (GtkCssRule *parent_rule);
|
||||
|
||||
void gtk_css_style_declaration_parse (GtkCssStyleDeclaration *style,
|
||||
GtkCssTokenSource *source);
|
||||
|
||||
GtkCssDeclaration * gtk_css_style_declaration_get_declaration (GtkCssStyleDeclaration *declaration,
|
||||
gssize id);
|
||||
|
||||
/* GtkCssStyleDeclaration DOM */
|
||||
void gtk_css_style_declaration_print_css_text (GtkCssStyleDeclaration *declaration,
|
||||
GString *string);
|
||||
char * gtk_css_style_declaration_get_css_text (GtkCssStyleDeclaration *declaration);
|
||||
gsize gtk_css_style_declaration_get_length (GtkCssStyleDeclaration *declaration);
|
||||
char * gtk_css_style_declaration_get_item (GtkCssStyleDeclaration *declaration,
|
||||
gssize size);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_STYLE_DECLARATION_PRIVATE_H__ */
|
@@ -192,6 +192,51 @@ gtk_css_style_property_parse_value (GtkStyleProperty *property,
|
||||
return (* style_property->parse_value) (style_property, parser);
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
gtk_css_style_property_token_parse (GtkStyleProperty *property,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssStyleProperty *style_property = GTK_CSS_STYLE_PROPERTY (property);
|
||||
const GtkCssToken *token;
|
||||
GtkCssValue *value;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "initial"))
|
||||
{
|
||||
/* the initial value can be explicitly specified with the
|
||||
* ‘initial’ keyword which all properties accept.
|
||||
*/
|
||||
value = _gtk_css_initial_value_new ();
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_ident (token, "inherit"))
|
||||
{
|
||||
/* All properties accept the ‘inherit’ value which
|
||||
* explicitly specifies that the value will be determined
|
||||
* by inheritance. The ‘inherit’ value can be used to
|
||||
* strengthen inherited values in the cascade, and it can
|
||||
* also be used on properties that are not normally inherited.
|
||||
*/
|
||||
value = _gtk_css_inherit_value_new ();
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is_ident (token, "unset"))
|
||||
{
|
||||
/* If the cascaded value of a property is the unset keyword,
|
||||
* then if it is an inherited property, this is treated as
|
||||
* inherit, and if it is not, this is treated as initial.
|
||||
*/
|
||||
value = _gtk_css_unset_value_new ();
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (* style_property->token_parse) (source);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_css_style_property_class_init (GtkCssStylePropertyClass *klass)
|
||||
{
|
||||
@@ -242,6 +287,7 @@ _gtk_css_style_property_class_init (GtkCssStylePropertyClass *klass)
|
||||
property_class->assign = _gtk_css_style_property_assign;
|
||||
property_class->query = _gtk_css_style_property_query;
|
||||
property_class->parse_value = gtk_css_style_property_parse_value;
|
||||
property_class->token_parse = gtk_css_style_property_token_parse;
|
||||
|
||||
klass->style_properties = g_ptr_array_new ();
|
||||
|
||||
@@ -256,10 +302,18 @@ gtk_css_style_property_real_parse_value (GtkCssStyleProperty *property,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
gtk_css_style_property_real_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_css_style_property_init (GtkCssStyleProperty *property)
|
||||
{
|
||||
property->parse_value = gtk_css_style_property_real_parse_value;
|
||||
property->token_parse = gtk_css_style_property_real_token_parse;
|
||||
}
|
||||
|
||||
/**
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -34,13 +34,14 @@ G_BEGIN_DECLS
|
||||
typedef struct _GtkCssStyleProperty GtkCssStyleProperty;
|
||||
typedef struct _GtkCssStylePropertyClass GtkCssStylePropertyClass;
|
||||
|
||||
typedef GtkCssValue * (* GtkCssStylePropertyParseFunc) (GtkCssStyleProperty *property,
|
||||
GtkCssParser *parser);
|
||||
typedef void (* GtkCssStylePropertyQueryFunc) (GtkCssStyleProperty *property,
|
||||
const GtkCssValue *cssvalue,
|
||||
GValue *value);
|
||||
typedef GtkCssValue * (* GtkCssStylePropertyAssignFunc) (GtkCssStyleProperty *property,
|
||||
const GValue *value);
|
||||
typedef GtkCssValue * (* GtkCssStylePropertyParseFunc) (GtkCssStyleProperty *property,
|
||||
GtkCssParser *parser);
|
||||
typedef GtkCssValue * (* GtkCssStylePropertyTokenParseFunc) (GtkCssTokenSource *source);
|
||||
typedef void (* GtkCssStylePropertyQueryFunc) (GtkCssStyleProperty *property,
|
||||
const GtkCssValue *cssvalue,
|
||||
GValue *value);
|
||||
typedef GtkCssValue * (* GtkCssStylePropertyAssignFunc) (GtkCssStyleProperty *property,
|
||||
const GValue *value);
|
||||
struct _GtkCssStyleProperty
|
||||
{
|
||||
GtkStyleProperty parent;
|
||||
@@ -52,6 +53,7 @@ struct _GtkCssStyleProperty
|
||||
guint animated :1;
|
||||
|
||||
GtkCssStylePropertyParseFunc parse_value;
|
||||
GtkCssStylePropertyTokenParseFunc token_parse;
|
||||
GtkCssStylePropertyQueryFunc query_value;
|
||||
GtkCssStylePropertyAssignFunc assign_value;
|
||||
};
|
||||
|
179
gtk/gtkcssstylerule.c
Normal file
179
gtk/gtkcssstylerule.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssstyleruleprivate.h"
|
||||
|
||||
#include "gtkcssselectorprivate.h"
|
||||
#include "gtkcssstylesheetprivate.h"
|
||||
|
||||
typedef struct _GtkCssStyleRulePrivate GtkCssStyleRulePrivate;
|
||||
struct _GtkCssStyleRulePrivate {
|
||||
GPtrArray *selectors;
|
||||
GtkCssStyleDeclaration *style;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssStyleRule, gtk_css_style_rule, GTK_TYPE_CSS_RULE)
|
||||
|
||||
static void
|
||||
gtk_css_style_rule_finalize (GObject *object)
|
||||
{
|
||||
GtkCssStyleRule *style_rule = GTK_CSS_STYLE_RULE (object);
|
||||
GtkCssStyleRulePrivate *priv = gtk_css_style_rule_get_instance_private (style_rule);
|
||||
|
||||
g_ptr_array_unref (priv->selectors);
|
||||
g_object_unref (priv->style);
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_style_rule_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_style_rule_class_init (GtkCssStyleRuleClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_style_rule_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_style_rule_init (GtkCssStyleRule *style_rule)
|
||||
{
|
||||
GtkCssStyleRulePrivate *priv = gtk_css_style_rule_get_instance_private (style_rule);
|
||||
|
||||
priv->selectors = g_ptr_array_new_with_free_func ((GDestroyNotify) _gtk_css_selector_free);
|
||||
priv->style = gtk_css_style_declaration_new (GTK_CSS_RULE (style_rule));
|
||||
}
|
||||
|
||||
static GtkCssRule *
|
||||
gtk_css_style_rule_new (GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_CSS_STYLE_RULE,
|
||||
"parent-rule", parent_rule,
|
||||
"parent-stylesheet", parent_style_sheet,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_style_rule_parse_selectors (GtkCssStyleRule *rule,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssStyleRulePrivate *priv = gtk_css_style_rule_get_instance_private (rule);
|
||||
GtkCssTokenSource *child_source;
|
||||
GtkCssSelector *selector;
|
||||
const GtkCssToken *token;
|
||||
|
||||
gtk_css_token_source_set_consumer (source, G_OBJECT (rule));
|
||||
|
||||
for (token = gtk_css_token_source_get_token (source);
|
||||
!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF);
|
||||
token = gtk_css_token_source_get_token (source))
|
||||
{
|
||||
child_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_COMMA);
|
||||
selector = gtk_css_selector_token_parse (child_source);
|
||||
gtk_css_token_source_unref (child_source);
|
||||
if (selector == NULL)
|
||||
return FALSE;
|
||||
|
||||
g_ptr_array_add (priv->selectors, selector);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkCssRule *
|
||||
gtk_css_style_rule_new_parse (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet)
|
||||
{
|
||||
GtkCssStyleRulePrivate *priv;
|
||||
GtkCssTokenSource *child_source;
|
||||
GtkCssStyleRule *rule;
|
||||
gboolean success;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
g_return_val_if_fail (parent_rule == NULL || GTK_IS_CSS_RULE (parent_rule), NULL);
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (parent_style_sheet), NULL);
|
||||
|
||||
rule = GTK_CSS_STYLE_RULE (gtk_css_style_rule_new (parent_rule, parent_style_sheet));
|
||||
priv = gtk_css_style_rule_get_instance_private (rule);
|
||||
|
||||
gtk_css_token_source_set_consumer (source, G_OBJECT (rule));
|
||||
child_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_OPEN_CURLY);
|
||||
success = gtk_css_style_rule_parse_selectors (rule, child_source);
|
||||
gtk_css_token_source_unref (child_source);
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
child_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_CLOSE_CURLY);
|
||||
if (success)
|
||||
gtk_css_style_declaration_parse (priv->style, child_source);
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_consume_all (child_source);
|
||||
}
|
||||
gtk_css_token_source_unref (child_source);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
g_object_unref (rule);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GTK_CSS_RULE (rule);
|
||||
}
|
||||
|
||||
gsize
|
||||
gtk_css_style_rule_get_n_selectors (GtkCssStyleRule *rule)
|
||||
{
|
||||
GtkCssStyleRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_RULE (rule), 0);
|
||||
|
||||
priv = gtk_css_style_rule_get_instance_private (rule);
|
||||
|
||||
return priv->selectors->len;
|
||||
}
|
||||
|
||||
GtkCssSelector *
|
||||
gtk_css_style_rule_get_selector (GtkCssStyleRule *rule,
|
||||
gsize id)
|
||||
{
|
||||
GtkCssStyleRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_RULE (rule), 0);
|
||||
|
||||
priv = gtk_css_style_rule_get_instance_private (rule);
|
||||
|
||||
return g_ptr_array_index (priv->selectors, id);
|
||||
}
|
||||
|
||||
GtkCssStyleDeclaration *
|
||||
gtk_css_style_rule_get_style (GtkCssStyleRule *rule)
|
||||
{
|
||||
GtkCssStyleRulePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_RULE (rule), NULL);
|
||||
|
||||
priv = gtk_css_style_rule_get_instance_private (rule);
|
||||
|
||||
return priv->style;
|
||||
}
|
64
gtk/gtkcssstyleruleprivate.h
Normal file
64
gtk/gtkcssstyleruleprivate.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_STYLE_RULE_PRIVATE_H__
|
||||
#define __GTK_CSS_STYLE_RULE_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssruleprivate.h"
|
||||
#include "gtk/gtkcssselectorprivate.h"
|
||||
#include "gtk/gtkcssstyledeclarationprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_STYLE_RULE (gtk_css_style_rule_get_type ())
|
||||
#define GTK_CSS_STYLE_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_STYLE_RULE, GtkCssStyleRule))
|
||||
#define GTK_CSS_STYLE_RULE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_STYLE_RULE, GtkCssStyleRuleClass))
|
||||
#define GTK_IS_CSS_STYLE_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_STYLE_RULE))
|
||||
#define GTK_IS_CSS_STYLE_RULE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_STYLE_RULE))
|
||||
#define GTK_CSS_STYLE_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_STYLE_RULE, GtkCssStyleRuleClass))
|
||||
|
||||
typedef struct _GtkCssStyleRule GtkCssStyleRule;
|
||||
typedef struct _GtkCssStyleRuleClass GtkCssStyleRuleClass;
|
||||
|
||||
struct _GtkCssStyleRule
|
||||
{
|
||||
GtkCssRule parent;
|
||||
};
|
||||
|
||||
struct _GtkCssStyleRuleClass
|
||||
{
|
||||
GtkCssRuleClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_style_rule_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssRule * gtk_css_style_rule_new_parse (GtkCssTokenSource *source,
|
||||
GtkCssRule *parent_rule,
|
||||
GtkCssStyleSheet *parent_style_sheet);
|
||||
|
||||
gsize gtk_css_style_rule_get_n_selectors (GtkCssStyleRule *rule);
|
||||
GtkCssSelector * gtk_css_style_rule_get_selector (GtkCssStyleRule *rule,
|
||||
gsize id);
|
||||
|
||||
GtkCssStyleDeclaration *gtk_css_style_rule_get_style (GtkCssStyleRule *rule);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_STYLE_RULE_PRIVATE_H__ */
|
267
gtk/gtkcssstylesheet.c
Normal file
267
gtk/gtkcssstylesheet.c
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssstylesheetprivate.h"
|
||||
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CSS_RULES,
|
||||
PROP_FILE,
|
||||
PROP_OWNER_RULE,
|
||||
PROP_PARENT_STYLESHEET,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
typedef struct _GtkCssStyleSheetPrivate GtkCssStyleSheetPrivate;
|
||||
struct _GtkCssStyleSheetPrivate {
|
||||
GtkCssRule *owner_rule;
|
||||
GtkCssRuleList *css_rules;
|
||||
|
||||
GFile *file;
|
||||
};
|
||||
|
||||
static GParamSpec *style_sheet_props[NUM_PROPERTIES] = { NULL, };
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssStyleSheet, gtk_css_style_sheet, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_css_style_sheet_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkCssStyleSheet *style_sheet = GTK_CSS_STYLE_SHEET (gobject);
|
||||
GtkCssStyleSheetPrivate *priv = gtk_css_style_sheet_get_instance_private (style_sheet);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FILE:
|
||||
priv->file = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_OWNER_RULE:
|
||||
priv->owner_rule = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_style_sheet_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkCssStyleSheet *style_sheet = GTK_CSS_STYLE_SHEET (gobject);
|
||||
GtkCssStyleSheetPrivate *priv = gtk_css_style_sheet_get_instance_private (style_sheet);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CSS_RULES:
|
||||
g_value_set_object (value, priv->css_rules);
|
||||
break;
|
||||
|
||||
case PROP_FILE:
|
||||
g_value_set_object (value, priv->file);
|
||||
break;
|
||||
|
||||
case PROP_OWNER_RULE:
|
||||
g_value_set_object (value, priv->owner_rule);
|
||||
break;
|
||||
|
||||
case PROP_PARENT_STYLESHEET:
|
||||
if (priv->owner_rule)
|
||||
g_value_set_object (value, gtk_css_rule_get_parent_style_sheet (priv->owner_rule));
|
||||
else
|
||||
g_value_set_object (value, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_style_sheet_finalize (GObject *object)
|
||||
{
|
||||
GtkCssStyleSheet *style_sheet = GTK_CSS_STYLE_SHEET (object);
|
||||
GtkCssStyleSheetPrivate *priv = gtk_css_style_sheet_get_instance_private (style_sheet);
|
||||
|
||||
g_object_unref (priv->css_rules);
|
||||
if (priv->owner_rule)
|
||||
g_object_unref (priv->owner_rule);
|
||||
if (priv->file)
|
||||
g_object_unref (priv->file);
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_style_sheet_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_style_sheet_class_init (GtkCssStyleSheetClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_style_sheet_finalize;
|
||||
object_class->get_property = gtk_css_style_sheet_get_property;
|
||||
object_class->set_property = gtk_css_style_sheet_set_property;
|
||||
|
||||
style_sheet_props[PROP_CSS_RULES] =
|
||||
g_param_spec_object ("css-rules",
|
||||
P_("css rules"),
|
||||
P_("The CSS rules of the style sheet"),
|
||||
GTK_TYPE_CSS_RULE_LIST,
|
||||
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
style_sheet_props[PROP_FILE] =
|
||||
g_param_spec_object ("file",
|
||||
P_("file"),
|
||||
P_("The file the style sheet was loaded from or NULL if inline"),
|
||||
G_TYPE_FILE,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY);
|
||||
style_sheet_props[PROP_OWNER_RULE] =
|
||||
g_param_spec_object ("owner-rule",
|
||||
P_("owner rule"),
|
||||
P_("The CSS rule that loaded this style sheet or NULL"),
|
||||
GTK_TYPE_CSS_RULE,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY);
|
||||
style_sheet_props[PROP_PARENT_STYLESHEET] =
|
||||
g_param_spec_object ("parent-stylesheet",
|
||||
P_("parent style sheet"),
|
||||
P_("The parent style sheet that loaded this style sheet or NULL"),
|
||||
GTK_TYPE_CSS_STYLE_SHEET,
|
||||
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, style_sheet_props);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_style_sheet_init (GtkCssStyleSheet *style_sheet)
|
||||
{
|
||||
GtkCssStyleSheetPrivate *priv = gtk_css_style_sheet_get_instance_private (style_sheet);
|
||||
|
||||
priv->css_rules = gtk_css_rule_list_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_style_sheet_parse (GtkCssStyleSheet *style_sheet,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssStyleSheetPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_CSS_STYLE_SHEET (style_sheet));
|
||||
g_return_if_fail (source != NULL);
|
||||
|
||||
priv = gtk_css_style_sheet_get_instance_private (style_sheet);
|
||||
|
||||
gtk_css_rule_list_parse (priv->css_rules, source, NULL, style_sheet);
|
||||
}
|
||||
|
||||
GtkCssStyleSheet *
|
||||
gtk_css_style_sheet_new (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssStyleSheet *sheet;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
|
||||
sheet = g_object_new (GTK_TYPE_CSS_STYLE_SHEET,
|
||||
"file", gtk_css_token_source_get_location (source),
|
||||
NULL);
|
||||
|
||||
gtk_css_style_sheet_parse (sheet, source);
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
GtkCssStyleSheet *
|
||||
gtk_css_style_sheet_new_import (GtkCssTokenSource *source,
|
||||
GtkCssRule *owner_rule)
|
||||
{
|
||||
GtkCssStyleSheet *sheet;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
g_return_val_if_fail (GTK_IS_CSS_RULE (owner_rule), NULL);
|
||||
|
||||
sheet = g_object_new (GTK_TYPE_CSS_STYLE_SHEET,
|
||||
"file", gtk_css_token_source_get_location (source),
|
||||
"owner-rule", owner_rule,
|
||||
NULL);
|
||||
|
||||
gtk_css_style_sheet_parse (sheet, source);
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
GFile *
|
||||
gtk_css_style_sheet_get_file (GtkCssStyleSheet *style_sheet)
|
||||
{
|
||||
GtkCssStyleSheetPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (style_sheet), NULL);
|
||||
|
||||
priv = gtk_css_style_sheet_get_instance_private (style_sheet);
|
||||
|
||||
return priv->file;
|
||||
}
|
||||
|
||||
GtkCssStyleSheet *
|
||||
gtk_css_style_sheet_get_parent_style_sheet (GtkCssStyleSheet *style_sheet)
|
||||
{
|
||||
GtkCssStyleSheetPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (style_sheet), NULL);
|
||||
|
||||
priv = gtk_css_style_sheet_get_instance_private (style_sheet);
|
||||
|
||||
if (priv->owner_rule == NULL)
|
||||
return NULL;
|
||||
|
||||
return gtk_css_rule_get_parent_style_sheet (priv->owner_rule);
|
||||
}
|
||||
|
||||
GtkCssRule *
|
||||
gtk_css_style_sheet_get_owner_rule (GtkCssStyleSheet *style_sheet)
|
||||
{
|
||||
GtkCssStyleSheetPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (style_sheet), NULL);
|
||||
|
||||
priv = gtk_css_style_sheet_get_instance_private (style_sheet);
|
||||
|
||||
return priv->owner_rule;
|
||||
}
|
||||
|
||||
GtkCssRuleList *
|
||||
gtk_css_style_sheet_get_css_rules (GtkCssStyleSheet *style_sheet)
|
||||
{
|
||||
GtkCssStyleSheetPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (style_sheet), NULL);
|
||||
|
||||
priv = gtk_css_style_sheet_get_instance_private (style_sheet);
|
||||
|
||||
return priv->css_rules;
|
||||
}
|
||||
|
68
gtk/gtkcssstylesheetprivate.h
Normal file
68
gtk/gtkcssstylesheetprivate.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_STYLE_SHEET_PRIVATE_H__
|
||||
#define __GTK_CSS_STYLE_SHEET_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssruleprivate.h"
|
||||
#include "gtk/gtkcssrulelistprivate.h"
|
||||
#include "gtk/gtkcsstokensourceprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_STYLE_SHEET (gtk_css_style_sheet_get_type ())
|
||||
#define GTK_CSS_STYLE_SHEET(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_STYLE_SHEET, GtkCssStyleSheet))
|
||||
#define GTK_CSS_STYLE_SHEET_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_STYLE_SHEET, GtkCssStyleSheetClass))
|
||||
#define GTK_IS_CSS_STYLE_SHEET(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_STYLE_SHEET))
|
||||
#define GTK_IS_CSS_STYLE_SHEET_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_STYLE_SHEET))
|
||||
#define GTK_CSS_STYLE_SHEET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_STYLE_SHEET, GtkCssStyleSheetClass))
|
||||
|
||||
/* declared with GtkCssRule */
|
||||
/* typedef struct _GtkCssStyleSheet GtkCssStyleSheet; */
|
||||
typedef struct _GtkCssStyleSheetClass GtkCssStyleSheetClass;
|
||||
|
||||
struct _GtkCssStyleSheet
|
||||
{
|
||||
GObject parent;
|
||||
};
|
||||
|
||||
struct _GtkCssStyleSheetClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_style_sheet_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssStyleSheet * gtk_css_style_sheet_new (GtkCssTokenSource *source);
|
||||
GtkCssStyleSheet * gtk_css_style_sheet_new_import (GtkCssTokenSource *source,
|
||||
GtkCssRule *owner_rule);
|
||||
|
||||
/* StyleSheet interface */
|
||||
GtkCssStyleSheet * gtk_css_style_sheet_get_parent_style_sheet (GtkCssStyleSheet *style_sheet);
|
||||
|
||||
GFile * gtk_css_style_sheet_get_file (GtkCssStyleSheet *style_sheet);
|
||||
|
||||
/* CSSStyleSheet interface */
|
||||
GtkCssRule * gtk_css_style_sheet_get_owner_rule (GtkCssStyleSheet *style_sheet);
|
||||
GtkCssRuleList * gtk_css_style_sheet_get_css_rules (GtkCssStyleSheet *style_sheet);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_STYLE_SHEET_PRIVATE_H__ */
|
1441
gtk/gtkcsstokenizer.c
Normal file
1441
gtk/gtkcsstokenizer.c
Normal file
File diff suppressed because it is too large
Load Diff
154
gtk/gtkcsstokenizerprivate.h
Normal file
154
gtk/gtkcsstokenizerprivate.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2011 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_TOKENIZER_PRIVATE_H__
|
||||
#define __GTK_CSS_TOKENIZER_PRIVATE_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
/* no content */
|
||||
GTK_CSS_TOKEN_EOF,
|
||||
GTK_CSS_TOKEN_WHITESPACE,
|
||||
GTK_CSS_TOKEN_OPEN_PARENS,
|
||||
GTK_CSS_TOKEN_CLOSE_PARENS,
|
||||
GTK_CSS_TOKEN_OPEN_SQUARE,
|
||||
GTK_CSS_TOKEN_CLOSE_SQUARE,
|
||||
GTK_CSS_TOKEN_OPEN_CURLY,
|
||||
GTK_CSS_TOKEN_CLOSE_CURLY,
|
||||
GTK_CSS_TOKEN_COMMA,
|
||||
GTK_CSS_TOKEN_COLON,
|
||||
GTK_CSS_TOKEN_SEMICOLON,
|
||||
GTK_CSS_TOKEN_CDO,
|
||||
GTK_CSS_TOKEN_CDC,
|
||||
GTK_CSS_TOKEN_INCLUDE_MATCH,
|
||||
GTK_CSS_TOKEN_DASH_MATCH,
|
||||
GTK_CSS_TOKEN_PREFIX_MATCH,
|
||||
GTK_CSS_TOKEN_SUFFIX_MATCH,
|
||||
GTK_CSS_TOKEN_SUBSTRING_MATCH,
|
||||
GTK_CSS_TOKEN_COLUMN,
|
||||
GTK_CSS_TOKEN_BAD_STRING,
|
||||
GTK_CSS_TOKEN_BAD_URL,
|
||||
GTK_CSS_TOKEN_COMMENT,
|
||||
/* delim */
|
||||
GTK_CSS_TOKEN_DELIM,
|
||||
/* string */
|
||||
GTK_CSS_TOKEN_STRING,
|
||||
GTK_CSS_TOKEN_IDENT,
|
||||
GTK_CSS_TOKEN_FUNCTION,
|
||||
GTK_CSS_TOKEN_AT_KEYWORD,
|
||||
GTK_CSS_TOKEN_HASH_UNRESTRICTED,
|
||||
GTK_CSS_TOKEN_HASH_ID,
|
||||
GTK_CSS_TOKEN_URL,
|
||||
/* number */
|
||||
GTK_CSS_TOKEN_SIGNED_INTEGER,
|
||||
GTK_CSS_TOKEN_SIGNLESS_INTEGER,
|
||||
GTK_CSS_TOKEN_SIGNED_NUMBER,
|
||||
GTK_CSS_TOKEN_SIGNLESS_NUMBER,
|
||||
GTK_CSS_TOKEN_PERCENTAGE,
|
||||
/* dimension */
|
||||
GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION,
|
||||
GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION,
|
||||
GTK_CSS_TOKEN_DIMENSION
|
||||
} GtkCssTokenType;
|
||||
|
||||
typedef union _GtkCssToken GtkCssToken;
|
||||
typedef struct _GtkCssTokenizer GtkCssTokenizer;
|
||||
typedef struct _GtkCssLocation GtkCssLocation;
|
||||
|
||||
typedef struct _GtkCssStringToken GtkCssStringToken;
|
||||
typedef struct _GtkCssDelimToken GtkCssDelimToken;
|
||||
typedef struct _GtkCssNumberToken GtkCssNumberToken;
|
||||
typedef struct _GtkCssDimensionToken GtkCssDimensionToken;
|
||||
|
||||
typedef void (* GtkCssTokenizerErrorFunc) (GtkCssTokenizer *parser,
|
||||
const GtkCssLocation *location,
|
||||
const GtkCssToken *token,
|
||||
const GError *error,
|
||||
gpointer user_data);
|
||||
|
||||
struct _GtkCssStringToken {
|
||||
GtkCssTokenType type;
|
||||
char *string;
|
||||
};
|
||||
|
||||
struct _GtkCssDelimToken {
|
||||
GtkCssTokenType type;
|
||||
gunichar delim;
|
||||
};
|
||||
|
||||
struct _GtkCssNumberToken {
|
||||
GtkCssTokenType type;
|
||||
double number;
|
||||
};
|
||||
|
||||
struct _GtkCssDimensionToken {
|
||||
GtkCssTokenType type;
|
||||
double value;
|
||||
char *dimension;
|
||||
};
|
||||
|
||||
union _GtkCssToken {
|
||||
GtkCssTokenType type;
|
||||
GtkCssStringToken string;
|
||||
GtkCssDelimToken delim;
|
||||
GtkCssNumberToken number;
|
||||
GtkCssDimensionToken dimension;
|
||||
};
|
||||
|
||||
struct _GtkCssLocation
|
||||
{
|
||||
gsize bytes;
|
||||
gsize chars;
|
||||
gsize lines;
|
||||
gsize line_bytes;
|
||||
gsize line_chars;
|
||||
};
|
||||
|
||||
void gtk_css_token_clear (GtkCssToken *token);
|
||||
|
||||
gboolean gtk_css_token_is_finite (const GtkCssToken *token);
|
||||
#define gtk_css_token_is(token, _type) ((token)->type == (_type))
|
||||
gboolean gtk_css_token_is_ident (const GtkCssToken *token,
|
||||
const char *ident);
|
||||
gboolean gtk_css_token_is_function (const GtkCssToken *token,
|
||||
const char *ident);
|
||||
gboolean gtk_css_token_is_delim (const GtkCssToken *token,
|
||||
gunichar delim);
|
||||
|
||||
void gtk_css_token_print (const GtkCssToken *token,
|
||||
GString *string);
|
||||
char * gtk_css_token_to_string (const GtkCssToken *token);
|
||||
|
||||
GtkCssTokenizer * gtk_css_tokenizer_new (GBytes *bytes,
|
||||
GtkCssTokenizerErrorFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy);
|
||||
|
||||
GtkCssTokenizer * gtk_css_tokenizer_ref (GtkCssTokenizer *tokenizer);
|
||||
void gtk_css_tokenizer_unref (GtkCssTokenizer *tokenizer);
|
||||
|
||||
const GtkCssLocation * gtk_css_tokenizer_get_location (GtkCssTokenizer *tokenizer);
|
||||
|
||||
void gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer,
|
||||
GtkCssToken *token);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_TOKENIZER_PRIVATE_H__ */
|
615
gtk/gtkcsstokensource.c
Normal file
615
gtk/gtkcsstokensource.c
Normal file
@@ -0,0 +1,615 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkcssprovider.h"
|
||||
|
||||
typedef struct _GtkCssTokenSourceTokenizer GtkCssTokenSourceTokenizer;
|
||||
struct _GtkCssTokenSourceTokenizer {
|
||||
GtkCssTokenSource parent;
|
||||
GtkCssTokenizer *tokenizer;
|
||||
GFile *location;
|
||||
GtkCssToken current_token;
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_css_token_source_tokenizer_finalize (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourceTokenizer *tok = (GtkCssTokenSourceTokenizer *) source;
|
||||
|
||||
gtk_css_token_clear (&tok->current_token);
|
||||
gtk_css_tokenizer_unref (tok->tokenizer);
|
||||
if (tok->location)
|
||||
g_object_unref (tok->location);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_token_source_tokenizer_consume_token (GtkCssTokenSource *source,
|
||||
GObject *consumer)
|
||||
{
|
||||
GtkCssTokenSourceTokenizer *tok = (GtkCssTokenSourceTokenizer *) source;
|
||||
|
||||
gtk_css_token_clear (&tok->current_token);
|
||||
}
|
||||
|
||||
static const GtkCssToken *
|
||||
gtk_css_token_source_tokenizer_peek_token (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourceTokenizer *tok = (GtkCssTokenSourceTokenizer *) source;
|
||||
|
||||
if (gtk_css_token_is (&tok->current_token, GTK_CSS_TOKEN_EOF))
|
||||
{
|
||||
gtk_css_tokenizer_read_token (tok->tokenizer, &tok->current_token);
|
||||
|
||||
#if 0
|
||||
if (!gtk_css_token_is (&tok->current_token, GTK_CSS_TOKEN_EOF)) {
|
||||
char *s = gtk_css_token_to_string (&tok->current_token);
|
||||
g_print ("%3zu:%02zu %2d %s\n",
|
||||
gtk_css_tokenizer_get_line (tok->tokenizer), gtk_css_tokenizer_get_line_char (tok->tokenizer),
|
||||
tok->current_token.type, s);
|
||||
g_free (s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return &tok->current_token;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_token_source_tokenizer_error (GtkCssTokenSource *source,
|
||||
const GError *error)
|
||||
{
|
||||
GtkCssTokenSourceTokenizer *tok = (GtkCssTokenSourceTokenizer *) source;
|
||||
const GtkCssLocation *pos = gtk_css_tokenizer_get_location (tok->tokenizer);
|
||||
|
||||
/* XXX */
|
||||
g_print ("ERROR: %zu:%zu: %s\n",
|
||||
pos->lines, pos->line_chars,
|
||||
error->message);
|
||||
}
|
||||
|
||||
static GFile *
|
||||
gtk_css_token_source_tokenizer_get_location (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourceTokenizer *tok = (GtkCssTokenSourceTokenizer *) source;
|
||||
|
||||
return tok->location;
|
||||
}
|
||||
|
||||
const GtkCssTokenSourceClass GTK_CSS_TOKEN_SOURCE_TOKENIZER = {
|
||||
gtk_css_token_source_tokenizer_finalize,
|
||||
gtk_css_token_source_tokenizer_consume_token,
|
||||
gtk_css_token_source_tokenizer_peek_token,
|
||||
gtk_css_token_source_tokenizer_error,
|
||||
gtk_css_token_source_tokenizer_get_location,
|
||||
};
|
||||
|
||||
GtkCssTokenSource *
|
||||
gtk_css_token_source_new_for_tokenizer (GtkCssTokenizer *tokenizer,
|
||||
GFile *location)
|
||||
{
|
||||
GtkCssTokenSourceTokenizer *source;
|
||||
|
||||
g_return_val_if_fail (tokenizer != NULL, NULL);
|
||||
g_return_val_if_fail (location == NULL || G_IS_FILE (location), NULL);
|
||||
|
||||
source = gtk_css_token_source_new (GtkCssTokenSourceTokenizer, >K_CSS_TOKEN_SOURCE_TOKENIZER);
|
||||
source->tokenizer = gtk_css_tokenizer_ref (tokenizer);
|
||||
if (location)
|
||||
source->location = g_object_ref (location);
|
||||
|
||||
return &source->parent;
|
||||
}
|
||||
|
||||
typedef struct _GtkCssTokenSourcePart GtkCssTokenSourcePart;
|
||||
struct _GtkCssTokenSourcePart {
|
||||
GtkCssTokenSource parent;
|
||||
GtkCssTokenSource *source;
|
||||
GtkCssTokenType end_type;
|
||||
GSList *blocks; /* of GPOINTER_TO_UINT(GtkCssTokenType) */
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_css_token_source_part_finalize (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourcePart *part = (GtkCssTokenSourcePart *) source;
|
||||
|
||||
gtk_css_token_source_unref (part->source);
|
||||
g_slist_free (part->blocks);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_token_source_part_consume_token (GtkCssTokenSource *source,
|
||||
GObject *consumer)
|
||||
{
|
||||
GtkCssTokenSourcePart *part = (GtkCssTokenSourcePart *) source;
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_peek_token (part->source);
|
||||
|
||||
if (part->blocks)
|
||||
{
|
||||
if (token->type == GPOINTER_TO_UINT (part->blocks->data))
|
||||
part->blocks = g_slist_remove (part->blocks, part->blocks->data);
|
||||
}
|
||||
else if (gtk_css_token_is (token, part->end_type))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (token->type)
|
||||
{
|
||||
case GTK_CSS_TOKEN_FUNCTION:
|
||||
case GTK_CSS_TOKEN_OPEN_PARENS:
|
||||
part->blocks = g_slist_prepend (part->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_PARENS));
|
||||
break;
|
||||
case GTK_CSS_TOKEN_OPEN_SQUARE:
|
||||
part->blocks = g_slist_prepend (part->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_SQUARE));
|
||||
break;
|
||||
case GTK_CSS_TOKEN_OPEN_CURLY:
|
||||
part->blocks = g_slist_prepend (part->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_CURLY));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token_as (part->source, consumer);
|
||||
}
|
||||
|
||||
static const GtkCssToken *
|
||||
gtk_css_token_source_part_peek_token (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourcePart *part = (GtkCssTokenSourcePart *) source;
|
||||
static const GtkCssToken eof_token = { GTK_CSS_TOKEN_EOF };
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_peek_token (part->source);
|
||||
if (part->blocks == NULL &&
|
||||
gtk_css_token_is (token, part->end_type))
|
||||
return &eof_token;
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_token_source_part_error (GtkCssTokenSource *source,
|
||||
const GError *error)
|
||||
{
|
||||
GtkCssTokenSourcePart *part = (GtkCssTokenSourcePart *) source;
|
||||
|
||||
gtk_css_token_source_emit_error (part->source, error);
|
||||
}
|
||||
|
||||
static GFile *
|
||||
gtk_css_token_source_part_get_location (GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssTokenSourcePart *part = (GtkCssTokenSourcePart *) source;
|
||||
|
||||
return gtk_css_token_source_get_location (part->source);
|
||||
}
|
||||
|
||||
const GtkCssTokenSourceClass GTK_CSS_TOKEN_SOURCE_PART = {
|
||||
gtk_css_token_source_part_finalize,
|
||||
gtk_css_token_source_part_consume_token,
|
||||
gtk_css_token_source_part_peek_token,
|
||||
gtk_css_token_source_part_error,
|
||||
gtk_css_token_source_part_get_location,
|
||||
};
|
||||
|
||||
GtkCssTokenSource *
|
||||
gtk_css_token_source_new_for_part (GtkCssTokenSource *source,
|
||||
GtkCssTokenType end_type)
|
||||
{
|
||||
GtkCssTokenSourcePart *part;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
g_return_val_if_fail (end_type != GTK_CSS_TOKEN_EOF, NULL);
|
||||
|
||||
part = gtk_css_token_source_new (GtkCssTokenSourcePart, >K_CSS_TOKEN_SOURCE_PART);
|
||||
part->source = gtk_css_token_source_ref (source);
|
||||
part->end_type = end_type;
|
||||
gtk_css_token_source_set_consumer (&part->parent,
|
||||
gtk_css_token_source_get_consumer (source));
|
||||
|
||||
return &part->parent;
|
||||
}
|
||||
|
||||
GtkCssTokenSource *
|
||||
gtk_css_token_source_alloc (gsize struct_size,
|
||||
const GtkCssTokenSourceClass *klass)
|
||||
{
|
||||
GtkCssTokenSource *source;
|
||||
|
||||
source = g_malloc0 (struct_size);
|
||||
source->klass = klass;
|
||||
source->ref_count = 1;
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
GtkCssTokenSource *
|
||||
gtk_css_token_source_ref (GtkCssTokenSource *source)
|
||||
{
|
||||
source->ref_count++;
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_token_source_unref (GtkCssTokenSource *source)
|
||||
{
|
||||
source->ref_count--;
|
||||
if (source->ref_count > 0)
|
||||
return;
|
||||
|
||||
source->klass->finalize (source);
|
||||
|
||||
g_clear_object (&source->consumer);
|
||||
|
||||
g_free (source);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gtk_css_token_source_consume_token (GtkCssTokenSource *source)
|
||||
{
|
||||
gtk_css_token_source_consume_token_as (source, source->consumer);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_token_source_consume_token_as (GtkCssTokenSource *source,
|
||||
GObject *consumer)
|
||||
{
|
||||
source->klass->consume_token (source, consumer);
|
||||
}
|
||||
|
||||
const GtkCssToken *
|
||||
gtk_css_token_source_peek_token (GtkCssTokenSource *source)
|
||||
{
|
||||
return source->klass->peek_token (source);
|
||||
}
|
||||
|
||||
const GtkCssToken *
|
||||
gtk_css_token_source_get_token (GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
for (token = gtk_css_token_source_peek_token (source);
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_COMMENT) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_WHITESPACE);
|
||||
token = gtk_css_token_source_peek_token (source))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_token_source_consume_all (GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
for (token = gtk_css_token_source_get_token (source);
|
||||
!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF);
|
||||
token = gtk_css_token_source_get_token (source))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
gtk_css_token_source_consume_to_string (GtkCssTokenSource *source)
|
||||
{
|
||||
GString *string;
|
||||
const GtkCssToken *token;
|
||||
|
||||
string = g_string_new (NULL);
|
||||
|
||||
for (token = gtk_css_token_source_peek_token (source);
|
||||
!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF);
|
||||
token = gtk_css_token_source_peek_token (source))
|
||||
{
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_COMMENT))
|
||||
continue;
|
||||
gtk_css_token_print (token, string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
|
||||
return g_string_free (string, FALSE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_css_token_source_consume_function (GtkCssTokenSource *source,
|
||||
guint min_args,
|
||||
guint max_args,
|
||||
guint (* parse_func) (GtkCssTokenSource *, guint, gpointer),
|
||||
gpointer data)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GtkCssTokenSource *func_source;
|
||||
gboolean result = FALSE;
|
||||
char *function_name;
|
||||
guint arg;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
g_return_val_if_fail (gtk_css_token_is (token, GTK_CSS_TOKEN_FUNCTION), FALSE);
|
||||
function_name = g_strdup (token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
func_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_CLOSE_PARENS);
|
||||
|
||||
arg = 0;
|
||||
while (arg < max_args)
|
||||
{
|
||||
guint parse_args = parse_func (func_source, arg, data);
|
||||
if (parse_args == 0)
|
||||
{
|
||||
gtk_css_token_source_consume_all (func_source);
|
||||
break;
|
||||
}
|
||||
arg += parse_args;
|
||||
token = gtk_css_token_source_get_token (func_source);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
|
||||
{
|
||||
if (arg < min_args)
|
||||
{
|
||||
gtk_css_token_source_error (source, "%s() requires at least %u arguments", function_name, min_args);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_COMMA))
|
||||
{
|
||||
gtk_css_token_source_consume_token (func_source);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (func_source, "Unexpected data at end of %s() argument", function_name);
|
||||
gtk_css_token_source_consume_all (func_source);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_css_token_source_unref (func_source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected ')' at end of %s()", function_name);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_free (function_name);
|
||||
return FALSE;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
g_free (function_name);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_css_token_source_consume_number (GtkCssTokenSource *source,
|
||||
double *number)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GtkCssValue *value;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_NUMBER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_NUMBER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER))
|
||||
{
|
||||
*number = token->number.number;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* because CSS allows calc() in numbers. Go CSS! */
|
||||
value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
|
||||
if (value == NULL)
|
||||
return FALSE;
|
||||
|
||||
*number = _gtk_css_number_value_get (value, 100);
|
||||
_gtk_css_value_unref (value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_css_token_source_consume_integer (GtkCssTokenSource *source,
|
||||
int *number)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER))
|
||||
{
|
||||
*number = token->number.number;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* XXX: parse calc() */
|
||||
gtk_css_token_source_error (source, "Expected an integer");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GFile *
|
||||
gtk_css_token_source_resolve_url (GtkCssTokenSource *source,
|
||||
const char *url)
|
||||
{
|
||||
char *scheme;
|
||||
GFile *file, *location, *base;
|
||||
|
||||
scheme = g_uri_parse_scheme (url);
|
||||
if (scheme != NULL)
|
||||
{
|
||||
file = g_file_new_for_uri (url);
|
||||
g_free (scheme);
|
||||
return file;
|
||||
}
|
||||
|
||||
location = gtk_css_token_source_get_location (source);
|
||||
if (location)
|
||||
{
|
||||
base = g_file_get_parent (location);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *dir = g_get_current_dir ();
|
||||
base = g_file_new_for_path (dir);
|
||||
g_free (dir);
|
||||
}
|
||||
|
||||
file = g_file_resolve_relative_path (base, url);
|
||||
g_object_unref (base);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
GFile *
|
||||
gtk_css_token_source_consume_url (GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GFile *file;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_URL))
|
||||
{
|
||||
file = gtk_css_token_source_resolve_url (source, token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return file;
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "url"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_STRING))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected string inside url()");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
file = gtk_css_token_source_resolve_url (source, token->string.string);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected closing ')' for url()");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (file);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return file;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected url()");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_token_source_emit_error (GtkCssTokenSource *source,
|
||||
const GError *error)
|
||||
{
|
||||
source->klass->error (source, error);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_token_source_error (GtkCssTokenSource *source,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
GError *error;
|
||||
|
||||
va_start (args, format);
|
||||
error = g_error_new_valist (GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
format, args);
|
||||
gtk_css_token_source_emit_error (source, error);
|
||||
g_error_free (error);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_token_source_unknown (GtkCssTokenSource *source,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
GError *error;
|
||||
|
||||
va_start (args, format);
|
||||
error = g_error_new_valist (GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
|
||||
format, args);
|
||||
gtk_css_token_source_emit_error (source, error);
|
||||
g_error_free (error);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_token_source_deprecated (GtkCssTokenSource *source,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
GError *error;
|
||||
|
||||
va_start (args, format);
|
||||
error = g_error_new_valist (GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_DEPRECATED,
|
||||
format, args);
|
||||
gtk_css_token_source_emit_error (source, error);
|
||||
g_error_free (error);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
GFile *
|
||||
gtk_css_token_source_get_location (GtkCssTokenSource *source)
|
||||
{
|
||||
return source->klass->get_location (source);
|
||||
}
|
||||
|
||||
GObject *
|
||||
gtk_css_token_source_get_consumer (GtkCssTokenSource *source)
|
||||
{
|
||||
return source->consumer;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_token_source_set_consumer (GtkCssTokenSource *source,
|
||||
GObject *consumer)
|
||||
{
|
||||
g_set_object (&source->consumer, consumer);
|
||||
}
|
||||
|
103
gtk/gtkcsstokensourceprivate.h
Normal file
103
gtk/gtkcsstokensourceprivate.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_TOKEN_SOURCE_PRIVATE_H__
|
||||
#define __GTK_CSS_TOKEN_SOURCE_PRIVATE_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include "gtk/gtkcsstokenizerprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkCssTokenSource GtkCssTokenSource;
|
||||
typedef struct _GtkCssTokenSourceClass GtkCssTokenSourceClass;
|
||||
|
||||
struct _GtkCssTokenSource
|
||||
{
|
||||
const GtkCssTokenSourceClass *klass;
|
||||
gint ref_count;
|
||||
GObject *consumer;
|
||||
};
|
||||
|
||||
struct _GtkCssTokenSourceClass
|
||||
{
|
||||
void (* finalize) (GtkCssTokenSource *source);
|
||||
void (* consume_token) (GtkCssTokenSource *source,
|
||||
GObject *consumer);
|
||||
const GtkCssToken * (* peek_token) (GtkCssTokenSource *source);
|
||||
void (* error) (GtkCssTokenSource *source,
|
||||
const GError *error);
|
||||
GFile * (* get_location) (GtkCssTokenSource *source);
|
||||
};
|
||||
|
||||
GtkCssTokenSource * gtk_css_token_source_new_for_tokenizer (GtkCssTokenizer *tokenizer,
|
||||
GFile *location);
|
||||
GtkCssTokenSource * gtk_css_token_source_new_for_part (GtkCssTokenSource *source,
|
||||
GtkCssTokenType end_type);
|
||||
|
||||
GtkCssTokenSource * gtk_css_token_source_ref (GtkCssTokenSource *source);
|
||||
void gtk_css_token_source_unref (GtkCssTokenSource *source);
|
||||
|
||||
#define gtk_css_token_source_new(type,klass) ((type *) gtk_css_token_source_alloc (sizeof (type), (klass)))
|
||||
GtkCssTokenSource * gtk_css_token_source_alloc (gsize struct_size,
|
||||
const GtkCssTokenSourceClass *klass);
|
||||
|
||||
void gtk_css_token_source_consume_token (GtkCssTokenSource *source);
|
||||
void gtk_css_token_source_consume_token_as (GtkCssTokenSource *source,
|
||||
GObject *consumer);
|
||||
const GtkCssToken * gtk_css_token_source_peek_token (GtkCssTokenSource *source);
|
||||
const GtkCssToken * gtk_css_token_source_get_token (GtkCssTokenSource *source);
|
||||
|
||||
void gtk_css_token_source_consume_all (GtkCssTokenSource *source);
|
||||
char * gtk_css_token_source_consume_to_string (GtkCssTokenSource *source);
|
||||
|
||||
gboolean gtk_css_token_source_consume_function (GtkCssTokenSource *source,
|
||||
guint min_args,
|
||||
guint max_args,
|
||||
guint (* parse_func) (GtkCssTokenSource *, guint, gpointer),
|
||||
gpointer data);
|
||||
gboolean gtk_css_token_source_consume_number (GtkCssTokenSource *source,
|
||||
double *number);
|
||||
gboolean gtk_css_token_source_consume_integer (GtkCssTokenSource *source,
|
||||
int *number);
|
||||
GFile * gtk_css_token_source_resolve_url (GtkCssTokenSource *source,
|
||||
const char *url);
|
||||
GFile * gtk_css_token_source_consume_url (GtkCssTokenSource *source);
|
||||
|
||||
void gtk_css_token_source_emit_error (GtkCssTokenSource *source,
|
||||
const GError *error);
|
||||
void gtk_css_token_source_error (GtkCssTokenSource *source,
|
||||
const char *format,
|
||||
...) G_GNUC_PRINTF(2, 3);
|
||||
void gtk_css_token_source_unknown (GtkCssTokenSource *source,
|
||||
const char *format,
|
||||
...) G_GNUC_PRINTF(2, 3);
|
||||
void gtk_css_token_source_deprecated (GtkCssTokenSource *source,
|
||||
const char *format,
|
||||
...) G_GNUC_PRINTF(2, 3);
|
||||
|
||||
GFile * gtk_css_token_source_get_location (GtkCssTokenSource *source);
|
||||
GObject * gtk_css_token_source_get_consumer (GtkCssTokenSource *source);
|
||||
void gtk_css_token_source_set_consumer (GtkCssTokenSource *source,
|
||||
GObject *consumer);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_TOKEN_SOURCE_PRIVATE_H__ */
|
@@ -1015,6 +1015,331 @@ _gtk_css_transform_value_parse (GtkCssParser *parser)
|
||||
return value;
|
||||
}
|
||||
|
||||
static guint
|
||||
token_parse_matrix (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssTransform *transform = data;
|
||||
|
||||
switch (n)
|
||||
{
|
||||
case 0:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xx) ? 1 : 0;
|
||||
case 1:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xy) ? 1 : 0;
|
||||
case 2:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.x0) ? 1 : 0;
|
||||
case 3:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yx) ? 1 : 0;
|
||||
case 4:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yy) ? 1 : 0;
|
||||
case 5:
|
||||
return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.y0) ? 1 : 0;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
token_parse_translate (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssTransform *transform = data;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
transform->translate.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH);
|
||||
if (transform->translate.x == NULL)
|
||||
return 0;
|
||||
transform->translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
|
||||
}
|
||||
else if (n == 1)
|
||||
{
|
||||
_gtk_css_value_unref (transform->translate.y);
|
||||
transform->translate.y = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH);
|
||||
if (transform->translate.y == NULL)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static guint
|
||||
token_parse_length (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssValue **value = data;
|
||||
|
||||
*value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH);
|
||||
if (*value == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static guint
|
||||
token_parse_scale (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssTransform *transform = data;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
transform->scale.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
|
||||
if (transform->scale.x == NULL)
|
||||
return 0;
|
||||
transform->scale.y = _gtk_css_value_ref (transform->scale.x);
|
||||
}
|
||||
else if (n == 1)
|
||||
{
|
||||
_gtk_css_value_unref (transform->scale.y);
|
||||
transform->scale.y = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
|
||||
if (transform->scale.y == NULL)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static guint
|
||||
token_parse_number (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssValue **value = data;
|
||||
|
||||
*value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
|
||||
if (*value == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static guint
|
||||
token_parse_angle (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssValue **value = data;
|
||||
|
||||
*value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
|
||||
if (*value == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static guint
|
||||
token_parse_skew (GtkCssTokenSource *source,
|
||||
guint n,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssTransform *transform = data;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
transform->skew.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
|
||||
if (transform->skew.x == NULL)
|
||||
return 0;
|
||||
transform->skew.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
|
||||
}
|
||||
else if (n == 1)
|
||||
{
|
||||
_gtk_css_value_unref (transform->skew.y);
|
||||
transform->skew.y = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
|
||||
if (transform->skew.y == NULL)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_transform_value_token_parse (GtkCssTokenSource *source)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GtkCssValue *value;
|
||||
GArray *array;
|
||||
guint i;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is_ident (token, "none"))
|
||||
{
|
||||
gtk_css_token_source_consume_token (source);
|
||||
return _gtk_css_transform_value_new_none ();
|
||||
}
|
||||
|
||||
array = g_array_new (FALSE, FALSE, sizeof (GtkCssTransform));
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GtkCssTransform transform = { 0, };
|
||||
|
||||
if (gtk_css_token_is_function (token, "matrix"))
|
||||
{
|
||||
transform.type = GTK_CSS_TRANSFORM_MATRIX;
|
||||
if (!gtk_css_token_source_consume_function (source, 6, 6, token_parse_matrix, &transform))
|
||||
goto fail;
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "translate"))
|
||||
{
|
||||
transform.type = GTK_CSS_TRANSFORM_TRANSLATE;
|
||||
if (!gtk_css_token_source_consume_function (source, 2, 2, token_parse_translate, &transform))
|
||||
{
|
||||
if (transform.translate.x)
|
||||
_gtk_css_value_unref (transform.translate.x);
|
||||
if (transform.translate.y)
|
||||
_gtk_css_value_unref (transform.translate.y);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "translateX"))
|
||||
{
|
||||
transform.type = GTK_CSS_TRANSFORM_TRANSLATE;
|
||||
if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_length, &transform.translate.x))
|
||||
{
|
||||
if (transform.translate.x)
|
||||
_gtk_css_value_unref (transform.translate.x);
|
||||
goto fail;
|
||||
}
|
||||
transform.translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "translateY"))
|
||||
{
|
||||
transform.type = GTK_CSS_TRANSFORM_TRANSLATE;
|
||||
if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_length, &transform.translate.y))
|
||||
{
|
||||
if (transform.translate.y)
|
||||
_gtk_css_value_unref (transform.translate.y);
|
||||
goto fail;
|
||||
}
|
||||
transform.translate.x = _gtk_css_number_value_new (0, GTK_CSS_PX);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "scale"))
|
||||
{
|
||||
transform.type = GTK_CSS_TRANSFORM_SCALE;
|
||||
if (!gtk_css_token_source_consume_function (source, 1, 2, token_parse_scale, &transform))
|
||||
{
|
||||
if (transform.scale.x)
|
||||
_gtk_css_value_unref (transform.scale.x);
|
||||
if (transform.scale.y)
|
||||
_gtk_css_value_unref (transform.scale.y);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "scaleX"))
|
||||
{
|
||||
transform.type = GTK_CSS_TRANSFORM_SCALE;
|
||||
|
||||
if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_number, &transform.scale.x))
|
||||
{
|
||||
if (transform.scale.x)
|
||||
_gtk_css_value_unref (transform.scale.x);
|
||||
goto fail;
|
||||
}
|
||||
transform.scale.y = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "scaleY"))
|
||||
{
|
||||
transform.type = GTK_CSS_TRANSFORM_SCALE;
|
||||
|
||||
if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_number, &transform.scale.y))
|
||||
{
|
||||
if (transform.scale.y)
|
||||
_gtk_css_value_unref (transform.scale.y);
|
||||
goto fail;
|
||||
}
|
||||
transform.scale.x = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "rotate"))
|
||||
{
|
||||
transform.type = GTK_CSS_TRANSFORM_ROTATE;
|
||||
|
||||
if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_angle, &transform.rotate.rotate))
|
||||
{
|
||||
if (transform.rotate.rotate)
|
||||
_gtk_css_value_unref (transform.rotate.rotate);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "skew"))
|
||||
{
|
||||
transform.type = GTK_CSS_TRANSFORM_SKEW;
|
||||
if (!gtk_css_token_source_consume_function (source, 1, 2, token_parse_skew, &transform))
|
||||
{
|
||||
if (transform.skew.x)
|
||||
_gtk_css_value_unref (transform.skew.x);
|
||||
if (transform.skew.y)
|
||||
_gtk_css_value_unref (transform.skew.y);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "skewX"))
|
||||
{
|
||||
transform.type = GTK_CSS_TRANSFORM_SKEW_X;
|
||||
|
||||
if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_angle, &transform.skew_x.skew))
|
||||
{
|
||||
if (transform.skew_x.skew)
|
||||
_gtk_css_value_unref (transform.skew_x.skew);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "skewY"))
|
||||
{
|
||||
transform.type = GTK_CSS_TRANSFORM_SKEW_Y;
|
||||
|
||||
if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_angle, &transform.skew_y.skew))
|
||||
{
|
||||
if (transform.skew_y.skew)
|
||||
_gtk_css_value_unref (transform.skew_y.skew);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
g_array_append_val (array, transform);
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
}
|
||||
|
||||
if (array->len == 0)
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a transform");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
value = gtk_css_transform_value_alloc (array->len);
|
||||
memcpy (value->transforms, array->data, sizeof (GtkCssTransform) * array->len);
|
||||
|
||||
g_array_free (array, TRUE);
|
||||
|
||||
return value;
|
||||
|
||||
fail:
|
||||
for (i = 0; i < array->len; i++)
|
||||
{
|
||||
gtk_css_transform_clear (&g_array_index (array, GtkCssTransform, i));
|
||||
}
|
||||
g_array_free (array, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_transform_value_get_matrix (const GtkCssValue *transform,
|
||||
cairo_matrix_t *matrix)
|
||||
|
@@ -21,12 +21,14 @@
|
||||
#define __GTK_CSS_TRANSFORM_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcsstokensourceprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GtkCssValue * _gtk_css_transform_value_new_none (void);
|
||||
GtkCssValue * _gtk_css_transform_value_parse (GtkCssParser *parser);
|
||||
GtkCssValue * gtk_css_transform_value_token_parse (GtkCssTokenSource *source);
|
||||
|
||||
gboolean _gtk_css_transform_value_get_matrix (const GtkCssValue *transform,
|
||||
cairo_matrix_t *matrix);
|
||||
|
197
gtk/gtkcsswidgetstyledeclaration.c
Normal file
197
gtk/gtkcsswidgetstyledeclaration.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcsswidgetstyledeclarationprivate.h"
|
||||
|
||||
#include "gtkwidget.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct _GtkCssWidgetStyleDeclarationPrivate GtkCssWidgetStyleDeclarationPrivate;
|
||||
struct _GtkCssWidgetStyleDeclarationPrivate {
|
||||
char *name;
|
||||
char *value;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssWidgetStyleDeclaration, gtk_css_widget_style_declaration, GTK_TYPE_CSS_DECLARATION)
|
||||
|
||||
static void
|
||||
gtk_css_widget_style_declaration_finalize (GObject *object)
|
||||
{
|
||||
GtkCssWidgetStyleDeclaration *widget_style = GTK_CSS_WIDGET_STYLE_DECLARATION (object);
|
||||
GtkCssWidgetStyleDeclarationPrivate *priv = gtk_css_widget_style_declaration_get_instance_private (widget_style);
|
||||
|
||||
g_free (priv->name);
|
||||
g_free (priv->value);
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_widget_style_declaration_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static const char *
|
||||
gtk_css_widget_style_declaration_get_name (GtkCssDeclaration *decl)
|
||||
{
|
||||
GtkCssWidgetStyleDeclaration *widget_style_declaration = GTK_CSS_WIDGET_STYLE_DECLARATION (decl);
|
||||
GtkCssWidgetStyleDeclarationPrivate *priv = gtk_css_widget_style_declaration_get_instance_private (widget_style_declaration);
|
||||
|
||||
return priv->name;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_widget_style_declaration_print_value (GtkCssDeclaration *decl,
|
||||
GString *string)
|
||||
{
|
||||
GtkCssWidgetStyleDeclaration *widget_style = GTK_CSS_WIDGET_STYLE_DECLARATION (decl);
|
||||
GtkCssWidgetStyleDeclarationPrivate *priv = gtk_css_widget_style_declaration_get_instance_private (widget_style);
|
||||
|
||||
g_string_append (string, priv->value);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_widget_style_declaration_class_init (GtkCssWidgetStyleDeclarationClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkCssDeclarationClass *decl_class = GTK_CSS_DECLARATION_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_widget_style_declaration_finalize;
|
||||
|
||||
decl_class->get_name = gtk_css_widget_style_declaration_get_name;
|
||||
decl_class->print_value = gtk_css_widget_style_declaration_print_value;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_widget_style_declaration_init (GtkCssWidgetStyleDeclaration *widget_style_declaration)
|
||||
{
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_css_widget_style_declaration_accepts_name (const char *name)
|
||||
{
|
||||
g_return_val_if_fail (name != NULL, FALSE);
|
||||
|
||||
if (name[0] != '-')
|
||||
return FALSE;
|
||||
|
||||
if (g_str_has_prefix (name, "-gtk-"))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
warn_if_deprecated (GtkCssTokenSource *source,
|
||||
const gchar *name)
|
||||
{
|
||||
gchar *n = NULL;
|
||||
gchar *p;
|
||||
const gchar *type_name;
|
||||
const gchar *property_name;
|
||||
GType type;
|
||||
GTypeClass *class = NULL;
|
||||
GParamSpec *pspec;
|
||||
|
||||
n = g_strdup (name);
|
||||
|
||||
/* skip initial - */
|
||||
type_name = n + 1;
|
||||
|
||||
p = strchr (type_name, '-');
|
||||
if (!p)
|
||||
goto out;
|
||||
|
||||
p[0] = '\0';
|
||||
property_name = p + 1;
|
||||
|
||||
type = g_type_from_name (type_name);
|
||||
if (type == G_TYPE_INVALID ||
|
||||
!g_type_is_a (type, GTK_TYPE_WIDGET))
|
||||
goto out;
|
||||
|
||||
class = g_type_class_ref (type);
|
||||
pspec = gtk_widget_class_find_style_property (GTK_WIDGET_CLASS (class), property_name);
|
||||
if (!pspec)
|
||||
goto out;
|
||||
|
||||
if (!(pspec->flags & G_PARAM_DEPRECATED))
|
||||
goto out;
|
||||
|
||||
gtk_css_token_source_deprecated (source,
|
||||
"The style property %s:%s is deprecated and shouldn't be "
|
||||
"used anymore. It will be removed in a future version",
|
||||
g_type_name (pspec->owner_type), pspec->name);
|
||||
|
||||
out:
|
||||
g_free (n);
|
||||
if (class)
|
||||
g_type_class_unref (class);
|
||||
}
|
||||
|
||||
GtkCssDeclaration *
|
||||
gtk_css_widget_style_declaration_new_parse (GtkCssStyleDeclaration *style,
|
||||
GtkCssTokenSource *source)
|
||||
{
|
||||
GtkCssWidgetStyleDeclarationPrivate *priv;
|
||||
const GtkCssToken *token;
|
||||
GtkCssWidgetStyleDeclaration *decl;
|
||||
|
||||
decl = g_object_new (GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION,
|
||||
"parent-style", style,
|
||||
NULL);
|
||||
priv = gtk_css_widget_style_declaration_get_instance_private (decl);
|
||||
|
||||
gtk_css_token_source_set_consumer (source, G_OBJECT (decl));
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Expected a property name");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (decl);
|
||||
return NULL;
|
||||
}
|
||||
if (!gtk_css_widget_style_declaration_accepts_name (token->string.string))
|
||||
{
|
||||
gtk_css_token_source_unknown (source, "Property name '%s' is not valid for a widget style property", token->string.string);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (decl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
priv->name = g_strdup (token->string.string);
|
||||
warn_if_deprecated (source, priv->name);
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COLON))
|
||||
{
|
||||
gtk_css_token_source_error (source, "No colon following property name");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
g_object_unref (decl);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
/* skip whitespace */
|
||||
gtk_css_token_source_get_token (source);
|
||||
priv->value = gtk_css_token_source_consume_to_string (source);
|
||||
|
||||
return GTK_CSS_DECLARATION (decl);
|
||||
}
|
||||
|
57
gtk/gtkcsswidgetstyledeclarationprivate.h
Normal file
57
gtk/gtkcsswidgetstyledeclarationprivate.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_WIDGET_STYLE_DECLARATION_PRIVATE_H__
|
||||
#define __GTK_CSS_WIDGET_STYLE_DECLARATION_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssdeclarationprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION (gtk_css_widget_style_declaration_get_type ())
|
||||
#define GTK_CSS_WIDGET_STYLE_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION, GtkCssWidgetStyleDeclaration))
|
||||
#define GTK_CSS_WIDGET_STYLE_DECLARATION_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION, GtkCssWidgetStyleDeclarationClass))
|
||||
#define GTK_IS_CSS_WIDGET_STYLE_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION))
|
||||
#define GTK_IS_CSS_WIDGET_STYLE_DECLARATION_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION))
|
||||
#define GTK_CSS_WIDGET_STYLE_DECLARATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION, GtkCssWidgetStyleDeclarationClass))
|
||||
|
||||
typedef struct _GtkCssWidgetStyleDeclaration GtkCssWidgetStyleDeclaration;
|
||||
typedef struct _GtkCssWidgetStyleDeclarationClass GtkCssWidgetStyleDeclarationClass;
|
||||
|
||||
struct _GtkCssWidgetStyleDeclaration
|
||||
{
|
||||
GtkCssDeclaration parent;
|
||||
};
|
||||
|
||||
struct _GtkCssWidgetStyleDeclarationClass
|
||||
{
|
||||
GtkCssDeclarationClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_widget_style_declaration_get_type (void) G_GNUC_CONST;
|
||||
|
||||
gboolean gtk_css_widget_style_declaration_accepts_name (const char *name);
|
||||
|
||||
GtkCssDeclaration * gtk_css_widget_style_declaration_new_parse (GtkCssStyleDeclaration *style,
|
||||
GtkCssTokenSource *source);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_WIDGET_STYLE_DECLARATION_PRIVATE_H__ */
|
@@ -33,13 +33,13 @@ typedef enum {
|
||||
} GtkWin32SizeType;
|
||||
|
||||
static const char *css_value_names[] = {
|
||||
"-gtk-win32-size(",
|
||||
"-gtk-win32-part-width(",
|
||||
"-gtk-win32-part-height(",
|
||||
"-gtk-win32-part-border-top(",
|
||||
"-gtk-win32-part-border-right(",
|
||||
"-gtk-win32-part-border-bottom(",
|
||||
"-gtk-win32-part-border-left("
|
||||
"-gtk-win32-size",
|
||||
"-gtk-win32-part-width",
|
||||
"-gtk-win32-part-height",
|
||||
"-gtk-win32-part-border-top",
|
||||
"-gtk-win32-part-border-right",
|
||||
"-gtk-win32-part-border-bottom",
|
||||
"-gtk-win32-part-border-left"
|
||||
};
|
||||
|
||||
struct _GtkCssValue {
|
||||
@@ -160,6 +160,7 @@ gtk_css_value_win32_size_print (const GtkCssValue *value,
|
||||
g_string_append_printf (string, "%g * ", value->scale);
|
||||
}
|
||||
g_string_append (string, css_value_names[value->type]);
|
||||
g_string_append (string, "(");
|
||||
gtk_win32_theme_print (value->theme, string);
|
||||
|
||||
switch (value->type)
|
||||
@@ -341,7 +342,7 @@ gtk_css_win32_size_value_parse (GtkCssParser *parser,
|
||||
|
||||
for (type = 0; type < G_N_ELEMENTS(css_value_names); type++)
|
||||
{
|
||||
if (_gtk_css_parser_try (parser, css_value_names[type], TRUE))
|
||||
if (_gtk_css_parser_try (parser, css_value_names[type], FALSE))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -351,6 +352,12 @@ gtk_css_win32_size_value_parse (GtkCssParser *parser,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try (parser, "(", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected '('");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
theme = gtk_win32_theme_parse (parser);
|
||||
if (theme == NULL)
|
||||
return NULL;
|
||||
@@ -399,3 +406,137 @@ gtk_css_win32_size_value_parse (GtkCssParser *parser,
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_win32_size_value_token_parse (GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags)
|
||||
{
|
||||
GtkWin32Theme *theme;
|
||||
const GtkCssToken *token;
|
||||
GtkCssValue *result;
|
||||
guint type;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
for (type = 0; type < G_N_ELEMENTS(css_value_names); type++)
|
||||
{
|
||||
if (gtk_css_token_is_function (token, css_value_names[type]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (type >= G_N_ELEMENTS(css_value_names))
|
||||
{
|
||||
gtk_css_token_source_error (source, "Not a win32 size value");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
theme = gtk_win32_theme_token_parse (source);
|
||||
if (theme == NULL)
|
||||
return NULL;
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COMMA))
|
||||
{
|
||||
gtk_win32_theme_unref (theme);
|
||||
gtk_css_token_source_error (source, "Expected ','");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
result = gtk_css_win32_size_value_new (1.0, theme, type);
|
||||
gtk_win32_theme_unref (theme);
|
||||
|
||||
switch (result->type)
|
||||
{
|
||||
case GTK_WIN32_SIZE:
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
|
||||
{
|
||||
result->val.size.id = gtk_win32_get_sys_metric_id_for_name (token->string.string);
|
||||
if (result->val.size.id == -1)
|
||||
{
|
||||
gtk_css_token_source_error (source, "'%s' is not a name for a win32 metric.", token->string.string);
|
||||
gtk_css_token_source_consume_all (source);
|
||||
_gtk_css_value_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER))
|
||||
{
|
||||
result->val.size.id = token->number.number;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gtk_css_value_unref (result);
|
||||
gtk_css_token_source_error (source, "Expected an integer ID");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case GTK_WIN32_PART_WIDTH:
|
||||
case GTK_WIN32_PART_HEIGHT:
|
||||
case GTK_WIN32_PART_BORDER_TOP:
|
||||
case GTK_WIN32_PART_BORDER_RIGHT:
|
||||
case GTK_WIN32_PART_BORDER_BOTTOM:
|
||||
case GTK_WIN32_PART_BORDER_LEFT:
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER) &&
|
||||
!gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER))
|
||||
{
|
||||
_gtk_css_value_unref (result);
|
||||
gtk_css_token_source_error (source, "Expected an integer part ID");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
result->val.part.part = token->number.number;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COMMA))
|
||||
{
|
||||
_gtk_css_value_unref (result);
|
||||
gtk_css_token_source_error (source, "Expected ','");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER) &&
|
||||
!gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER))
|
||||
{
|
||||
_gtk_css_value_unref (result);
|
||||
gtk_css_token_source_error (source, "Expected an integer state ID");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
result->val.part.state = token->number.number;
|
||||
gtk_css_token_source_consume_token (source);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
_gtk_css_value_unref (result);
|
||||
result = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
token = gtk_css_token_source_get_token (source);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
|
||||
{
|
||||
_gtk_css_value_unref (result);
|
||||
gtk_css_token_source_error (source, "Expected ')'");
|
||||
gtk_css_token_source_consume_all (source);
|
||||
return NULL;
|
||||
}
|
||||
gtk_css_token_source_consume_token (source);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@@ -26,6 +26,8 @@ G_BEGIN_DECLS
|
||||
|
||||
GtkCssValue * gtk_css_win32_size_value_parse (GtkCssParser *parser,
|
||||
GtkCssNumberParseFlags flags);
|
||||
GtkCssValue * gtk_css_win32_size_value_token_parse(GtkCssTokenSource *source,
|
||||
GtkCssNumberParseFlags flags);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -3011,7 +3011,19 @@ gtk_menu_draw (GtkWidget *widget,
|
||||
gtk_css_gadget_draw (priv->bottom_arrow_gadget, cr);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_menu_parent_class)->draw (widget, cr);
|
||||
if (gtk_cairo_should_draw_window (cr, priv->bin_window))
|
||||
{
|
||||
int x, y;
|
||||
|
||||
gdk_window_get_position (priv->view_window, &x, &y);
|
||||
cairo_rectangle (cr,
|
||||
x, y,
|
||||
gdk_window_get_width (priv->view_window),
|
||||
gdk_window_get_height (priv->view_window));
|
||||
cairo_clip (cr);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_menu_parent_class)->draw (widget, cr);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user