css: Use enums instead of idents for font-variant properties

As Benjamin says, ident should only be used if any value
is valid, which is not the case here. So use enums instead,
which should also be more efficient. To handle the more
complicated cases like font-variant-ligatures, we have to
introduce flags-like values.
This commit is contained in:
Matthias Clasen 2017-09-18 18:38:16 -04:00
parent 01911b5ecd
commit 6859f0a6d1
6 changed files with 958 additions and 475 deletions

View File

@ -936,3 +936,570 @@ _gtk_css_icon_style_value_get (const GtkCssValue *value)
return value->value;
}
/* GtkCssFontKerning */
static const GtkCssValueClass GTK_CSS_VALUE_FONT_KERNING = {
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
gtk_css_value_enum_transition,
gtk_css_value_enum_print
};
static GtkCssValue font_kerning_values[] = {
{ &GTK_CSS_VALUE_FONT_KERNING, 1, GTK_CSS_FONT_KERNING_AUTO, "auto" },
{ &GTK_CSS_VALUE_FONT_KERNING, 1, GTK_CSS_FONT_KERNING_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_KERNING, 1, GTK_CSS_FONT_KERNING_NONE, "none" }
};
GtkCssValue *
_gtk_css_font_kerning_value_new (GtkCssFontKerning kerning)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (font_kerning_values); i++)
{
if (font_kerning_values[i].value == kerning)
return _gtk_css_value_ref (&font_kerning_values[i]);
}
g_return_val_if_reached (NULL);
}
GtkCssValue *
_gtk_css_font_kerning_value_try_parse (GtkCssParser *parser)
{
guint i;
g_return_val_if_fail (parser != NULL, NULL);
for (i = 0; i < G_N_ELEMENTS (font_kerning_values); i++)
{
if (_gtk_css_parser_try (parser, font_kerning_values[i].name, TRUE))
return _gtk_css_value_ref (&font_kerning_values[i]);
}
return NULL;
}
GtkCssFontKerning
_gtk_css_font_kerning_value_get (const GtkCssValue *value)
{
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_KERNING, GTK_CSS_FONT_KERNING_AUTO);
return value->value;
}
/* GtkCssFontVariantPos */
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_POSITION = {
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
gtk_css_value_enum_transition,
gtk_css_value_enum_print
};
static GtkCssValue font_variant_position_values[] = {
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, GTK_CSS_FONT_VARIANT_POSITION_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, GTK_CSS_FONT_VARIANT_POSITION_SUB, "sub" },
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, GTK_CSS_FONT_VARIANT_POSITION_SUPER, "super" }
};
GtkCssValue *
_gtk_css_font_variant_position_value_new (GtkCssFontVariantPosition position)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (font_variant_position_values); i++)
{
if (font_variant_position_values[i].value == position)
return _gtk_css_value_ref (&font_variant_position_values[i]);
}
g_return_val_if_reached (NULL);
}
GtkCssValue *
_gtk_css_font_variant_position_value_try_parse (GtkCssParser *parser)
{
guint i;
g_return_val_if_fail (parser != NULL, NULL);
for (i = 0; i < G_N_ELEMENTS (font_variant_position_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_position_values[i].name, TRUE))
return _gtk_css_value_ref (&font_variant_position_values[i]);
}
return NULL;
}
GtkCssFontVariantPosition
_gtk_css_font_variant_position_value_get (const GtkCssValue *value)
{
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_POSITION, GTK_CSS_FONT_VARIANT_POSITION_NORMAL);
return value->value;
}
/* GtkCssFontVariantCaps */
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_CAPS = {
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
gtk_css_value_enum_transition,
gtk_css_value_enum_print
};
static GtkCssValue font_variant_caps_values[] = {
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_SMALL_CAPS, "small-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_ALL_SMALL_CAPS, "all-small-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_PETITE_CAPS, "petite-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_ALL_PETITE_CAPS, "all-petite-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_UNICASE, "unicase" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_TITLING_CAPS, "titling-caps" }
};
GtkCssValue *
_gtk_css_font_variant_caps_value_new (GtkCssFontVariantCaps caps)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (font_variant_caps_values); i++)
{
if (font_variant_caps_values[i].value == caps)
return _gtk_css_value_ref (&font_variant_caps_values[i]);
}
g_return_val_if_reached (NULL);
}
GtkCssValue *
_gtk_css_font_variant_caps_value_try_parse (GtkCssParser *parser)
{
guint i;
g_return_val_if_fail (parser != NULL, NULL);
for (i = 0; i < G_N_ELEMENTS (font_variant_caps_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_caps_values[i].name, TRUE))
return _gtk_css_value_ref (&font_variant_caps_values[i]);
}
return NULL;
}
GtkCssFontVariantCaps
_gtk_css_font_variant_caps_value_get (const GtkCssValue *value)
{
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_CAPS, GTK_CSS_FONT_VARIANT_CAPS_NORMAL);
return value->value;
}
/* GtkCssFontVariantAlternate */
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE = {
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
gtk_css_value_enum_transition,
gtk_css_value_enum_print
};
static GtkCssValue font_variant_alternate_values[] = {
{ &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, GTK_CSS_FONT_VARIANT_ALTERNATE_HISTORICAL_FORMS, "historical-forms" }
};
GtkCssValue *
_gtk_css_font_variant_alternate_value_new (GtkCssFontVariantAlternate alternate)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (font_variant_alternate_values); i++)
{
if (font_variant_alternate_values[i].value == alternate)
return _gtk_css_value_ref (&font_variant_alternate_values[i]);
}
g_return_val_if_reached (NULL);
}
GtkCssValue *
_gtk_css_font_variant_alternate_value_try_parse (GtkCssParser *parser)
{
guint i;
g_return_val_if_fail (parser != NULL, NULL);
for (i = 0; i < G_N_ELEMENTS (font_variant_alternate_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_alternate_values[i].name, TRUE))
return _gtk_css_value_ref (&font_variant_alternate_values[i]);
}
return NULL;
}
GtkCssFontVariantAlternate
_gtk_css_font_variant_alternate_value_get (const GtkCssValue *value)
{
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL);
return value->value;
}
/* below are flags, which are handle a bit differently. We allocate values dynamically,
* and we parse one bit at a time, while allowing for detection of invalid combinations.
*/
typedef struct {
int value;
const char *name;
} FlagsValue;
static gboolean
gtk_css_value_flags_equal (const GtkCssValue *enum1,
const GtkCssValue *enum2)
{
return enum1->value == enum2->value;
}
static void
gtk_css_value_flags_print (const FlagsValue *values,
guint n_values,
const GtkCssValue *value,
GString *string)
{
guint i;
const char *sep = "";
for (i = 0; i < n_values; i++)
{
if (value->value & values[i].value)
{
g_string_append (string, sep);
g_string_append (string, values[i].name);
sep = " ";
}
}
}
/* GtkCssFontVariantLigature */
static FlagsValue font_variant_ligature_values[] = {
{ GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL, "normal" },
{ GTK_CSS_FONT_VARIANT_LIGATURE_NONE, "none" },
{ GTK_CSS_FONT_VARIANT_LIGATURE_COMMON_LIGATURES, "common-ligatures" },
{ GTK_CSS_FONT_VARIANT_LIGATURE_NO_COMMON_LIGATURES, "no-common-ligatures" },
{ GTK_CSS_FONT_VARIANT_LIGATURE_DISCRETIONARY_LIGATURES, "discretionary-ligatures" },
{ GTK_CSS_FONT_VARIANT_LIGATURE_NO_DISCRETIONARY_LIGATURES, "no-discretionary-ligatures" },
{ GTK_CSS_FONT_VARIANT_LIGATURE_HISTORICAL_LIGATURES, "historical-ligatures" },
{ GTK_CSS_FONT_VARIANT_LIGATURE_NO_HISTORICAL_LIGATURES, "no-historical-ligatures" },
{ GTK_CSS_FONT_VARIANT_LIGATURE_CONTEXTUAL, "contextual" },
{ GTK_CSS_FONT_VARIANT_LIGATURE_NO_CONTEXTUAL, "no-contextual" }
};
static void
gtk_css_font_variant_ligature_value_print (const GtkCssValue *value,
GString *string)
{
gtk_css_value_flags_print (font_variant_ligature_values,
G_N_ELEMENTS (font_variant_ligature_values),
value, string);
}
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_LIGATURE = {
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_flags_equal,
gtk_css_value_enum_transition,
gtk_css_font_variant_ligature_value_print
};
static gboolean
ligature_value_is_valid (GtkCssFontVariantLigature ligatures)
{
if (((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL) &&
(ligatures != GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL)) ||
((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NONE) &&
(ligatures != GTK_CSS_FONT_VARIANT_LIGATURE_NONE)) ||
((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_COMMON_LIGATURES) &&
(ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_COMMON_LIGATURES)) ||
((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_DISCRETIONARY_LIGATURES) &&
(ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_DISCRETIONARY_LIGATURES)) ||
((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_HISTORICAL_LIGATURES) &&
(ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_HISTORICAL_LIGATURES)) ||
((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_CONTEXTUAL) &&
(ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_CONTEXTUAL)))
return FALSE;
return TRUE;
}
GtkCssValue *
_gtk_css_font_variant_ligature_value_new (GtkCssFontVariantLigature ligatures)
{
GtkCssValue *value;
if (!ligature_value_is_valid (ligatures))
return NULL;
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_FONT_VARIANT_LIGATURE);
value->value = ligatures;
value->name = NULL;
return value;
}
GtkCssFontVariantLigature
_gtk_css_font_variant_ligature_try_parse_one (GtkCssParser *parser,
GtkCssFontVariantLigature base)
{
guint i;
GtkCssFontVariantLigature value = 0;
g_return_val_if_fail (parser != NULL, 0);
for (i = 0; i < G_N_ELEMENTS (font_variant_ligature_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_ligature_values[i].name, TRUE))
{
value = font_variant_ligature_values[i].value;
break;
}
}
if (value == 0)
return base; /* not parsing this value */
if ((base | value) == base)
return 0; /* repeated value */
if (!ligature_value_is_valid (base | value))
return 0; /* bad combination */
return base | value;
}
GtkCssFontVariantLigature
_gtk_css_font_variant_ligature_value_get (const GtkCssValue *value)
{
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_LIGATURE, GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL);
return value->value;
}
/* GtkCssFontVariantNumeric */
static FlagsValue font_variant_numeric_values[] = {
{ GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL, "normal" },
{ GTK_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS, "lining-nums" },
{ GTK_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS, "oldstyle-nums" },
{ GTK_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS, "proportional-nums" },
{ GTK_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS, "tabular-nums" },
{ GTK_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS, "diagonal-fractions" },
{ GTK_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS, "stacked-fractions" },
{ GTK_CSS_FONT_VARIANT_NUMERIC_ORDINAL, "ordinal" },
{ GTK_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO, "slashed-zero" }
};
static void
gtk_css_font_variant_numeric_value_print (const GtkCssValue *value,
GString *string)
{
gtk_css_value_flags_print (font_variant_numeric_values,
G_N_ELEMENTS (font_variant_numeric_values),
value, string);
}
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_NUMERIC = {
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_flags_equal,
gtk_css_value_enum_transition,
gtk_css_font_variant_numeric_value_print
};
static gboolean
numeric_value_is_valid (GtkCssFontVariantNumeric numeric)
{
if (((numeric & GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL) &&
(numeric != GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL)) ||
((numeric & GTK_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS) &&
(numeric & GTK_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS)) ||
((numeric & GTK_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS) &&
(numeric & GTK_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS)) ||
((numeric & GTK_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS) &&
(numeric & GTK_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS)))
return FALSE;
return TRUE;
}
GtkCssValue *
_gtk_css_font_variant_numeric_value_new (GtkCssFontVariantNumeric numeric)
{
GtkCssValue *value;
if (!numeric_value_is_valid (numeric))
return NULL;
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_FONT_VARIANT_NUMERIC);
value->value = numeric;
value->name = NULL;
return value;
}
GtkCssFontVariantNumeric
_gtk_css_font_variant_numeric_try_parse_one (GtkCssParser *parser,
GtkCssFontVariantNumeric base)
{
guint i;
GtkCssFontVariantNumeric value = 0;
g_return_val_if_fail (parser != NULL, 0);
for (i = 0; i < G_N_ELEMENTS (font_variant_numeric_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_numeric_values[i].name, TRUE))
{
value = font_variant_numeric_values[i].value;
break;
}
}
if (value == 0)
return base; /* not parsing this value */
if ((base | value) == base)
return 0; /* repeated value */
if (!numeric_value_is_valid (base | value))
return 0; /* bad combination */
return base | value;
}
GtkCssFontVariantNumeric
_gtk_css_font_variant_numeric_value_get (const GtkCssValue *value)
{
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_NUMERIC, GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL);
return value->value;
}
/* GtkCssFontVariantEastAsian */
static FlagsValue font_variant_east_asian_values[] = {
{ GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL, "normal" },
{ GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS78, "jis78" },
{ GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS83, "jis83" },
{ GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS90, "jis90" },
{ GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS04, "jis04" },
{ GTK_CSS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED, "simplified" },
{ GTK_CSS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL, "traditional" },
{ GTK_CSS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH, "full-width" },
{ GTK_CSS_FONT_VARIANT_EAST_ASIAN_PROPORTIONAL, "proportional-width" },
{ GTK_CSS_FONT_VARIANT_EAST_ASIAN_RUBY, "ruby" }
};
static void
gtk_css_font_variant_east_asian_value_print (const GtkCssValue *value,
GString *string)
{
gtk_css_value_flags_print (font_variant_east_asian_values,
G_N_ELEMENTS (font_variant_east_asian_values),
value, string);
}
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN = {
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_flags_equal,
gtk_css_value_enum_transition,
gtk_css_font_variant_east_asian_value_print
};
static gboolean
east_asian_value_is_valid (GtkCssFontVariantEastAsian east_asian)
{
if ((east_asian & GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL) &&
(east_asian != GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL))
return FALSE;
if (__builtin_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS78 |
GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS83 |
GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS90 |
GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS04 |
GTK_CSS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED |
GTK_CSS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL)) > 1)
return FALSE;
if (__builtin_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH |
GTK_CSS_FONT_VARIANT_EAST_ASIAN_PROPORTIONAL)) > 1)
return FALSE;
return TRUE;
}
GtkCssValue *
_gtk_css_font_variant_east_asian_value_new (GtkCssFontVariantEastAsian east_asian)
{
GtkCssValue *value;
if (!east_asian_value_is_valid (east_asian))
return NULL;
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN);
value->value = east_asian;
value->name = NULL;
return value;
}
GtkCssFontVariantEastAsian
_gtk_css_font_variant_east_asian_try_parse_one (GtkCssParser *parser,
GtkCssFontVariantEastAsian base)
{
guint i;
GtkCssFontVariantEastAsian value = 0;
g_return_val_if_fail (parser != NULL, 0);
for (i = 0; i < G_N_ELEMENTS (font_variant_east_asian_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_east_asian_values[i].name, TRUE))
{
value = font_variant_east_asian_values[i].value;
break;
}
}
if (value == 0)
return base; /* not parsing this value */
if ((base | value) == base)
return 0; /* repeated value */
if (!east_asian_value_is_valid (base | value))
return 0; /* bad combination */
return base | value;
}
GtkCssFontVariantEastAsian
_gtk_css_font_variant_east_asian_value_get (const GtkCssValue *value)
{
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN, GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL);
return value->value;
}

