forked from AuroraMiddleware/gtk
css: Fix text-decoration-line support
This property needs to be treated as flags, not as enum, since it should be possible to specify more than one value, e.g. text-decoration-line: underline overline; Tests included. Fixes: #3621
This commit is contained in:
parent
b6e7acfb90
commit
1258fcaaf4
@ -545,58 +545,6 @@ _gtk_css_font_stretch_value_get (const GtkCssValue *value)
|
||||
return value->value;
|
||||
}
|
||||
|
||||
/* GtkTextDecorationLine */
|
||||
|
||||
static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_LINE = {
|
||||
"GtkCssTextDecorationLineValue",
|
||||
gtk_css_value_enum_free,
|
||||
gtk_css_value_enum_compute,
|
||||
gtk_css_value_enum_equal,
|
||||
gtk_css_value_enum_transition,
|
||||
NULL,
|
||||
NULL,
|
||||
gtk_css_value_enum_print
|
||||
};
|
||||
|
||||
static GtkCssValue text_decoration_line_values[] = {
|
||||
{ >K_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_NONE, "none" },
|
||||
{ >K_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE, "underline" },
|
||||
{ >K_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_OVERLINE, "overline" },
|
||||
{ >K_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH, "line-through" },
|
||||
};
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line)
|
||||
{
|
||||
g_return_val_if_fail (line < G_N_ELEMENTS (text_decoration_line_values), NULL);
|
||||
|
||||
return _gtk_css_value_ref (&text_decoration_line_values[line]);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_text_decoration_line_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (parser != NULL, NULL);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (text_decoration_line_values); i++)
|
||||
{
|
||||
if (gtk_css_parser_try_ident (parser, text_decoration_line_values[i].name))
|
||||
return _gtk_css_value_ref (&text_decoration_line_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkTextDecorationLine
|
||||
_gtk_css_text_decoration_line_value_get (const GtkCssValue *value)
|
||||
{
|
||||
g_return_val_if_fail (value->class == >K_CSS_VALUE_TEXT_DECORATION_LINE, GTK_CSS_TEXT_DECORATION_LINE_NONE);
|
||||
|
||||
return value->value;
|
||||
}
|
||||
|
||||
/* GtkTextDecorationStyle */
|
||||
|
||||
static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_STYLE = {
|
||||
@ -1204,6 +1152,99 @@ gtk_css_value_flags_print (const FlagsValue *values,
|
||||
}
|
||||
}
|
||||
|
||||
/* GtkTextDecorationLine */
|
||||
|
||||
static FlagsValue text_decoration_line_values[] = {
|
||||
{ GTK_CSS_TEXT_DECORATION_LINE_NONE, "none" },
|
||||
{ GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE, "underline" },
|
||||
{ GTK_CSS_TEXT_DECORATION_LINE_OVERLINE, "overline" },
|
||||
{ GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH, "line-through" },
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_css_text_decoration_line_value_print (const GtkCssValue *value,
|
||||
GString *string)
|
||||
{
|
||||
gtk_css_value_flags_print (text_decoration_line_values,
|
||||
G_N_ELEMENTS (text_decoration_line_values),
|
||||
value, string);
|
||||
}
|
||||
|
||||
static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_LINE = {
|
||||
"GtkCssTextDecorationLine",
|
||||
gtk_css_value_enum_free,
|
||||
gtk_css_value_enum_compute,
|
||||
gtk_css_value_flags_equal,
|
||||
gtk_css_value_enum_transition,
|
||||
NULL,
|
||||
NULL,
|
||||
gtk_css_text_decoration_line_value_print
|
||||
};
|
||||
|
||||
static gboolean
|
||||
text_decoration_line_is_valid (GtkTextDecorationLine line)
|
||||
{
|
||||
if ((line & GTK_CSS_TEXT_DECORATION_LINE_NONE) &&
|
||||
(line != GTK_CSS_TEXT_DECORATION_LINE_NONE))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line)
|
||||
{
|
||||
GtkCssValue *value;
|
||||
|
||||
if (!text_decoration_line_is_valid (line))
|
||||
return NULL;
|
||||
|
||||
value = _gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_TEXT_DECORATION_LINE);
|
||||
value->value = line;
|
||||
value->name = NULL;
|
||||
value->is_computed = TRUE;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
GtkTextDecorationLine
|
||||
_gtk_css_text_decoration_line_try_parse_one (GtkCssParser *parser,
|
||||
GtkTextDecorationLine base)
|
||||
{
|
||||
guint i;
|
||||
GtkTextDecorationLine value = 0;
|
||||
|
||||
g_return_val_if_fail (parser != NULL, 0);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (text_decoration_line_values); i++)
|
||||
{
|
||||
if (gtk_css_parser_try_ident (parser, text_decoration_line_values[i].name))
|
||||
{
|
||||
value = text_decoration_line_values[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (value == 0)
|
||||
return base; /* not parsing this value */
|
||||
|
||||
if ((base | value) == base)
|
||||
return 0; /* repeated value */
|
||||
|
||||
if (!text_decoration_line_is_valid (base | value))
|
||||
return 0; /* bad combination */
|
||||
|
||||
return base | value;
|
||||
}
|
||||
|
||||
GtkTextDecorationLine
|
||||
_gtk_css_text_decoration_line_value_get (const GtkCssValue *value)
|
||||
{
|
||||
g_return_val_if_fail (value->class == >K_CSS_VALUE_TEXT_DECORATION_LINE, GTK_CSS_TEXT_DECORATION_LINE_NONE);
|
||||
|
||||
return value->value;
|
||||
}
|
||||
|
||||
/* GtkCssFontVariantLigature */
|
||||
|
||||
static FlagsValue font_variant_ligature_values[] = {
|
||||
|
@ -54,11 +54,12 @@ GtkCssValue * _gtk_css_font_stretch_value_new (PangoStretch stretc
|
||||
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_try_parse (GtkCssParser *parser);
|
||||
GtkTextDecorationLine _gtk_css_text_decoration_line_value_get (const GtkCssValue *value);
|
||||
GtkCssValue * _gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line);
|
||||
GtkTextDecorationLine _gtk_css_text_decoration_line_try_parse_one (GtkCssParser *parser,
|
||||
GtkTextDecorationLine base);
|
||||
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_new (GtkTextDecorationStyle style);
|
||||
GtkCssValue * _gtk_css_text_decoration_style_value_try_parse (GtkCssParser *parser);
|
||||
GtkTextDecorationStyle _gtk_css_text_decoration_style_value_get (const GtkCssValue *value);
|
||||
|
||||
|
@ -865,16 +865,26 @@ parse_text_decoration (GtkCssShorthandProperty *shorthand,
|
||||
GtkCssValue **values,
|
||||
GtkCssParser *parser)
|
||||
{
|
||||
GtkTextDecorationLine line = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (values[0] == NULL &&
|
||||
(values[0] = _gtk_css_text_decoration_line_value_try_parse (parser)))
|
||||
GtkTextDecorationLine parsed_line;
|
||||
|
||||
parsed_line = _gtk_css_text_decoration_line_try_parse_one (parser, line);
|
||||
|
||||
if (parsed_line == 0 && line != 0)
|
||||
{
|
||||
if (values[0] == NULL)
|
||||
return FALSE;
|
||||
gtk_css_parser_error_value (parser, "Invalid combination of text-decoration-line values");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (parsed_line != line)
|
||||
{
|
||||
line = parsed_line;
|
||||
}
|
||||
else if (values[1] == NULL &&
|
||||
(values[1] = _gtk_css_text_decoration_style_value_try_parse (parser)))
|
||||
(values[1] = _gtk_css_text_decoration_style_value_try_parse (parser)))
|
||||
{
|
||||
if (values[1] == NULL)
|
||||
return FALSE;
|
||||
@ -895,6 +905,16 @@ parse_text_decoration (GtkCssShorthandProperty *shorthand,
|
||||
}
|
||||
while (!value_is_done_parsing (parser));
|
||||
|
||||
if (line != 0)
|
||||
{
|
||||
values[0] = _gtk_css_text_decoration_line_value_new (line);
|
||||
if (values[0] == NULL)
|
||||
{
|
||||
gtk_css_parser_error_value (parser, "Invalid combination of text-decoration-line values");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -451,32 +451,29 @@ gtk_css_style_get_pango_attributes (GtkCssStyle *style)
|
||||
? style->font_variant->text_decoration_color
|
||||
: style->core->color);
|
||||
|
||||
switch (decoration_line)
|
||||
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE)
|
||||
{
|
||||
case GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE:
|
||||
attrs = add_pango_attr (attrs, pango_attr_underline_new (get_pango_underline_from_style (decoration_style)));
|
||||
if (!gdk_rgba_equal (color, decoration_color))
|
||||
attrs = add_pango_attr (attrs, pango_attr_underline_color_new (decoration_color->red * 65535. + 0.5,
|
||||
decoration_color->green * 65535. + 0.5,
|
||||
decoration_color->blue * 65535. + 0.5));
|
||||
break;
|
||||
case GTK_CSS_TEXT_DECORATION_LINE_OVERLINE:
|
||||
}
|
||||
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_OVERLINE)
|
||||
{
|
||||
attrs = add_pango_attr (attrs, pango_attr_overline_new (get_pango_overline_from_style (decoration_style)));
|
||||
if (!gdk_rgba_equal (color, decoration_color))
|
||||
attrs = add_pango_attr (attrs, pango_attr_overline_color_new (decoration_color->red * 65535. + 0.5,
|
||||
decoration_color->green * 65535. + 0.5,
|
||||
decoration_color->blue * 65535. + 0.5));
|
||||
break;
|
||||
case GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH:
|
||||
}
|
||||
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH)
|
||||
{
|
||||
attrs = add_pango_attr (attrs, pango_attr_strikethrough_new (TRUE));
|
||||
if (!gdk_rgba_equal (color, decoration_color))
|
||||
attrs = add_pango_attr (attrs, pango_attr_strikethrough_color_new (decoration_color->red * 65535. + 0.5,
|
||||
decoration_color->green * 65535. + 0.5,
|
||||
decoration_color->blue * 65535. + 0.5));
|
||||
break;
|
||||
case GTK_CSS_TEXT_DECORATION_LINE_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* letter-spacing */
|
||||
|
@ -317,14 +317,38 @@ parse_letter_spacing (GtkCssStyleProperty *property,
|
||||
return _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
value_is_done_parsing (GtkCssParser *parser)
|
||||
{
|
||||
return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_COMMA) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SEMICOLON) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_CLOSE_CURLY);
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
parse_text_decoration_line (GtkCssStyleProperty *property,
|
||||
GtkCssParser *parser)
|
||||
{
|
||||
GtkCssValue *value = _gtk_css_text_decoration_line_value_try_parse (parser);
|
||||
GtkCssValue *value = NULL;
|
||||
GtkTextDecorationLine line;
|
||||
|
||||
line = 0;
|
||||
do {
|
||||
GtkTextDecorationLine parsed;
|
||||
|
||||
parsed = _gtk_css_text_decoration_line_try_parse_one (parser, line);
|
||||
if (parsed == 0 || parsed == line)
|
||||
{
|
||||
gtk_css_parser_error_syntax (parser, "Not a valid value");
|
||||
return NULL;
|
||||
}
|
||||
line = parsed;
|
||||
} while (!value_is_done_parsing (parser));
|
||||
|
||||
value = _gtk_css_text_decoration_line_value_new (line);
|
||||
if (value == NULL)
|
||||
gtk_css_parser_error_syntax (parser, "unknown text decoration line value");
|
||||
gtk_css_parser_error_syntax (parser, "Invalid combination of values");
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -353,15 +377,6 @@ parse_font_kerning (GtkCssStyleProperty *property,
|
||||
return value;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
value_is_done_parsing (GtkCssParser *parser)
|
||||
{
|
||||
return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_COMMA) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SEMICOLON) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_CLOSE_CURLY);
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
parse_font_variant_ligatures (GtkCssStyleProperty *property,
|
||||
GtkCssParser *parser)
|
||||
|
@ -325,10 +325,10 @@ typedef enum /*< skip >*/ {
|
||||
} GtkCssFontSize;
|
||||
|
||||
typedef enum /*< skip >*/ {
|
||||
GTK_CSS_TEXT_DECORATION_LINE_NONE,
|
||||
GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE,
|
||||
GTK_CSS_TEXT_DECORATION_LINE_OVERLINE,
|
||||
GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH
|
||||
GTK_CSS_TEXT_DECORATION_LINE_NONE = 1 << 0,
|
||||
GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE = 1 << 1,
|
||||
GTK_CSS_TEXT_DECORATION_LINE_OVERLINE = 1 << 2,
|
||||
GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH = 1 << 3
|
||||
} GtkTextDecorationLine;
|
||||
|
||||
typedef enum /*< skip >*/ {
|
||||
|
@ -423,6 +423,8 @@ test_data = [
|
||||
'string-values.css',
|
||||
'string-values.ref.css',
|
||||
'test.png',
|
||||
'text-decoration.css',
|
||||
'text-decoration.ref.css',
|
||||
'text-decoration-color.css',
|
||||
'text-decoration-color.ref.css',
|
||||
'text-decoration-line.css',
|
||||
|
@ -21,3 +21,11 @@ e {
|
||||
f {
|
||||
text-decoration-line: line-through;
|
||||
}
|
||||
|
||||
g {
|
||||
text-decoration-line: overline;
|
||||
}
|
||||
|
||||
h {
|
||||
text-decoration-line: underline overline;
|
||||
}
|
||||
|
@ -21,3 +21,11 @@ e {
|
||||
f {
|
||||
text-decoration-line: line-through;
|
||||
}
|
||||
|
||||
g {
|
||||
text-decoration-line: overline;
|
||||
}
|
||||
|
||||
h {
|
||||
text-decoration-line: underline overline;
|
||||
}
|
||||
|
23
testsuite/css/parser/text-decoration.css
Normal file
23
testsuite/css/parser/text-decoration.css
Normal file
@ -0,0 +1,23 @@
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
b {
|
||||
text-decoration: wavy;
|
||||
}
|
||||
|
||||
c {
|
||||
text-decoration: red;
|
||||
}
|
||||
|
||||
d {
|
||||
text-decoration: red wavy;
|
||||
}
|
||||
|
||||
e {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
f {
|
||||
text-decoration: red underline wavy overline;
|
||||
}
|
35
testsuite/css/parser/text-decoration.ref.css
Normal file
35
testsuite/css/parser/text-decoration.ref.css
Normal file
@ -0,0 +1,35 @@
|
||||
a {
|
||||
text-decoration-color: initial;
|
||||
text-decoration-line: underline;
|
||||
text-decoration-style: initial;
|
||||
}
|
||||
|
||||
b {
|
||||
text-decoration-color: initial;
|
||||
text-decoration-line: initial;
|
||||
text-decoration-style: wavy;
|
||||
}
|
||||
|
||||
c {
|
||||
text-decoration-color: rgb(255,0,0);
|
||||
text-decoration-line: initial;
|
||||
text-decoration-style: initial;
|
||||
}
|
||||
|
||||
d {
|
||||
text-decoration-color: rgb(255,0,0);
|
||||
text-decoration-line: initial;
|
||||
text-decoration-style: wavy;
|
||||
}
|
||||
|
||||
e {
|
||||
text-decoration-color: initial;
|
||||
text-decoration-line: none;
|
||||
text-decoration-style: initial;
|
||||
}
|
||||
|
||||
f {
|
||||
text-decoration-color: rgb(255,0,0);
|
||||
text-decoration-line: underline overline;
|
||||
text-decoration-style: wavy;
|
||||
}
|
Loading…
Reference in New Issue
Block a user