View File

@ -81,6 +81,38 @@ GtkCssValue * _gtk_css_icon_style_value_new (GtkCssIconStyle icon_s
GtkCssValue * _gtk_css_icon_style_value_try_parse (GtkCssParser *parser);
GtkCssIconStyle _gtk_css_icon_style_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_font_kerning_value_new (GtkCssFontKerning kerning);
GtkCssValue * _gtk_css_font_kerning_value_try_parse (GtkCssParser *parser);
GtkCssFontKerning _gtk_css_font_kerning_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_font_variant_position_value_new (GtkCssFontVariantPosition position);
GtkCssValue * _gtk_css_font_variant_position_value_try_parse (GtkCssParser *parser);
GtkCssFontVariantPosition _gtk_css_font_variant_position_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_font_variant_caps_value_new (GtkCssFontVariantCaps caps);
GtkCssValue * _gtk_css_font_variant_caps_value_try_parse (GtkCssParser *parser);
GtkCssFontVariantCaps _gtk_css_font_variant_caps_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_font_variant_alternate_value_new (GtkCssFontVariantAlternate alternates);
GtkCssValue * _gtk_css_font_variant_alternate_value_try_parse (GtkCssParser *parser);
GtkCssFontVariantAlternate _gtk_css_font_variant_alternate_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_font_variant_ligature_value_new (GtkCssFontVariantLigature ligatures);
GtkCssFontVariantLigature _gtk_css_font_variant_ligature_try_parse_one (GtkCssParser *parser,
GtkCssFontVariantLigature base);
GtkCssFontVariantLigature _gtk_css_font_variant_ligature_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_font_variant_numeric_value_new (GtkCssFontVariantNumeric numeric);
GtkCssFontVariantNumeric _gtk_css_font_variant_numeric_try_parse_one (GtkCssParser *parser,
GtkCssFontVariantNumeric base);
GtkCssFontVariantNumeric _gtk_css_font_variant_numeric_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_font_variant_east_asian_value_new (GtkCssFontVariantEastAsian east_asian);
GtkCssFontVariantEastAsian _gtk_css_font_variant_east_asian_try_parse_one (GtkCssParser *parser,
GtkCssFontVariantEastAsian base);
GtkCssFontVariantEastAsian _gtk_css_font_variant_east_asian_value_get (const GtkCssValue *value);
G_END_DECLS
#endif /* __GTK_CSS_ENUM_VALUE_PRIVATE_H__ */

View File

@ -878,202 +878,153 @@ parse_font_variant (GtkCssShorthandProperty *shorthand,
else if (_gtk_css_parser_try (parser, "none", TRUE))
{
/* all initial values, except for font-variant-ligatures */
values[0] = _gtk_css_array_value_new (_gtk_css_ident_value_new ("none"));
values[0] = _gtk_css_font_variant_ligature_value_new (GTK_CSS_FONT_VARIANT_LIGATURE_NONE);
}
else
{
gboolean found;
GtkCssValue *lig_values[4] = { NULL, NULL, NULL, NULL };
guint n_ligs = 0;
gboolean common = FALSE;
gboolean discretionary = FALSE;
gboolean historical = FALSE;
gboolean contextual = FALSE;
GtkCssValue *num_values[5] = { NULL, NULL, NULL, NULL };
guint n_num = 0;
gboolean figure = FALSE;
gboolean spacing = FALSE;
gboolean fraction = FALSE;
gboolean ordinal = FALSE;
gboolean zero = FALSE;
GtkCssValue *alt_value;
GtkCssValue *ea_values[5] = { NULL, NULL, NULL, NULL };
guint n_ea = 0;
gboolean variant = FALSE;
gboolean width = FALSE;
gboolean ruby = FALSE;
GtkCssFontVariantLigature ligatures;
GtkCssFontVariantNumeric numeric;
GtkCssFontVariantEastAsian east_asian;
ligatures = 0;
numeric = 0;
east_asian = 0;
do {
found = FALSE;
if (!common)
GtkCssFontVariantLigature parsed_ligature;
GtkCssFontVariantNumeric parsed_numeric;
GtkCssFontVariantEastAsian parsed_east_asian;
parsed_ligature = _gtk_css_font_variant_ligature_try_parse_one (parser, ligatures);
if (parsed_ligature == 0 && ligatures != 0)
{
lig_values[n_ligs] = _gtk_css_ident_value_try (parser, "common-ligatures",
"no-common-ligatures", NULL);
if (lig_values[n_ligs])
{
n_ligs++;
common = TRUE;
found = TRUE;
}
_gtk_css_parser_error (parser, "Invalid combination of ligature values");
return FALSE;
}
if (!discretionary)
if (parsed_ligature == GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL ||
parsed_ligature == GTK_CSS_FONT_VARIANT_LIGATURE_NONE)
{
lig_values[n_ligs] = _gtk_css_ident_value_try (parser, "discretionary-ligatures",
"no-discretionary-ligatures", NULL);
if (lig_values[n_ligs])
{
n_ligs++;
discretionary = TRUE;
found = TRUE;
}
_gtk_css_parser_error (parser, "Unexpected ligature value");
return FALSE;
}
if (!historical)
if (parsed_ligature != ligatures)
{
lig_values[n_ligs] = _gtk_css_ident_value_try (parser, "historical-ligatures",
"no-historical-ligatures", NULL);
if (lig_values[n_ligs])
{
n_ligs++;
historical = TRUE;
found = TRUE;
}
}
if (!contextual)
{
lig_values[n_ligs] = _gtk_css_ident_value_try (parser, "contextual",
"no-contextual", NULL);
if (lig_values[n_ligs])
{
n_ligs++;
contextual = TRUE;
found = TRUE;
}
ligatures = parsed_ligature;
goto found;
}
if (!figure)
parsed_numeric = _gtk_css_font_variant_numeric_try_parse_one (parser, numeric);
if (parsed_numeric == 0 && numeric != 0)
{
num_values[n_num] = _gtk_css_ident_value_try (parser, "lining-nums",
"oldstyle-nums", NULL);
if (num_values[n_num])
{
n_num++;
figure = TRUE;
found = TRUE;
}
_gtk_css_parser_error (parser, "Invalid combination of numeric values");
return FALSE;
}
if (!spacing)
if (parsed_numeric == GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL)
{
num_values[n_num] = _gtk_css_ident_value_try (parser, "proportional-nums",
"tabular-nums", NULL);
if (num_values[n_num])
{
n_num++;
spacing = TRUE;
found = TRUE;
}
_gtk_css_parser_error (parser, "Unexpected numeric value");
return FALSE;
}
if (!fraction)
if (parsed_numeric != numeric)
{
num_values[n_num] = _gtk_css_ident_value_try (parser, "diagonal-fractions",
"stacked-fractions", NULL);
if (num_values[n_num])
{
n_num++;
fraction = TRUE;
found = TRUE;
}
numeric = parsed_numeric;
goto found;
}
if (!ordinal)
parsed_east_asian = _gtk_css_font_variant_east_asian_try_parse_one (parser, east_asian);
if (parsed_east_asian == 0 && east_asian != 0)
{
num_values[n_num] = _gtk_css_ident_value_try (parser, "ordinal", NULL);
if (num_values[n_num])
{
n_num++;
ordinal = TRUE;
found = TRUE;
}
_gtk_css_parser_error (parser, "Invalid combination of east asian values");
return FALSE;
}
if (!zero)
if (parsed_east_asian == GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL)
{
num_values[n_num] = _gtk_css_ident_value_try (parser, "slashed-zero", NULL);
if (num_values[n_num])
{
n_num++;
zero = TRUE;
found = TRUE;
}
_gtk_css_parser_error (parser, "Unexpected east asian value");
return FALSE;
}
if (alt_value == NULL)
if (parsed_east_asian != east_asian)
{
alt_value = _gtk_css_ident_value_try (parser, "historical-forms", NULL);
if (alt_value)
found = TRUE;
east_asian = parsed_east_asian;
goto found;
}
if (values[1] == NULL)
{
values[1] = _gtk_css_ident_value_try (parser, "sub", "super", NULL);
values[1] = _gtk_css_font_variant_position_value_try_parse (parser);
if (values[1])
found = TRUE;
{
if (_gtk_css_font_variant_position_value_get (values[1]) == GTK_CSS_FONT_VARIANT_POSITION_NORMAL)
{
_gtk_css_parser_error (parser, "Unexpected position value");
return FALSE;
}
goto found;
}
}
if (values[2] == NULL)
{
values[2] = _gtk_css_ident_value_try (parser, "small-caps", "all-small-caps",
"petite-caps", "all-petite-caps",
"unicase", "titling-caps", NULL);
values[2] = _gtk_css_font_variant_caps_value_try_parse (parser);
if (values[2])
found = TRUE;
{
if (_gtk_css_font_variant_caps_value_get (values[2]) == GTK_CSS_FONT_VARIANT_CAPS_NORMAL)
{
_gtk_css_parser_error (parser, "Unexpected caps value");
return FALSE;
}
goto found;
}
}
if (!variant)
if (values[4] == NULL)
{
ea_values[n_ea] = _gtk_css_ident_value_try (parser, "jis78", "jis83", "jis90", "jis04",
"simplified", "traditional", NULL);
if (ea_values[n_ea])
values[4] = _gtk_css_font_variant_alternate_value_try_parse (parser);
if (values[4])
{
n_ea++;
variant = TRUE;
if (_gtk_css_font_variant_alternate_value_get (values[4]) == GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL)
{
_gtk_css_parser_error (parser, "Unexpected alternate value");
return FALSE;
}
goto found;
}
}
if (!width)
{
ea_values[n_ea] = _gtk_css_ident_value_try (parser, "full-width"
"proportional-width", NULL);
if (ea_values[n_ea])
{
n_ea++;
width = TRUE;
}
}
if (!ruby)
{
ea_values[n_ea] = _gtk_css_ident_value_try (parser, "ruby", NULL);
if (ea_values[n_ea])
{
n_ea++;
ruby = TRUE;
}
}
if (!found)
{
_gtk_css_parser_error (parser, "Unknown value for property");
return FALSE;
}
} while (!value_is_done_parsing (parser));
if (n_ligs > 0)
values[0] = _gtk_css_array_value_new_from_array (lig_values, n_ligs);
_gtk_css_parser_error (parser, "Unknown value for property");
return FALSE;
if (n_num > 0)
values[3] = _gtk_css_array_value_new_from_array (num_values, n_num);
found:
if (value_is_done_parsing (parser))
break;
if (alt_value)
values[4] = _gtk_css_array_value_new (alt_value);
} while (1);
if (n_ea > 0)
values[5] = _gtk_css_array_value_new_from_array (ea_values, n_ea);
if (ligatures != 0)
{
values[0] = _gtk_css_font_variant_ligature_value_new (ligatures);
if (values[0] == NULL)
{
_gtk_css_parser_error (parser, "Invalid combination of ligature values");
return FALSE;
}
}
if (numeric != 0)
{
values[3] = _gtk_css_font_variant_numeric_value_new (numeric);
if (values[3] == NULL)
{
_gtk_css_parser_error (parser, "Invalid combination of numeric values");
return FALSE;
}
}
if (east_asian != 0)
{
values[5] = _gtk_css_font_variant_east_asian_value_new (east_asian);
if (values[5] == NULL)
{
_gtk_css_parser_error (parser, "Invalid combination of east asian values");
return FALSE;
}
}
}
return TRUE;

View File

@ -216,6 +216,14 @@ add_pango_attr (PangoAttrList *attrs,
return attrs;
}
static void
append_separated (GString *s, const char *text)
{
if (s->len > 0)
g_string_append (s, ", ");
g_string_append (s, text);
}
PangoAttrList *
gtk_css_style_get_pango_attributes (GtkCssStyle *style)
{
@ -225,15 +233,11 @@ gtk_css_style_get_pango_attributes (GtkCssStyle *style)
const GdkRGBA *color;
const GdkRGBA *decoration_color;
gint letter_spacing;
GtkCssValue *kerning;
GtkCssValue *ligatures;
GtkCssValue *position;
GtkCssValue *caps;
GtkCssValue *numeric;
GtkCssValue *alternates;
GtkCssValue *east_asian;
GtkCssValue *value;
GtkCssFontVariantLigature ligatures;
GtkCssFontVariantNumeric numeric;
GtkCssFontVariantEastAsian east_asian;
GString *s;
int i;
/* text-decoration */
decoration_line = _gtk_css_text_decoration_line_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_TEXT_DECORATION_LINE));
@ -273,136 +277,143 @@ gtk_css_style_get_pango_attributes (GtkCssStyle *style)
s = g_string_new ("");
kerning = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_KERNING);
if (strcmp (_gtk_css_ident_value_get (kerning), "normal") == 0)
g_string_append (s, "kern 1");
else if (strcmp (_gtk_css_ident_value_get (kerning), "none") == 0)
g_string_append (s, "kern 0");
ligatures = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES);
for (i = 0; i < _gtk_css_array_value_get_n_values (ligatures); i++)
value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_KERNING);
switch (_gtk_css_font_kerning_value_get (value))
{
GtkCssValue *value = _gtk_css_array_value_get_nth (ligatures, i);
if (s->len > 0) g_string_append (s, ", ");
if (strcmp (_gtk_css_ident_value_get (value), "none") == 0)
g_string_append (s, "liga 0, clig 0, dlig 0, hlig 0, calt 0");
else if (strcmp (_gtk_css_ident_value_get (value), "common-ligatures") == 0)
g_string_append (s, "liga 1, clig 1");
else if (strcmp (_gtk_css_ident_value_get (value), "no-common-ligatures") == 0)
g_string_append (s, "liga 0, clig 0");
else if (strcmp (_gtk_css_ident_value_get (value), "discretionary-ligatures") == 0)
g_string_append (s, "dlig 1");
else if (strcmp (_gtk_css_ident_value_get (value), "no-discretionary-ligatures") == 0)
g_string_append (s, "dlig 0");
else if (strcmp (_gtk_css_ident_value_get (value), "historical-ligatures") == 0)
g_string_append (s, "hlig 1");
else if (strcmp (_gtk_css_ident_value_get (value), "no-historical-ligatures") == 0)
g_string_append (s, "hlig 0");
else if (strcmp (_gtk_css_ident_value_get (value), "contextual") == 0)
g_string_append (s, "calt 1");
else if (strcmp (_gtk_css_ident_value_get (value), "no-contextual") == 0)
g_string_append (s, "calt 0");
case GTK_CSS_FONT_KERNING_NORMAL:
append_separated (s, "kern 1");
break;
case GTK_CSS_FONT_KERNING_NONE:
append_separated (s, "kern 0");
break;
default: ;
}
position = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_POSITION);
if (strcmp (_gtk_css_ident_value_get (position), "sub") == 0)
value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES);
ligatures = _gtk_css_font_variant_ligature_value_get (value);
if (ligatures == GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL)
{
if (s->len > 0) g_string_append (s, ", ");
g_string_append (s, "subs 1");
/* all defaults */
}
else if (strcmp (_gtk_css_ident_value_get (kerning), "super") == 0)
else if (ligatures == GTK_CSS_FONT_VARIANT_LIGATURE_NONE)
append_separated (s, "liga 0, clig 0, dlig 0, hlig 0, calt 0");
else
{
if (s->len > 0) g_string_append (s, ", ");
g_string_append (s, "sups 1");
if (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_COMMON_LIGATURES)
append_separated (s, "liga 1, clig 1");
if (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_COMMON_LIGATURES)
append_separated (s, "liga 0, clig 0");
if (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_DISCRETIONARY_LIGATURES)
append_separated (s, "dlig 1");
if (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_DISCRETIONARY_LIGATURES)
append_separated (s, "dlig 0");
if (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_HISTORICAL_LIGATURES)
append_separated (s, "hlig 1");
if (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_HISTORICAL_LIGATURES)
append_separated (s, "hlig 0");
if (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_CONTEXTUAL)
append_separated (s, "calt 1");
if (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_CONTEXTUAL)
append_separated (s, "calt 0");
}
caps = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_CAPS);
if (strcmp (_gtk_css_ident_value_get (caps), "small-caps") == 0)
value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_POSITION);
switch (_gtk_css_font_variant_position_value_get (value))
{
if (s->len > 0) g_string_append (s, ", ");
g_string_append (s, "smcp 1");
}
else if (strcmp (_gtk_css_ident_value_get (caps), "all-small-caps") == 0)
{
if (s->len > 0) g_string_append (s, ", ");
g_string_append (s, "c2sc 1, smcp 1");
}
else if (strcmp (_gtk_css_ident_value_get (caps), "petite-caps") == 0)
{
if (s->len > 0) g_string_append (s, ", ");
g_string_append (s, "pcap 1");
}
else if (strcmp (_gtk_css_ident_value_get (caps), "all-petite-caps") == 0)
{
if (s->len > 0) g_string_append (s, ", ");
g_string_append (s, "c2pc 1, pcap 1");
}
else if (strcmp (_gtk_css_ident_value_get (caps), "unicase") == 0)
{
if (s->len > 0) g_string_append (s, ", ");
g_string_append (s, "unic 1");
}
else if (strcmp (_gtk_css_ident_value_get (caps), "titling-caps") == 0)
{
if (s->len > 0) g_string_append (s, ", ");
g_string_append (s, "titl 1");
case GTK_CSS_FONT_VARIANT_POSITION_SUB:
append_separated (s, "subs 1");
break;
case GTK_CSS_FONT_VARIANT_POSITION_SUPER:
append_separated (s, "sups 1");
break;
default: ;
}
numeric = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_NUMERIC);
for (i = 0; i < _gtk_css_array_value_get_n_values (numeric); i++)
value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_CAPS);
switch (_gtk_css_font_variant_caps_value_get (value))
{
GtkCssValue *value = _gtk_css_array_value_get_nth (numeric, i);
if (s->len > 0) g_string_append (s, ", ");
if (strcmp (_gtk_css_ident_value_get (value), "lining-nums") == 0)
g_string_append (s, "lnum 1");
else if (strcmp (_gtk_css_ident_value_get (value), "oldstyle-nums") == 0)
g_string_append (s, "onum 1");
else if (strcmp (_gtk_css_ident_value_get (value), "proportional-nums") == 0)
g_string_append (s, "pnum 1");
else if (strcmp (_gtk_css_ident_value_get (value), "tabular-nums") == 0)
g_string_append (s, "tnum 1");
else if (strcmp (_gtk_css_ident_value_get (value), "diagonal-fractions") == 0)
g_string_append (s, "frac 1");
else if (strcmp (_gtk_css_ident_value_get (value), "stacked-fractions") == 0)
g_string_append (s, "afrc 1");
else if (strcmp (_gtk_css_ident_value_get (value), "ordinal") == 0)
g_string_append (s, "ordn 1");
else if (strcmp (_gtk_css_ident_value_get (value), "slashed-zero") == 0)
g_string_append (s, "zero 1");
case GTK_CSS_FONT_VARIANT_CAPS_SMALL_CAPS:
append_separated (s, "smcp 1");
break;
case GTK_CSS_FONT_VARIANT_CAPS_ALL_SMALL_CAPS:
append_separated (s, "c2sc 1, smcp 1");
break;
case GTK_CSS_FONT_VARIANT_CAPS_PETITE_CAPS:
append_separated (s, "pcap 1");
break;
case GTK_CSS_FONT_VARIANT_CAPS_ALL_PETITE_CAPS:
append_separated (s, "c2pc 1, pcap 1");
break;
case GTK_CSS_FONT_VARIANT_CAPS_UNICASE:
append_separated (s, "unic 1");
break;
case GTK_CSS_FONT_VARIANT_CAPS_TITLING_CAPS:
append_separated (s, "titl 1");
break;
default: ;
}
alternates = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_ALTERNATES);
for (i = 0; i < _gtk_css_array_value_get_n_values (alternates); i++)
value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_NUMERIC);
numeric = _gtk_css_font_variant_numeric_value_get (value);
if (numeric == GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL)
{
GtkCssValue *value = _gtk_css_array_value_get_nth (alternates, i);
if (s->len > 0) g_string_append (s, ", ");
if (strcmp (_gtk_css_ident_value_get (value), "historical-forms") == 0)
g_string_append (s, "hist 1");
/* all defaults */
}
else
{
if (numeric & GTK_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS)
append_separated (s, "lnum 1");
if (numeric & GTK_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS)
append_separated (s, "onum 1");
if (numeric & GTK_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS)
append_separated (s, "pnum 1");
if (numeric & GTK_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS)
append_separated (s, "tnum 1");
if (numeric & GTK_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS)
append_separated (s, "frac 1");
if (numeric & GTK_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS)
append_separated (s, "afrc 1");
if (numeric & GTK_CSS_FONT_VARIANT_NUMERIC_ORDINAL)
append_separated (s, "ordn 1");
if (numeric & GTK_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO)
append_separated (s, "zero 1");
}
east_asian = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_EAST_ASIAN);
for (i = 0; i < _gtk_css_array_value_get_n_values (east_asian); i++)
value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_ALTERNATES);
switch (_gtk_css_font_variant_alternate_value_get (value))
{
GtkCssValue *value = _gtk_css_array_value_get_nth (east_asian, i);
if (s->len > 0) g_string_append (s, ", ");
if (strcmp (_gtk_css_ident_value_get (value), "jis78") == 0)
g_string_append (s, "jp78 1");
if (strcmp (_gtk_css_ident_value_get (value), "jis83") == 0)
g_string_append (s, "jp83 1");
if (strcmp (_gtk_css_ident_value_get (value), "jis90") == 0)
g_string_append (s, "jp90 1");
if (strcmp (_gtk_css_ident_value_get (value), "jis04") == 0)
g_string_append (s, "jp04 1");
if (strcmp (_gtk_css_ident_value_get (value), "simplified") == 0)
g_string_append (s, "smpl 1");
if (strcmp (_gtk_css_ident_value_get (value), "traditional") == 0)
g_string_append (s, "trad 1");
if (strcmp (_gtk_css_ident_value_get (value), "full-width") == 0)
g_string_append (s, "fwid 1");
if (strcmp (_gtk_css_ident_value_get (value), "proportional-width") == 0)
g_string_append (s, "pwid 1");
if (strcmp (_gtk_css_ident_value_get (value), "ruby") == 0)
g_string_append (s, "ruby 1");
case GTK_CSS_FONT_VARIANT_ALTERNATE_HISTORICAL_FORMS:
append_separated (s, "hist 1");
break;
default: ;
}
value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_EAST_ASIAN);
east_asian = _gtk_css_font_variant_east_asian_value_get (value);
if (east_asian == GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL)
{
/* all defaults */
}
else
{
if (east_asian & GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS78)
append_separated (s, "jp78 1");
if (east_asian & GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS83)
append_separated (s, "jp83 1");
if (east_asian & GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS90)
append_separated (s, "jp90 1");
if (east_asian & GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS04)
append_separated (s, "jp04 1");
if (east_asian & GTK_CSS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED)
append_separated (s, "smpl 1");
if (east_asian & GTK_CSS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL)
append_separated (s, "trad 1");
if (east_asian & GTK_CSS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH)
append_separated (s, "fwid 1");
if (east_asian & GTK_CSS_FONT_VARIANT_EAST_ASIAN_PROPORTIONAL)
append_separated (s, "pwid 1");
if (east_asian & GTK_CSS_FONT_VARIANT_EAST_ASIAN_RUBY)
append_separated (s, "ruby 1");
}
attrs = add_pango_attr (attrs, pango_attr_font_features_new (s->str));

View File

@ -1,4 +1,4 @@
/* GTK - The GIMP Toolkit
/*
* Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
*
* This library is free software; you can redistribute it and/or
@ -513,9 +513,8 @@ static GtkCssValue *
parse_font_kerning (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
GtkCssValue *value = NULL;
GtkCssValue *value = _gtk_css_font_kerning_value_try_parse (parser);
value = _gtk_css_ident_value_try (parser, "auto", "normal", "none", NULL);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
@ -536,73 +535,24 @@ parse_font_variant_ligatures (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
GtkCssValue *value = NULL;
GtkCssFontVariantLigature ligatures;
if (_gtk_css_parser_try (parser, "normal", TRUE))
value = _gtk_css_array_value_new (_gtk_css_ident_value_new ("normal"));
else if (_gtk_css_parser_try (parser, "none", TRUE))
value = _gtk_css_array_value_new (_gtk_css_ident_value_new ("none"));
else
{
GtkCssValue *values[4] = { NULL, NULL, NULL, NULL };
guint n_values = 0;
guint old_n;
gboolean common = FALSE;
gboolean discretionary = FALSE;
gboolean historical = FALSE;
gboolean contextual = FALSE;
ligatures = 0;
do {
GtkCssFontVariantLigature parsed;
do {
old_n = n_values;
if (!common)
{
values[n_values] = _gtk_css_ident_value_try (parser, "common-ligatures",
"no-common-ligatures", NULL);
if (values[n_values])
{
n_values++;
common = TRUE;
}
}
if (!discretionary)
{
values[n_values] = _gtk_css_ident_value_try (parser, "discretionary-ligatures",
"no-discretionary-ligatures", NULL);
if (values[n_values])
{
n_values++;
discretionary = TRUE;
}
}
if (!historical)
{
values[n_values] = _gtk_css_ident_value_try (parser, "historical-ligatures",
"no-historical-ligatures",
NULL);
if (values[n_values])
{
n_values++;
historical = TRUE;
}
}
if (!contextual)
{
values[n_values] = _gtk_css_ident_value_try (parser, "contextual",
"no-contextual", NULL);
if (values[n_values])
{
n_values++;
contextual = TRUE;
}
}
if (old_n == n_values)
{
_gtk_css_parser_error (parser, "Not a valid value");
return NULL;
}
} while (!value_is_done_parsing (parser));
parsed = _gtk_css_font_variant_ligature_try_parse_one (parser, ligatures);
if (parsed == 0 || parsed == ligatures)
{
_gtk_css_parser_error (parser, "Not a valid value");
return NULL;
}
ligatures = parsed;
} while (!value_is_done_parsing (parser));
value = _gtk_css_array_value_new_from_array (values, n_values);
}
value = _gtk_css_font_variant_ligature_value_new (ligatures);
if (value == NULL)
_gtk_css_parser_error (parser, "Invalid combination of values");
return value;
}
@ -611,9 +561,8 @@ static GtkCssValue *
parse_font_variant_position (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
GtkCssValue *value = NULL;
GtkCssValue *value = _gtk_css_font_variant_position_value_try_parse (parser);
value = _gtk_css_ident_value_try (parser, "normal", "sub", "super", NULL);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
@ -624,12 +573,8 @@ static GtkCssValue *
parse_font_variant_caps (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
GtkCssValue *value = NULL;
GtkCssValue *value = _gtk_css_font_variant_caps_value_try_parse (parser);
value = _gtk_css_ident_value_try (parser, "normal",
"small-caps", "all-small-caps",
"petite-caps", "all-petite-caps",
"unicase", "titling-caps", NULL);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
@ -641,76 +586,24 @@ parse_font_variant_numeric (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
GtkCssValue *value = NULL;
GtkCssFontVariantNumeric numeric;
if (_gtk_css_parser_try (parser, "normal", TRUE))
value = _gtk_css_array_value_new (_gtk_css_ident_value_new ("normal"));
else
{
GtkCssValue *values[5] = { NULL, NULL, NULL, NULL };
guint n_values = 0;
guint old_n;
gboolean figure = FALSE;
gboolean spacing = FALSE;
gboolean fraction = FALSE;
gboolean ordinal = FALSE;
gboolean zero = FALSE;
numeric = 0;
do {
GtkCssFontVariantNumeric parsed;
do {
old_n = n_values;
if (!figure)
{
values[n_values] = _gtk_css_ident_value_try (parser, "lining-nums", "oldstyle-nums", NULL);
if (values[n_values])
{
n_values++;
figure = TRUE;
}
}
if (!spacing)
{
values[n_values] = _gtk_css_ident_value_try (parser, "proportional-nums", "tabular-nums", NULL);
if (values[n_values])
{
n_values++;
spacing = TRUE;
}
}
if (!fraction)
{
values[n_values] = _gtk_css_ident_value_try (parser, "diagonal-fractions", "stacked-fractions", NULL);
if (values[n_values])
{
n_values++;
fraction = TRUE;
}
}
if (!ordinal)
{
values[n_values] = _gtk_css_ident_value_try (parser, "ordinal", NULL);
if (values[n_values])
{
n_values++;
ordinal = TRUE;
}
}
if (!zero)
{
values[n_values] = _gtk_css_ident_value_try (parser, "slashed-zero", NULL);
if (values[n_values])
{
n_values++;
zero = TRUE;
}
}
if (old_n == n_values)
{
_gtk_css_parser_error (parser, "Not a valid value");
return NULL;
}
} while (!value_is_done_parsing (parser));
parsed = _gtk_css_font_variant_numeric_try_parse_one (parser, numeric);
if (parsed == 0 || parsed == numeric)
{
_gtk_css_parser_error (parser, "Not a valid value");
return NULL;
}
numeric = parsed;
} while (!value_is_done_parsing (parser));
value = _gtk_css_array_value_new_from_array (values, n_values);
}
value = _gtk_css_font_variant_numeric_value_new (numeric);
if (value == NULL)
_gtk_css_parser_error (parser, "Invalid combination of values");
return value;
}
@ -719,11 +612,10 @@ static GtkCssValue *
parse_font_variant_alternates (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
GtkCssValue *value = NULL;
GtkCssValue *value = _gtk_css_font_variant_alternate_value_try_parse (parser);
value = _gtk_css_ident_value_try (parser, "normal", "historical-forms", NULL);
if (value == NULL)
_gtk_css_parser_error (parser, "Not a valid value");
_gtk_css_parser_error (parser, "unknown value for property");
return value;
}
@ -733,63 +625,28 @@ parse_font_variant_east_asian (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
GtkCssValue *value = NULL;
GtkCssFontVariantEastAsian east_asian;
if (_gtk_css_parser_try (parser, "normal", TRUE))
value = _gtk_css_array_value_new (_gtk_css_ident_value_new ("normal"));
else
{
GtkCssValue *values[3] = { NULL, NULL, NULL };
guint n_values = 0;
guint old_n;
gboolean variant = FALSE;
gboolean width = FALSE;
gboolean ruby = FALSE;
east_asian = 0;
do {
GtkCssFontVariantEastAsian parsed;
do {
old_n = n_values;
if (!variant)
{
values[n_values] = _gtk_css_ident_value_try (parser, "jis78", "jis83", "jis90", "jis04",
"simplified", "traditional", NULL);
if (values[n_values])
{
n_values++;
variant = TRUE;
}
}
if (!width)
{
values[n_values] = _gtk_css_ident_value_try (parser, "full-width"
"proportional-width", NULL);
if (values[n_values])
{
n_values++;
width = TRUE;
}
}
if (!ruby)
{
values[n_values] = _gtk_css_ident_value_try (parser, "ruby", NULL);
if (values[n_values])
{
n_values++;
ruby = TRUE;
}
}
if (old_n == n_values)
{
_gtk_css_parser_error (parser, "Not a valid value");
return NULL;
}
} while (!value_is_done_parsing (parser));
parsed = _gtk_css_font_variant_east_asian_try_parse_one (parser, east_asian);
if (parsed == 0 || parsed == east_asian)
{
_gtk_css_parser_error (parser, "Not a valid value");
return NULL;
}
east_asian = parsed;
} while (!value_is_done_parsing (parser));
value = _gtk_css_array_value_new_from_array (values, n_values);
}
value = _gtk_css_font_variant_east_asian_value_new (east_asian);
if (value == NULL)
_gtk_css_parser_error (parser, "Invalid combination of values");
return value;
}
static GtkCssValue *
box_shadow_value_parse (GtkCssStyleProperty *property,
GtkCssParser *parser)
@ -1274,7 +1131,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_AFFECTS_TEXT | GTK_CSS_AFFECTS_TEXT_ATTRS,
parse_font_kerning,
NULL,
_gtk_css_ident_value_new ("auto"));
_gtk_css_font_kerning_value_new (GTK_CSS_FONT_KERNING_AUTO));
gtk_css_style_property_register ("font-variant-ligatures",
GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES,
G_TYPE_NONE,
@ -1282,7 +1139,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_AFFECTS_TEXT | GTK_CSS_AFFECTS_TEXT_ATTRS,
parse_font_variant_ligatures,
NULL,
_gtk_css_array_value_new (_gtk_css_ident_value_new ("normal")));
_gtk_css_font_variant_ligature_value_new (GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL));
gtk_css_style_property_register ("font-variant-position",
GTK_CSS_PROPERTY_FONT_VARIANT_POSITION,
G_TYPE_NONE,
@ -1290,7 +1147,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_AFFECTS_TEXT | GTK_CSS_AFFECTS_TEXT_ATTRS,
parse_font_variant_position,
NULL,
_gtk_css_ident_value_new ("normal"));
_gtk_css_font_variant_position_value_new (GTK_CSS_FONT_VARIANT_POSITION_NORMAL));
gtk_css_style_property_register ("font-variant-caps",
GTK_CSS_PROPERTY_FONT_VARIANT_CAPS,
G_TYPE_NONE,
@ -1298,7 +1155,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_AFFECTS_TEXT | GTK_CSS_AFFECTS_TEXT_ATTRS,
parse_font_variant_caps,
NULL,
_gtk_css_ident_value_new ("normal"));
_gtk_css_font_variant_caps_value_new (GTK_CSS_FONT_VARIANT_CAPS_NORMAL));
gtk_css_style_property_register ("font-variant-numeric",
GTK_CSS_PROPERTY_FONT_VARIANT_NUMERIC,
G_TYPE_NONE,
@ -1306,7 +1163,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_AFFECTS_TEXT | GTK_CSS_AFFECTS_TEXT_ATTRS,
parse_font_variant_numeric,
NULL,
_gtk_css_array_value_new (_gtk_css_ident_value_new ("normal")));
_gtk_css_font_variant_numeric_value_new (GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL));
gtk_css_style_property_register ("font-variant-alternates",
GTK_CSS_PROPERTY_FONT_VARIANT_ALTERNATES,
G_TYPE_NONE,
@ -1314,7 +1171,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_AFFECTS_TEXT | GTK_CSS_AFFECTS_TEXT_ATTRS,
parse_font_variant_alternates,
NULL,
_gtk_css_array_value_new (_gtk_css_ident_value_new ("normal")));
_gtk_css_font_variant_alternate_value_new (GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL));
gtk_css_style_property_register ("font-variant-east-asian",
GTK_CSS_PROPERTY_FONT_VARIANT_EAST_ASIAN,
G_TYPE_NONE,
@ -1322,7 +1179,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_AFFECTS_TEXT | GTK_CSS_AFFECTS_TEXT_ATTRS,
parse_font_variant_east_asian,
NULL,
_gtk_css_array_value_new (_gtk_css_ident_value_new ("normal")));
_gtk_css_font_variant_east_asian_value_new (GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL));
gtk_css_style_property_register ("text-shadow",
GTK_CSS_PROPERTY_TEXT_SHADOW,
G_TYPE_NONE,

View File

@ -364,6 +364,71 @@ typedef enum /*< skip >*/ {
GTK_CSS_MS,
} GtkCssUnit;
typedef enum /*< skip >*/ {
GTK_CSS_FONT_KERNING_AUTO,
GTK_CSS_FONT_KERNING_NORMAL,
GTK_CSS_FONT_KERNING_NONE
} GtkCssFontKerning;
typedef enum /*< skip >*/ {
GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL = 1 << 0,
GTK_CSS_FONT_VARIANT_LIGATURE_NONE = 1 << 1,
GTK_CSS_FONT_VARIANT_LIGATURE_COMMON_LIGATURES = 1 << 2,
GTK_CSS_FONT_VARIANT_LIGATURE_NO_COMMON_LIGATURES = 1 << 3,
GTK_CSS_FONT_VARIANT_LIGATURE_DISCRETIONARY_LIGATURES = 1 << 4,
GTK_CSS_FONT_VARIANT_LIGATURE_NO_DISCRETIONARY_LIGATURES = 1 << 5,
GTK_CSS_FONT_VARIANT_LIGATURE_HISTORICAL_LIGATURES = 1 << 6,
GTK_CSS_FONT_VARIANT_LIGATURE_NO_HISTORICAL_LIGATURES = 1 << 7,
GTK_CSS_FONT_VARIANT_LIGATURE_CONTEXTUAL = 1 << 8,
GTK_CSS_FONT_VARIANT_LIGATURE_NO_CONTEXTUAL = 1 << 9
} GtkCssFontVariantLigature;
typedef enum /*< skip >*/ {
GTK_CSS_FONT_VARIANT_POSITION_NORMAL,
GTK_CSS_FONT_VARIANT_POSITION_SUB,
GTK_CSS_FONT_VARIANT_POSITION_SUPER
} GtkCssFontVariantPosition;
typedef enum /*< skip >*/ {
GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL = 1 << 0,
GTK_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS = 1 << 1,
GTK_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS = 1 << 2,
GTK_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS = 1 << 3,
GTK_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS = 1 << 4,
GTK_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS = 1 << 5,
GTK_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS = 1 << 6,
GTK_CSS_FONT_VARIANT_NUMERIC_ORDINAL = 1 << 7,
GTK_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO = 1 << 8
} GtkCssFontVariantNumeric;
typedef enum /*< skip >*/ {
GTK_CSS_FONT_VARIANT_CAPS_NORMAL,
GTK_CSS_FONT_VARIANT_CAPS_SMALL_CAPS,
GTK_CSS_FONT_VARIANT_CAPS_ALL_SMALL_CAPS,
GTK_CSS_FONT_VARIANT_CAPS_PETITE_CAPS,
GTK_CSS_FONT_VARIANT_CAPS_ALL_PETITE_CAPS,
GTK_CSS_FONT_VARIANT_CAPS_UNICASE,
GTK_CSS_FONT_VARIANT_CAPS_TITLING_CAPS
} GtkCssFontVariantCaps;
typedef enum /*< skip >*/ {
GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL,
GTK_CSS_FONT_VARIANT_ALTERNATE_HISTORICAL_FORMS
} GtkCssFontVariantAlternate;
typedef enum /*< skip >*/ {
GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL = 1 << 0,
GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS78 = 1 << 1,
GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS83 = 1 << 2,
GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS90 = 1 << 3,
GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS04 = 1 << 4,
GTK_CSS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED = 1 << 5,
GTK_CSS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL = 1 << 6,
GTK_CSS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH = 1 << 7,
GTK_CSS_FONT_VARIANT_EAST_ASIAN_PROPORTIONAL = 1 << 8,
GTK_CSS_FONT_VARIANT_EAST_ASIAN_RUBY = 1 << 9
} GtkCssFontVariantEastAsian;
cairo_operator_t _gtk_css_blend_mode_get_operator (GskBlendMode mode);
GtkCssChange _gtk_css_change_for_sibling (GtkCssChange match);