1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2011 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include "gtkcssenumvalueprivate.h"
21 
22 #include "gtkcssstyleprivate.h"
23 #include "gtkcssnumbervalueprivate.h"
24 #include "gtkstyleproviderprivate.h"
25 #include "gtksettingsprivate.h"
26 
27 #include "gtkpopcountprivate.h"
28 
29 /* repeated API */
30 
31 struct _GtkCssValue {
32   GTK_CSS_VALUE_BASE
33   int value;
34   const char *name;
35 };
36 
37 static void
gtk_css_value_enum_free(GtkCssValue * value)38 gtk_css_value_enum_free (GtkCssValue *value)
39 {
40   g_slice_free (GtkCssValue, value);
41 }
42 
43 static GtkCssValue *
gtk_css_value_enum_compute(GtkCssValue * value,guint property_id,GtkStyleProvider * provider,GtkCssStyle * style,GtkCssStyle * parent_style)44 gtk_css_value_enum_compute (GtkCssValue      *value,
45                             guint             property_id,
46                             GtkStyleProvider *provider,
47                             GtkCssStyle      *style,
48                             GtkCssStyle      *parent_style)
49 {
50   return _gtk_css_value_ref (value);
51 }
52 
53 static gboolean
gtk_css_value_enum_equal(const GtkCssValue * enum1,const GtkCssValue * enum2)54 gtk_css_value_enum_equal (const GtkCssValue *enum1,
55                           const GtkCssValue *enum2)
56 {
57   return enum1 == enum2;
58 }
59 
60 static GtkCssValue *
gtk_css_value_enum_transition(GtkCssValue * start,GtkCssValue * end,guint property_id,double progress)61 gtk_css_value_enum_transition (GtkCssValue *start,
62                                GtkCssValue *end,
63                                guint        property_id,
64                                double       progress)
65 {
66   return NULL;
67 }
68 
69 static void
gtk_css_value_enum_print(const GtkCssValue * value,GString * string)70 gtk_css_value_enum_print (const GtkCssValue *value,
71                           GString           *string)
72 {
73   g_string_append (string, value->name);
74 }
75 
76 /* GtkBorderStyle */
77 
78 static const GtkCssValueClass GTK_CSS_VALUE_BORDER_STYLE = {
79   "GtkCssBorderStyleValue",
80   gtk_css_value_enum_free,
81   gtk_css_value_enum_compute,
82   gtk_css_value_enum_equal,
83   gtk_css_value_enum_transition,
84   NULL,
85   NULL,
86   gtk_css_value_enum_print
87 };
88 
89 static GtkCssValue border_style_values[] = {
90   { &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_NONE, "none" },
91   { &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_SOLID, "solid" },
92   { &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_INSET, "inset" },
93   { &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_OUTSET, "outset" },
94   { &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_HIDDEN, "hidden" },
95   { &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DOTTED, "dotted" },
96   { &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DASHED, "dashed" },
97   { &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DOUBLE, "double" },
98   { &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_GROOVE, "groove" },
99   { &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_RIDGE, "ridge" }
100 };
101 
102 GtkCssValue *
_gtk_css_border_style_value_new(GtkBorderStyle border_style)103 _gtk_css_border_style_value_new (GtkBorderStyle border_style)
104 {
105   g_return_val_if_fail (border_style < G_N_ELEMENTS (border_style_values), NULL);
106 
107   return _gtk_css_value_ref (&border_style_values[border_style]);
108 }
109 
110 GtkCssValue *
_gtk_css_border_style_value_try_parse(GtkCssParser * parser)111 _gtk_css_border_style_value_try_parse (GtkCssParser *parser)
112 {
113   guint i;
114 
115   g_return_val_if_fail (parser != NULL, NULL);
116 
117   for (i = 0; i < G_N_ELEMENTS (border_style_values); i++)
118     {
119       if (gtk_css_parser_try_ident (parser, border_style_values[i].name))
120         return _gtk_css_value_ref (&border_style_values[i]);
121     }
122 
123   return NULL;
124 }
125 
126 GtkBorderStyle
_gtk_css_border_style_value_get(const GtkCssValue * value)127 _gtk_css_border_style_value_get (const GtkCssValue *value)
128 {
129   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_BORDER_STYLE, GTK_BORDER_STYLE_NONE);
130 
131   return value->value;
132 }
133 
134 /* GtkCssBlendMode */
135 
136 static const GtkCssValueClass GTK_CSS_VALUE_BLEND_MODE = {
137   "GtkCssBlendModeValue",
138   gtk_css_value_enum_free,
139   gtk_css_value_enum_compute,
140   gtk_css_value_enum_equal,
141   gtk_css_value_enum_transition,
142   NULL,
143   NULL,
144   gtk_css_value_enum_print
145 };
146 
147 static GtkCssValue blend_mode_values[] = {
148   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DEFAULT, "normal" },
149   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_MULTIPLY, "multiply" },
150   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SCREEN, "screen" },
151   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_OVERLAY, "overlay" },
152   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DARKEN, "darken" },
153   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_LIGHTEN, "lighten" },
154   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR_DODGE, "color-dodge" },
155   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR_BURN, "color-burn" },
156   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_HARD_LIGHT, "hard-light" },
157   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SOFT_LIGHT, "soft-light" },
158   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DIFFERENCE, "difference" },
159   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_EXCLUSION, "exclusion" },
160   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR, "color" },
161   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_HUE, "hue" },
162   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SATURATION, "saturation" },
163   { &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_LUMINOSITY, "luminosity" }
164 };
165 
166 GtkCssValue *
_gtk_css_blend_mode_value_new(GskBlendMode blend_mode)167 _gtk_css_blend_mode_value_new (GskBlendMode blend_mode)
168 {
169   g_return_val_if_fail (blend_mode < G_N_ELEMENTS (blend_mode_values), NULL);
170 
171   return _gtk_css_value_ref (&blend_mode_values[blend_mode]);
172 }
173 
174 GtkCssValue *
_gtk_css_blend_mode_value_try_parse(GtkCssParser * parser)175 _gtk_css_blend_mode_value_try_parse (GtkCssParser *parser)
176 {
177   guint i;
178 
179   g_return_val_if_fail (parser != NULL, NULL);
180 
181   for (i = 0; i < G_N_ELEMENTS (blend_mode_values); i++)
182     {
183       if (gtk_css_parser_try_ident (parser, blend_mode_values[i].name))
184         return _gtk_css_value_ref (&blend_mode_values[i]);
185     }
186 
187   return NULL;
188 }
189 
190 GskBlendMode
_gtk_css_blend_mode_value_get(const GtkCssValue * value)191 _gtk_css_blend_mode_value_get (const GtkCssValue *value)
192 {
193   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_BLEND_MODE, GSK_BLEND_MODE_DEFAULT);
194 
195   return value->value;
196 }
197 
198 /* GtkCssFontSize */
199 
200 static double
get_dpi(GtkCssStyle * style)201 get_dpi (GtkCssStyle *style)
202 {
203   return _gtk_css_number_value_get (style->core->dpi, 96);
204 }
205 
206 /* XXX: Kinda bad to have that machinery here, nobody expects vital font
207  * size code to appear in gtkcssvalueenum.c.
208  */
209 #define DEFAULT_FONT_SIZE_PT 10
210 
211 double
gtk_css_font_size_get_default_px(GtkStyleProvider * provider,GtkCssStyle * style)212 gtk_css_font_size_get_default_px (GtkStyleProvider *provider,
213                                   GtkCssStyle      *style)
214 {
215   GtkSettings *settings;
216   int font_size;
217 
218   settings = gtk_style_provider_get_settings (provider);
219   if (settings == NULL)
220     return DEFAULT_FONT_SIZE_PT * get_dpi (style) / 72.0;
221 
222   font_size = gtk_settings_get_font_size (settings);
223   if (font_size == 0)
224     return DEFAULT_FONT_SIZE_PT * get_dpi (style) / 72.0;
225   else if (gtk_settings_get_font_size_is_absolute (settings))
226     return (double) font_size / PANGO_SCALE;
227   else
228     return ((double) font_size / PANGO_SCALE) * get_dpi (style) / 72.0;
229 }
230 
231 static GtkCssValue *
gtk_css_value_font_size_compute(GtkCssValue * value,guint property_id,GtkStyleProvider * provider,GtkCssStyle * style,GtkCssStyle * parent_style)232 gtk_css_value_font_size_compute (GtkCssValue      *value,
233                                  guint             property_id,
234                                  GtkStyleProvider *provider,
235                                  GtkCssStyle      *style,
236                                  GtkCssStyle      *parent_style)
237 {
238   double font_size;
239 
240   switch (value->value)
241     {
242     case GTK_CSS_FONT_SIZE_XX_SMALL:
243       font_size = gtk_css_font_size_get_default_px (provider, style) * 3. / 5;
244       break;
245     case GTK_CSS_FONT_SIZE_X_SMALL:
246       font_size = gtk_css_font_size_get_default_px (provider, style) * 3. / 4;
247       break;
248     case GTK_CSS_FONT_SIZE_SMALL:
249       font_size = gtk_css_font_size_get_default_px (provider, style) * 8. / 9;
250       break;
251     default:
252       g_assert_not_reached ();
253       /* fall thru */
254     case GTK_CSS_FONT_SIZE_MEDIUM:
255       font_size = gtk_css_font_size_get_default_px (provider, style);
256       break;
257     case GTK_CSS_FONT_SIZE_LARGE:
258       font_size = gtk_css_font_size_get_default_px (provider, style) * 6. / 5;
259       break;
260     case GTK_CSS_FONT_SIZE_X_LARGE:
261       font_size = gtk_css_font_size_get_default_px (provider, style) * 3. / 2;
262       break;
263     case GTK_CSS_FONT_SIZE_XX_LARGE:
264       font_size = gtk_css_font_size_get_default_px (provider, style) * 2;
265       break;
266     case GTK_CSS_FONT_SIZE_SMALLER:
267       if (parent_style)
268         font_size = _gtk_css_number_value_get (parent_style->core->font_size, 100);
269       else
270         font_size = gtk_css_font_size_get_default_px (provider, style);
271       /* This is what WebKit does... */
272       font_size /= 1.2;
273       break;
274     case GTK_CSS_FONT_SIZE_LARGER:
275       if (parent_style)
276         font_size = _gtk_css_number_value_get (parent_style->core->font_size, 100);
277       else
278         font_size = gtk_css_font_size_get_default_px (provider, style);
279       /* This is what WebKit does... */
280       font_size *= 1.2;
281       break;
282   }
283 
284   return _gtk_css_number_value_new (font_size, GTK_CSS_PX);
285 }
286 
287 static const GtkCssValueClass GTK_CSS_VALUE_FONT_SIZE = {
288   "GtkCssFontSizeValue",
289   gtk_css_value_enum_free,
290   gtk_css_value_font_size_compute,
291   gtk_css_value_enum_equal,
292   gtk_css_value_enum_transition,
293   NULL,
294   NULL,
295   gtk_css_value_enum_print
296 };
297 
298 static GtkCssValue font_size_values[] = {
299   { &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_SMALLER, "smaller" },
300   { &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_LARGER, "larger" },
301   { &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_XX_SMALL, "xx-small" },
302   { &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_X_SMALL, "x-small" },
303   { &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_SMALL, "small" },
304   { &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_MEDIUM, "medium" },
305   { &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_LARGE, "large" },
306   { &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_X_LARGE, "x-large" },
307   { &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_XX_LARGE, "xx-large" }
308 };
309 
310 GtkCssValue *
_gtk_css_font_size_value_new(GtkCssFontSize font_size)311 _gtk_css_font_size_value_new (GtkCssFontSize font_size)
312 {
313   g_return_val_if_fail (font_size < G_N_ELEMENTS (font_size_values), NULL);
314 
315   return _gtk_css_value_ref (&font_size_values[font_size]);
316 }
317 
318 GtkCssValue *
_gtk_css_font_size_value_try_parse(GtkCssParser * parser)319 _gtk_css_font_size_value_try_parse (GtkCssParser *parser)
320 {
321   guint i;
322 
323   g_return_val_if_fail (parser != NULL, NULL);
324 
325   for (i = 0; i < G_N_ELEMENTS (font_size_values); i++)
326     {
327       if (gtk_css_parser_try_ident (parser, font_size_values[i].name))
328         return _gtk_css_value_ref (&font_size_values[i]);
329     }
330 
331   return NULL;
332 }
333 
334 GtkCssFontSize
_gtk_css_font_size_value_get(const GtkCssValue * value)335 _gtk_css_font_size_value_get (const GtkCssValue *value)
336 {
337   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_SIZE, GTK_CSS_FONT_SIZE_MEDIUM);
338 
339   return value->value;
340 }
341 
342 /* PangoStyle */
343 
344 static const GtkCssValueClass GTK_CSS_VALUE_FONT_STYLE = {
345   "GtkCssFontStyleValue",
346   gtk_css_value_enum_free,
347   gtk_css_value_enum_compute,
348   gtk_css_value_enum_equal,
349   gtk_css_value_enum_transition,
350   NULL,
351   NULL,
352   gtk_css_value_enum_print
353 };
354 
355 static GtkCssValue font_style_values[] = {
356   { &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, PANGO_STYLE_NORMAL, "normal" },
357   { &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, PANGO_STYLE_OBLIQUE, "oblique" },
358   { &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, PANGO_STYLE_ITALIC, "italic" }
359 };
360 
361 GtkCssValue *
_gtk_css_font_style_value_new(PangoStyle font_style)362 _gtk_css_font_style_value_new (PangoStyle font_style)
363 {
364   g_return_val_if_fail (font_style < G_N_ELEMENTS (font_style_values), NULL);
365 
366   return _gtk_css_value_ref (&font_style_values[font_style]);
367 }
368 
369 GtkCssValue *
_gtk_css_font_style_value_try_parse(GtkCssParser * parser)370 _gtk_css_font_style_value_try_parse (GtkCssParser *parser)
371 {
372   guint i;
373 
374   g_return_val_if_fail (parser != NULL, NULL);
375 
376   for (i = 0; i < G_N_ELEMENTS (font_style_values); i++)
377     {
378       if (gtk_css_parser_try_ident (parser, font_style_values[i].name))
379         return _gtk_css_value_ref (&font_style_values[i]);
380     }
381 
382   return NULL;
383 }
384 
385 PangoStyle
_gtk_css_font_style_value_get(const GtkCssValue * value)386 _gtk_css_font_style_value_get (const GtkCssValue *value)
387 {
388   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_STYLE, PANGO_STYLE_NORMAL);
389 
390   return value->value;
391 }
392 
393 /* PangoWeight */
394 
395 #define BOLDER -1
396 #define LIGHTER -2
397 
398 static GtkCssValue *
gtk_css_value_font_weight_compute(GtkCssValue * value,guint property_id,GtkStyleProvider * provider,GtkCssStyle * style,GtkCssStyle * parent_style)399 gtk_css_value_font_weight_compute (GtkCssValue      *value,
400                                    guint             property_id,
401                                    GtkStyleProvider *provider,
402                                    GtkCssStyle      *style,
403                                    GtkCssStyle      *parent_style)
404 {
405   PangoWeight new_weight;
406   int parent_value;
407 
408   if (value->value >= 0)
409     return _gtk_css_value_ref (value);
410 
411   if (parent_style)
412     parent_value = _gtk_css_number_value_get (parent_style->font->font_weight, 100);
413   else
414     parent_value = 400;
415 
416   if (value->value == BOLDER)
417     {
418       if (parent_value < 350)
419         new_weight = 400;
420       else if (parent_value < 550)
421         new_weight = 700;
422       else
423         new_weight = 900;
424     }
425   else if (value->value == LIGHTER)
426     {
427       if (parent_value > 750)
428         new_weight = 700;
429       else if (parent_value > 550)
430         new_weight = 400;
431       else
432         new_weight = 100;
433     }
434   else
435     {
436       g_assert_not_reached ();
437       new_weight = PANGO_WEIGHT_NORMAL;
438     }
439 
440   return _gtk_css_number_value_new (new_weight, GTK_CSS_NUMBER);
441 }
442 
443 static const GtkCssValueClass GTK_CSS_VALUE_FONT_WEIGHT = {
444   "GtkCssFontWeightValue",
445   gtk_css_value_enum_free,
446   gtk_css_value_font_weight_compute,
447   gtk_css_value_enum_equal,
448   NULL,
449   NULL,
450   NULL,
451   gtk_css_value_enum_print
452 };
453 
454 static GtkCssValue font_weight_values[] = {
455   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, FALSE, BOLDER, "bolder" },
456   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, FALSE, LIGHTER, "lighter" },
457 };
458 
459 GtkCssValue *
gtk_css_font_weight_value_try_parse(GtkCssParser * parser)460 gtk_css_font_weight_value_try_parse (GtkCssParser *parser)
461 {
462   guint i;
463 
464   g_return_val_if_fail (parser != NULL, NULL);
465 
466   for (i = 0; i < G_N_ELEMENTS (font_weight_values); i++)
467     {
468       if (gtk_css_parser_try_ident (parser, font_weight_values[i].name))
469         return _gtk_css_value_ref (&font_weight_values[i]);
470     }
471 
472   if (gtk_css_parser_try_ident (parser, "normal"))
473     return _gtk_css_number_value_new (PANGO_WEIGHT_NORMAL, GTK_CSS_NUMBER);
474   if (gtk_css_parser_try_ident (parser, "bold"))
475     return _gtk_css_number_value_new (PANGO_WEIGHT_BOLD, GTK_CSS_NUMBER);
476 
477   return NULL;
478 }
479 
480 PangoWeight
gtk_css_font_weight_value_get(const GtkCssValue * value)481 gtk_css_font_weight_value_get (const GtkCssValue *value)
482 {
483   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_WEIGHT, PANGO_WEIGHT_NORMAL);
484 
485   return value->value;
486 }
487 
488 #undef BOLDER
489 #undef LIGHTER
490 
491 /* PangoStretch */
492 
493 static const GtkCssValueClass GTK_CSS_VALUE_FONT_STRETCH = {
494   "GtkCssFontStretchValue",
495   gtk_css_value_enum_free,
496   gtk_css_value_enum_compute,
497   gtk_css_value_enum_equal,
498   gtk_css_value_enum_transition,
499   NULL,
500   NULL,
501   gtk_css_value_enum_print
502 };
503 
504 static GtkCssValue font_stretch_values[] = {
505   { &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_ULTRA_CONDENSED, "ultra-condensed" },
506   { &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXTRA_CONDENSED, "extra-condensed" },
507   { &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_CONDENSED, "condensed" },
508   { &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_SEMI_CONDENSED, "semi-condensed" },
509   { &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_NORMAL, "normal" },
510   { &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_SEMI_EXPANDED, "semi-expanded" },
511   { &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXPANDED, "expanded" },
512   { &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXTRA_EXPANDED, "extra-expanded" },
513   { &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_ULTRA_EXPANDED, "ultra-expanded" },
514 };
515 
516 GtkCssValue *
_gtk_css_font_stretch_value_new(PangoStretch font_stretch)517 _gtk_css_font_stretch_value_new (PangoStretch font_stretch)
518 {
519   g_return_val_if_fail (font_stretch < G_N_ELEMENTS (font_stretch_values), NULL);
520 
521   return _gtk_css_value_ref (&font_stretch_values[font_stretch]);
522 }
523 
524 GtkCssValue *
_gtk_css_font_stretch_value_try_parse(GtkCssParser * parser)525 _gtk_css_font_stretch_value_try_parse (GtkCssParser *parser)
526 {
527   guint i;
528 
529   g_return_val_if_fail (parser != NULL, NULL);
530 
531   for (i = 0; i < G_N_ELEMENTS (font_stretch_values); i++)
532     {
533       if (gtk_css_parser_try_ident (parser, font_stretch_values[i].name))
534         return _gtk_css_value_ref (&font_stretch_values[i]);
535     }
536 
537   return NULL;
538 }
539 
540 PangoStretch
_gtk_css_font_stretch_value_get(const GtkCssValue * value)541 _gtk_css_font_stretch_value_get (const GtkCssValue *value)
542 {
543   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_STRETCH, PANGO_STRETCH_NORMAL);
544 
545   return value->value;
546 }
547 
548 /* GtkTextDecorationStyle */
549 
550 static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_STYLE = {
551   "GtkCssTextDecorationStyleValue",
552   gtk_css_value_enum_free,
553   gtk_css_value_enum_compute,
554   gtk_css_value_enum_equal,
555   gtk_css_value_enum_transition,
556   NULL,
557   NULL,
558   gtk_css_value_enum_print
559 };
560 
561 static GtkCssValue text_decoration_style_values[] = {
562   { &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, GTK_CSS_TEXT_DECORATION_STYLE_SOLID, "solid" },
563   { &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, GTK_CSS_TEXT_DECORATION_STYLE_DOUBLE, "double" },
564   { &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, GTK_CSS_TEXT_DECORATION_STYLE_WAVY, "wavy" },
565 };
566 
567 GtkCssValue *
_gtk_css_text_decoration_style_value_new(GtkTextDecorationStyle style)568 _gtk_css_text_decoration_style_value_new (GtkTextDecorationStyle style)
569 {
570   g_return_val_if_fail (style < G_N_ELEMENTS (text_decoration_style_values), NULL);
571 
572   return _gtk_css_value_ref (&text_decoration_style_values[style]);
573 }
574 
575 GtkCssValue *
_gtk_css_text_decoration_style_value_try_parse(GtkCssParser * parser)576 _gtk_css_text_decoration_style_value_try_parse (GtkCssParser *parser)
577 {
578   guint i;
579 
580   g_return_val_if_fail (parser != NULL, NULL);
581 
582   for (i = 0; i < G_N_ELEMENTS (text_decoration_style_values); i++)
583     {
584       if (gtk_css_parser_try_ident (parser, text_decoration_style_values[i].name))
585         return _gtk_css_value_ref (&text_decoration_style_values[i]);
586     }
587 
588   return NULL;
589 }
590 
591 GtkTextDecorationStyle
_gtk_css_text_decoration_style_value_get(const GtkCssValue * value)592 _gtk_css_text_decoration_style_value_get (const GtkCssValue *value)
593 {
594   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, GTK_CSS_TEXT_DECORATION_STYLE_SOLID);
595 
596   return value->value;
597 }
598 
599 /* GtkCssArea */
600 
601 static const GtkCssValueClass GTK_CSS_VALUE_AREA = {
602   "GtkCssAreaValue",
603   gtk_css_value_enum_free,
604   gtk_css_value_enum_compute,
605   gtk_css_value_enum_equal,
606   gtk_css_value_enum_transition,
607   NULL,
608   NULL,
609   gtk_css_value_enum_print
610 };
611 
612 static GtkCssValue area_values[] = {
613   { &GTK_CSS_VALUE_AREA, 1, TRUE, GTK_CSS_AREA_BORDER_BOX, "border-box" },
614   { &GTK_CSS_VALUE_AREA, 1, TRUE, GTK_CSS_AREA_PADDING_BOX, "padding-box" },
615   { &GTK_CSS_VALUE_AREA, 1, TRUE, GTK_CSS_AREA_CONTENT_BOX, "content-box" }
616 };
617 
618 GtkCssValue *
_gtk_css_area_value_new(GtkCssArea area)619 _gtk_css_area_value_new (GtkCssArea area)
620 {
621   guint i;
622 
623   for (i = 0; i < G_N_ELEMENTS (area_values); i++)
624     {
625       if (area_values[i].value == area)
626         return _gtk_css_value_ref (&area_values[i]);
627     }
628 
629   g_return_val_if_reached (NULL);
630 }
631 
632 GtkCssValue *
_gtk_css_area_value_try_parse(GtkCssParser * parser)633 _gtk_css_area_value_try_parse (GtkCssParser *parser)
634 {
635   guint i;
636 
637   g_return_val_if_fail (parser != NULL, NULL);
638 
639   for (i = 0; i < G_N_ELEMENTS (area_values); i++)
640     {
641       if (gtk_css_parser_try_ident (parser, area_values[i].name))
642         return _gtk_css_value_ref (&area_values[i]);
643     }
644 
645   return NULL;
646 }
647 
648 GtkCssArea
_gtk_css_area_value_get(const GtkCssValue * value)649 _gtk_css_area_value_get (const GtkCssValue *value)
650 {
651   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_AREA, GTK_CSS_AREA_BORDER_BOX);
652 
653   return value->value;
654 }
655 
656 /* GtkCssDirection */
657 
658 static const GtkCssValueClass GTK_CSS_VALUE_DIRECTION = {
659   "GtkCssDirectionValue",
660   gtk_css_value_enum_free,
661   gtk_css_value_enum_compute,
662   gtk_css_value_enum_equal,
663   gtk_css_value_enum_transition,
664   NULL,
665   NULL,
666   gtk_css_value_enum_print
667 };
668 
669 static GtkCssValue direction_values[] = {
670   { &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_NORMAL, "normal" },
671   { &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_REVERSE, "reverse" },
672   { &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_ALTERNATE, "alternate" },
673   { &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_ALTERNATE_REVERSE, "alternate-reverse" }
674 };
675 
676 GtkCssValue *
_gtk_css_direction_value_new(GtkCssDirection direction)677 _gtk_css_direction_value_new (GtkCssDirection direction)
678 {
679   guint i;
680 
681   for (i = 0; i < G_N_ELEMENTS (direction_values); i++)
682     {
683       if (direction_values[i].value == direction)
684         return _gtk_css_value_ref (&direction_values[i]);
685     }
686 
687   g_return_val_if_reached (NULL);
688 }
689 
690 GtkCssValue *
_gtk_css_direction_value_try_parse(GtkCssParser * parser)691 _gtk_css_direction_value_try_parse (GtkCssParser *parser)
692 {
693   int i;
694 
695   g_return_val_if_fail (parser != NULL, NULL);
696 
697   /* need to parse backwards here, otherwise "alternate" will also match "alternate-reverse".
698    * Our parser rocks!
699    */
700   for (i = G_N_ELEMENTS (direction_values) - 1; i >= 0; i--)
701     {
702       if (gtk_css_parser_try_ident (parser, direction_values[i].name))
703         return _gtk_css_value_ref (&direction_values[i]);
704     }
705 
706   return NULL;
707 }
708 
709 GtkCssDirection
_gtk_css_direction_value_get(const GtkCssValue * value)710 _gtk_css_direction_value_get (const GtkCssValue *value)
711 {
712   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_DIRECTION, GTK_CSS_DIRECTION_NORMAL);
713 
714   return value->value;
715 }
716 
717 /* GtkCssPlayState */
718 
719 static const GtkCssValueClass GTK_CSS_VALUE_PLAY_STATE = {
720   "GtkCssPlayStateValue",
721   gtk_css_value_enum_free,
722   gtk_css_value_enum_compute,
723   gtk_css_value_enum_equal,
724   gtk_css_value_enum_transition,
725   NULL,
726   NULL,
727   gtk_css_value_enum_print
728 };
729 
730 static GtkCssValue play_state_values[] = {
731   { &GTK_CSS_VALUE_PLAY_STATE, 1, TRUE, GTK_CSS_PLAY_STATE_RUNNING, "running" },
732   { &GTK_CSS_VALUE_PLAY_STATE, 1, TRUE, GTK_CSS_PLAY_STATE_PAUSED, "paused" }
733 };
734 
735 GtkCssValue *
_gtk_css_play_state_value_new(GtkCssPlayState play_state)736 _gtk_css_play_state_value_new (GtkCssPlayState play_state)
737 {
738   guint i;
739 
740   for (i = 0; i < G_N_ELEMENTS (play_state_values); i++)
741     {
742       if (play_state_values[i].value == play_state)
743         return _gtk_css_value_ref (&play_state_values[i]);
744     }
745 
746   g_return_val_if_reached (NULL);
747 }
748 
749 GtkCssValue *
_gtk_css_play_state_value_try_parse(GtkCssParser * parser)750 _gtk_css_play_state_value_try_parse (GtkCssParser *parser)
751 {
752   guint i;
753 
754   g_return_val_if_fail (parser != NULL, NULL);
755 
756   for (i = 0; i < G_N_ELEMENTS (play_state_values); i++)
757     {
758       if (gtk_css_parser_try_ident (parser, play_state_values[i].name))
759         return _gtk_css_value_ref (&play_state_values[i]);
760     }
761 
762   return NULL;
763 }
764 
765 GtkCssPlayState
_gtk_css_play_state_value_get(const GtkCssValue * value)766 _gtk_css_play_state_value_get (const GtkCssValue *value)
767 {
768   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_PLAY_STATE, GTK_CSS_PLAY_STATE_RUNNING);
769 
770   return value->value;
771 }
772 
773 /* GtkCssFillMode */
774 
775 static const GtkCssValueClass GTK_CSS_VALUE_FILL_MODE = {
776   "GtkCssFillModeValue",
777   gtk_css_value_enum_free,
778   gtk_css_value_enum_compute,
779   gtk_css_value_enum_equal,
780   gtk_css_value_enum_transition,
781   NULL,
782   NULL,
783   gtk_css_value_enum_print
784 };
785 
786 static GtkCssValue fill_mode_values[] = {
787   { &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_NONE, "none" },
788   { &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_FORWARDS, "forwards" },
789   { &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_BACKWARDS, "backwards" },
790   { &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_BOTH, "both" }
791 };
792 
793 GtkCssValue *
_gtk_css_fill_mode_value_new(GtkCssFillMode fill_mode)794 _gtk_css_fill_mode_value_new (GtkCssFillMode fill_mode)
795 {
796   guint i;
797 
798   for (i = 0; i < G_N_ELEMENTS (fill_mode_values); i++)
799     {
800       if (fill_mode_values[i].value == fill_mode)
801         return _gtk_css_value_ref (&fill_mode_values[i]);
802     }
803 
804   g_return_val_if_reached (NULL);
805 }
806 
807 GtkCssValue *
_gtk_css_fill_mode_value_try_parse(GtkCssParser * parser)808 _gtk_css_fill_mode_value_try_parse (GtkCssParser *parser)
809 {
810   guint i;
811 
812   g_return_val_if_fail (parser != NULL, NULL);
813 
814   for (i = 0; i < G_N_ELEMENTS (fill_mode_values); i++)
815     {
816       if (gtk_css_parser_try_ident (parser, fill_mode_values[i].name))
817         return _gtk_css_value_ref (&fill_mode_values[i]);
818     }
819 
820   return NULL;
821 }
822 
823 GtkCssFillMode
_gtk_css_fill_mode_value_get(const GtkCssValue * value)824 _gtk_css_fill_mode_value_get (const GtkCssValue *value)
825 {
826   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FILL_MODE, GTK_CSS_FILL_NONE);
827 
828   return value->value;
829 }
830 
831 /* GtkCssIconStyle */
832 
833 static const GtkCssValueClass GTK_CSS_VALUE_ICON_STYLE = {
834   "GtkCssIconStyleValue",
835   gtk_css_value_enum_free,
836   gtk_css_value_enum_compute,
837   gtk_css_value_enum_equal,
838   gtk_css_value_enum_transition,
839   NULL,
840   NULL,
841   gtk_css_value_enum_print
842 };
843 
844 static GtkCssValue icon_style_values[] = {
845   { &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, GTK_CSS_ICON_STYLE_REQUESTED, "requested" },
846   { &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, GTK_CSS_ICON_STYLE_REGULAR, "regular" },
847   { &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, GTK_CSS_ICON_STYLE_SYMBOLIC, "symbolic" }
848 };
849 
850 GtkCssValue *
_gtk_css_icon_style_value_new(GtkCssIconStyle icon_style)851 _gtk_css_icon_style_value_new (GtkCssIconStyle icon_style)
852 {
853   guint i;
854 
855   for (i = 0; i < G_N_ELEMENTS (icon_style_values); i++)
856     {
857       if (icon_style_values[i].value == icon_style)
858         return _gtk_css_value_ref (&icon_style_values[i]);
859     }
860 
861   g_return_val_if_reached (NULL);
862 }
863 
864 GtkCssValue *
_gtk_css_icon_style_value_try_parse(GtkCssParser * parser)865 _gtk_css_icon_style_value_try_parse (GtkCssParser *parser)
866 {
867   guint i;
868 
869   g_return_val_if_fail (parser != NULL, NULL);
870 
871   for (i = 0; i < G_N_ELEMENTS (icon_style_values); i++)
872     {
873       if (gtk_css_parser_try_ident (parser, icon_style_values[i].name))
874         return _gtk_css_value_ref (&icon_style_values[i]);
875     }
876 
877   return NULL;
878 }
879 
880 GtkCssIconStyle
_gtk_css_icon_style_value_get(const GtkCssValue * value)881 _gtk_css_icon_style_value_get (const GtkCssValue *value)
882 {
883   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_ICON_STYLE, GTK_CSS_ICON_STYLE_REQUESTED);
884 
885   return value->value;
886 }
887 
888 /* GtkCssFontKerning */
889 
890 static const GtkCssValueClass GTK_CSS_VALUE_FONT_KERNING = {
891   "GtkCssFontKerningValue",
892   gtk_css_value_enum_free,
893   gtk_css_value_enum_compute,
894   gtk_css_value_enum_equal,
895   gtk_css_value_enum_transition,
896   NULL,
897   NULL,
898   gtk_css_value_enum_print
899 };
900 
901 static GtkCssValue font_kerning_values[] = {
902   { &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, GTK_CSS_FONT_KERNING_AUTO, "auto" },
903   { &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, GTK_CSS_FONT_KERNING_NORMAL, "normal" },
904   { &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, GTK_CSS_FONT_KERNING_NONE, "none" }
905 };
906 
907 GtkCssValue *
_gtk_css_font_kerning_value_new(GtkCssFontKerning kerning)908 _gtk_css_font_kerning_value_new (GtkCssFontKerning kerning)
909 {
910   guint i;
911 
912   for (i = 0; i < G_N_ELEMENTS (font_kerning_values); i++)
913     {
914       if (font_kerning_values[i].value == kerning)
915         return _gtk_css_value_ref (&font_kerning_values[i]);
916     }
917 
918   g_return_val_if_reached (NULL);
919 }
920 
921 GtkCssValue *
_gtk_css_font_kerning_value_try_parse(GtkCssParser * parser)922 _gtk_css_font_kerning_value_try_parse (GtkCssParser *parser)
923 {
924   guint i;
925 
926   g_return_val_if_fail (parser != NULL, NULL);
927 
928   for (i = 0; i < G_N_ELEMENTS (font_kerning_values); i++)
929     {
930       if (gtk_css_parser_try_ident (parser, font_kerning_values[i].name))
931         return _gtk_css_value_ref (&font_kerning_values[i]);
932     }
933 
934   return NULL;
935 }
936 
937 GtkCssFontKerning
_gtk_css_font_kerning_value_get(const GtkCssValue * value)938 _gtk_css_font_kerning_value_get (const GtkCssValue *value)
939 {
940   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_KERNING, GTK_CSS_FONT_KERNING_AUTO);
941 
942   return value->value;
943 }
944 
945 /* GtkCssFontVariantPos */
946 
947 static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_POSITION = {
948   "GtkCssFontVariationPositionValue",
949   gtk_css_value_enum_free,
950   gtk_css_value_enum_compute,
951   gtk_css_value_enum_equal,
952   gtk_css_value_enum_transition,
953   NULL,
954   NULL,
955   gtk_css_value_enum_print
956 };
957 
958 static GtkCssValue font_variant_position_values[] = {
959   { &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, GTK_CSS_FONT_VARIANT_POSITION_NORMAL, "normal" },
960   { &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, GTK_CSS_FONT_VARIANT_POSITION_SUB, "sub" },
961   { &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, GTK_CSS_FONT_VARIANT_POSITION_SUPER, "super" }
962 };
963 
964 GtkCssValue *
_gtk_css_font_variant_position_value_new(GtkCssFontVariantPosition position)965 _gtk_css_font_variant_position_value_new (GtkCssFontVariantPosition position)
966 {
967   guint i;
968 
969   for (i = 0; i < G_N_ELEMENTS (font_variant_position_values); i++)
970     {
971       if (font_variant_position_values[i].value == position)
972         return _gtk_css_value_ref (&font_variant_position_values[i]);
973     }
974 
975   g_return_val_if_reached (NULL);
976 }
977 
978 GtkCssValue *
_gtk_css_font_variant_position_value_try_parse(GtkCssParser * parser)979 _gtk_css_font_variant_position_value_try_parse (GtkCssParser *parser)
980 {
981   guint i;
982 
983   g_return_val_if_fail (parser != NULL, NULL);
984 
985   for (i = 0; i < G_N_ELEMENTS (font_variant_position_values); i++)
986     {
987       if (gtk_css_parser_try_ident (parser, font_variant_position_values[i].name))
988         return _gtk_css_value_ref (&font_variant_position_values[i]);
989     }
990 
991   return NULL;
992 }
993 
994 GtkCssFontVariantPosition
_gtk_css_font_variant_position_value_get(const GtkCssValue * value)995 _gtk_css_font_variant_position_value_get (const GtkCssValue *value)
996 {
997   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_POSITION, GTK_CSS_FONT_VARIANT_POSITION_NORMAL);
998 
999   return value->value;
1000 }
1001 
1002 /* GtkCssFontVariantCaps */
1003 
1004 static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_CAPS = {
1005   "GtkCssFontVariantCapsValue",
1006   gtk_css_value_enum_free,
1007   gtk_css_value_enum_compute,
1008   gtk_css_value_enum_equal,
1009   gtk_css_value_enum_transition,
1010   NULL,
1011   NULL,
1012   gtk_css_value_enum_print
1013 };
1014 
1015 static GtkCssValue font_variant_caps_values[] = {
1016   { &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_NORMAL, "normal" },
1017   { &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_SMALL_CAPS, "small-caps" },
1018   { &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_ALL_SMALL_CAPS, "all-small-caps" },
1019   { &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_PETITE_CAPS, "petite-caps" },
1020   { &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_ALL_PETITE_CAPS, "all-petite-caps" },
1021   { &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_UNICASE, "unicase" },
1022   { &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_TITLING_CAPS, "titling-caps" }
1023 };
1024 
1025 GtkCssValue *
_gtk_css_font_variant_caps_value_new(GtkCssFontVariantCaps caps)1026 _gtk_css_font_variant_caps_value_new (GtkCssFontVariantCaps caps)
1027 {
1028   guint i;
1029 
1030   for (i = 0; i < G_N_ELEMENTS (font_variant_caps_values); i++)
1031     {
1032       if (font_variant_caps_values[i].value == caps)
1033         return _gtk_css_value_ref (&font_variant_caps_values[i]);
1034     }
1035 
1036   g_return_val_if_reached (NULL);
1037 }
1038 
1039 GtkCssValue *
_gtk_css_font_variant_caps_value_try_parse(GtkCssParser * parser)1040 _gtk_css_font_variant_caps_value_try_parse (GtkCssParser *parser)
1041 {
1042   guint i;
1043 
1044   g_return_val_if_fail (parser != NULL, NULL);
1045 
1046   for (i = 0; i < G_N_ELEMENTS (font_variant_caps_values); i++)
1047     {
1048       if (gtk_css_parser_try_ident (parser, font_variant_caps_values[i].name))
1049         return _gtk_css_value_ref (&font_variant_caps_values[i]);
1050     }
1051 
1052   return NULL;
1053 }
1054 
1055 GtkCssFontVariantCaps
_gtk_css_font_variant_caps_value_get(const GtkCssValue * value)1056 _gtk_css_font_variant_caps_value_get (const GtkCssValue *value)
1057 {
1058   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_CAPS, GTK_CSS_FONT_VARIANT_CAPS_NORMAL);
1059 
1060   return value->value;
1061 }
1062 
1063 /* GtkCssFontVariantAlternate */
1064 
1065 static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE = {
1066   "GtkCssFontVariantAlternateValue",
1067   gtk_css_value_enum_free,
1068   gtk_css_value_enum_compute,
1069   gtk_css_value_enum_equal,
1070   gtk_css_value_enum_transition,
1071   NULL,
1072   NULL,
1073   gtk_css_value_enum_print
1074 };
1075 
1076 static GtkCssValue font_variant_alternate_values[] = {
1077   { &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, TRUE, GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL, "normal" },
1078   { &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, TRUE, GTK_CSS_FONT_VARIANT_ALTERNATE_HISTORICAL_FORMS, "historical-forms" }
1079 };
1080 
1081 GtkCssValue *
_gtk_css_font_variant_alternate_value_new(GtkCssFontVariantAlternate alternate)1082 _gtk_css_font_variant_alternate_value_new (GtkCssFontVariantAlternate alternate)
1083 {
1084   guint i;
1085 
1086   for (i = 0; i < G_N_ELEMENTS (font_variant_alternate_values); i++)
1087     {
1088       if (font_variant_alternate_values[i].value == alternate)
1089         return _gtk_css_value_ref (&font_variant_alternate_values[i]);
1090     }
1091 
1092   g_return_val_if_reached (NULL);
1093 }
1094 
1095 GtkCssValue *
_gtk_css_font_variant_alternate_value_try_parse(GtkCssParser * parser)1096 _gtk_css_font_variant_alternate_value_try_parse (GtkCssParser *parser)
1097 {
1098   guint i;
1099 
1100   g_return_val_if_fail (parser != NULL, NULL);
1101 
1102   for (i = 0; i < G_N_ELEMENTS (font_variant_alternate_values); i++)
1103     {
1104       if (gtk_css_parser_try_ident (parser, font_variant_alternate_values[i].name))
1105         return _gtk_css_value_ref (&font_variant_alternate_values[i]);
1106     }
1107 
1108   return NULL;
1109 }
1110 
1111 GtkCssFontVariantAlternate
_gtk_css_font_variant_alternate_value_get(const GtkCssValue * value)1112 _gtk_css_font_variant_alternate_value_get (const GtkCssValue *value)
1113 {
1114   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL);
1115 
1116   return value->value;
1117 }
1118 
1119 /* below are flags, which are handle a bit differently. We allocate values dynamically,
1120  * and we parse one bit at a time, while allowing for detection of invalid combinations.
1121  */
1122 
1123 typedef struct {
1124   int value;
1125   const char *name;
1126 } FlagsValue;
1127 
1128 static gboolean
gtk_css_value_flags_equal(const GtkCssValue * enum1,const GtkCssValue * enum2)1129 gtk_css_value_flags_equal (const GtkCssValue *enum1,
1130                            const GtkCssValue *enum2)
1131 {
1132   return enum1->value == enum2->value;
1133 }
1134 
1135 static void
gtk_css_value_flags_print(const FlagsValue * values,guint n_values,const GtkCssValue * value,GString * string)1136 gtk_css_value_flags_print (const FlagsValue  *values,
1137                            guint              n_values,
1138                            const GtkCssValue *value,
1139                            GString           *string)
1140 {
1141   guint i;
1142   const char *sep = "";
1143 
1144   for (i = 0; i < n_values; i++)
1145     {
1146       if (value->value & values[i].value)
1147         {
1148           g_string_append (string, sep);
1149           g_string_append (string, values[i].name);
1150           sep = " ";
1151         }
1152     }
1153 }
1154 
1155 /* GtkTextDecorationLine */
1156 
1157 static FlagsValue text_decoration_line_values[] = {
1158   { GTK_CSS_TEXT_DECORATION_LINE_NONE, "none" },
1159   { GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE, "underline" },
1160   { GTK_CSS_TEXT_DECORATION_LINE_OVERLINE, "overline" },
1161   { GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH, "line-through" },
1162 };
1163 
1164 static void
gtk_css_text_decoration_line_value_print(const GtkCssValue * value,GString * string)1165 gtk_css_text_decoration_line_value_print (const GtkCssValue *value,
1166                                           GString           *string)
1167 {
1168   gtk_css_value_flags_print (text_decoration_line_values,
1169                              G_N_ELEMENTS (text_decoration_line_values),
1170                              value, string);
1171 }
1172 
1173 static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_LINE = {
1174   "GtkCssTextDecorationLine",
1175   gtk_css_value_enum_free,
1176   gtk_css_value_enum_compute,
1177   gtk_css_value_flags_equal,
1178   gtk_css_value_enum_transition,
1179   NULL,
1180   NULL,
1181   gtk_css_text_decoration_line_value_print
1182 };
1183 
1184 static gboolean
text_decoration_line_is_valid(GtkTextDecorationLine line)1185 text_decoration_line_is_valid (GtkTextDecorationLine line)
1186 {
1187   if ((line & GTK_CSS_TEXT_DECORATION_LINE_NONE) &&
1188       (line != GTK_CSS_TEXT_DECORATION_LINE_NONE))
1189     return FALSE;
1190 
1191   return TRUE;
1192 }
1193 
1194 GtkCssValue *
_gtk_css_text_decoration_line_value_new(GtkTextDecorationLine line)1195 _gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line)
1196 {
1197   GtkCssValue *value;
1198 
1199   if (!text_decoration_line_is_valid (line))
1200     return NULL;
1201 
1202   value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_TEXT_DECORATION_LINE);
1203   value->value = line;
1204   value->name = NULL;
1205   value->is_computed = TRUE;
1206 
1207   return value;
1208 }
1209 
1210 GtkTextDecorationLine
_gtk_css_text_decoration_line_try_parse_one(GtkCssParser * parser,GtkTextDecorationLine base)1211 _gtk_css_text_decoration_line_try_parse_one (GtkCssParser          *parser,
1212                                              GtkTextDecorationLine  base)
1213 {
1214   guint i;
1215   GtkTextDecorationLine value = 0;
1216 
1217   g_return_val_if_fail (parser != NULL, 0);
1218 
1219   for (i = 0; i < G_N_ELEMENTS (text_decoration_line_values); i++)
1220     {
1221       if (gtk_css_parser_try_ident (parser, text_decoration_line_values[i].name))
1222         {
1223           value = text_decoration_line_values[i].value;
1224           break;
1225         }
1226     }
1227 
1228   if (value == 0)
1229     return base; /* not parsing this value */
1230 
1231   if ((base | value) == base)
1232     return 0; /* repeated value */
1233 
1234   if (!text_decoration_line_is_valid (base | value))
1235     return 0; /* bad combination */
1236 
1237   return base | value;
1238 }
1239 
1240 GtkTextDecorationLine
_gtk_css_text_decoration_line_value_get(const GtkCssValue * value)1241 _gtk_css_text_decoration_line_value_get (const GtkCssValue *value)
1242 {
1243   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_TEXT_DECORATION_LINE, GTK_CSS_TEXT_DECORATION_LINE_NONE);
1244 
1245   return value->value;
1246 }
1247 
1248 /* GtkCssFontVariantLigature */
1249 
1250 static FlagsValue font_variant_ligature_values[] = {
1251   { GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL, "normal" },
1252   { GTK_CSS_FONT_VARIANT_LIGATURE_NONE, "none" },
1253   { GTK_CSS_FONT_VARIANT_LIGATURE_COMMON_LIGATURES, "common-ligatures" },
1254   { GTK_CSS_FONT_VARIANT_LIGATURE_NO_COMMON_LIGATURES, "no-common-ligatures" },
1255   { GTK_CSS_FONT_VARIANT_LIGATURE_DISCRETIONARY_LIGATURES, "discretionary-ligatures" },
1256   { GTK_CSS_FONT_VARIANT_LIGATURE_NO_DISCRETIONARY_LIGATURES, "no-discretionary-ligatures" },
1257   { GTK_CSS_FONT_VARIANT_LIGATURE_HISTORICAL_LIGATURES, "historical-ligatures" },
1258   { GTK_CSS_FONT_VARIANT_LIGATURE_NO_HISTORICAL_LIGATURES, "no-historical-ligatures" },
1259   { GTK_CSS_FONT_VARIANT_LIGATURE_CONTEXTUAL, "contextual" },
1260   { GTK_CSS_FONT_VARIANT_LIGATURE_NO_CONTEXTUAL, "no-contextual" }
1261 };
1262 
1263 static void
gtk_css_font_variant_ligature_value_print(const GtkCssValue * value,GString * string)1264 gtk_css_font_variant_ligature_value_print (const GtkCssValue *value,
1265                                            GString           *string)
1266 {
1267   gtk_css_value_flags_print (font_variant_ligature_values,
1268                              G_N_ELEMENTS (font_variant_ligature_values),
1269                              value, string);
1270 }
1271 
1272 static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_LIGATURE = {
1273   "GtkCssFontVariantLigatureValue",
1274   gtk_css_value_enum_free,
1275   gtk_css_value_enum_compute,
1276   gtk_css_value_flags_equal,
1277   gtk_css_value_enum_transition,
1278   NULL,
1279   NULL,
1280   gtk_css_font_variant_ligature_value_print
1281 };
1282 
1283 static gboolean
ligature_value_is_valid(GtkCssFontVariantLigature ligatures)1284 ligature_value_is_valid (GtkCssFontVariantLigature ligatures)
1285 {
1286   if (((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL) &&
1287        (ligatures != GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL)) ||
1288       ((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NONE) &&
1289        (ligatures != GTK_CSS_FONT_VARIANT_LIGATURE_NONE)) ||
1290       ((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_COMMON_LIGATURES) &&
1291        (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_COMMON_LIGATURES)) ||
1292       ((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_DISCRETIONARY_LIGATURES) &&
1293        (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_DISCRETIONARY_LIGATURES)) ||
1294       ((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_HISTORICAL_LIGATURES) &&
1295        (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_HISTORICAL_LIGATURES)) ||
1296       ((ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_CONTEXTUAL) &&
1297        (ligatures & GTK_CSS_FONT_VARIANT_LIGATURE_NO_CONTEXTUAL)))
1298     return FALSE;
1299 
1300   return TRUE;
1301 }
1302 
1303 GtkCssValue *
_gtk_css_font_variant_ligature_value_new(GtkCssFontVariantLigature ligatures)1304 _gtk_css_font_variant_ligature_value_new (GtkCssFontVariantLigature ligatures)
1305 {
1306   GtkCssValue *value;
1307 
1308   if (!ligature_value_is_valid (ligatures))
1309     return NULL;
1310 
1311   value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_FONT_VARIANT_LIGATURE);
1312   value->value = ligatures;
1313   value->name = NULL;
1314   value->is_computed = TRUE;
1315 
1316   return value;
1317 }
1318 
1319 GtkCssFontVariantLigature
_gtk_css_font_variant_ligature_try_parse_one(GtkCssParser * parser,GtkCssFontVariantLigature base)1320 _gtk_css_font_variant_ligature_try_parse_one (GtkCssParser              *parser,
1321                                               GtkCssFontVariantLigature  base)
1322 {
1323   guint i;
1324   GtkCssFontVariantLigature value = 0;
1325 
1326   g_return_val_if_fail (parser != NULL, 0);
1327 
1328   for (i = 0; i < G_N_ELEMENTS (font_variant_ligature_values); i++)
1329     {
1330       if (gtk_css_parser_try_ident (parser, font_variant_ligature_values[i].name))
1331         {
1332           value = font_variant_ligature_values[i].value;
1333           break;
1334         }
1335     }
1336 
1337   if (value == 0)
1338     return base; /* not parsing this value */
1339 
1340   if ((base | value) == base)
1341     return 0; /* repeated value */
1342 
1343   if (!ligature_value_is_valid (base | value))
1344     return 0; /* bad combination */
1345 
1346   return base | value;
1347 }
1348 
1349 GtkCssFontVariantLigature
_gtk_css_font_variant_ligature_value_get(const GtkCssValue * value)1350 _gtk_css_font_variant_ligature_value_get (const GtkCssValue *value)
1351 {
1352   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_LIGATURE, GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL);
1353 
1354   return value->value;
1355 }
1356 
1357 /* GtkCssFontVariantNumeric */
1358 
1359 static FlagsValue font_variant_numeric_values[] = {
1360   { GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL, "normal" },
1361   { GTK_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS, "lining-nums" },
1362   { GTK_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS, "oldstyle-nums" },
1363   { GTK_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS, "proportional-nums" },
1364   { GTK_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS, "tabular-nums" },
1365   { GTK_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS, "diagonal-fractions" },
1366   { GTK_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS, "stacked-fractions" },
1367   { GTK_CSS_FONT_VARIANT_NUMERIC_ORDINAL, "ordinal" },
1368   { GTK_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO, "slashed-zero" }
1369 };
1370 
1371 static void
gtk_css_font_variant_numeric_value_print(const GtkCssValue * value,GString * string)1372 gtk_css_font_variant_numeric_value_print (const GtkCssValue *value,
1373                                           GString           *string)
1374 {
1375   gtk_css_value_flags_print (font_variant_numeric_values,
1376                              G_N_ELEMENTS (font_variant_numeric_values),
1377                              value, string);
1378 }
1379 
1380 static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_NUMERIC = {
1381   "GtkCssFontVariantNumbericValue",
1382   gtk_css_value_enum_free,
1383   gtk_css_value_enum_compute,
1384   gtk_css_value_flags_equal,
1385   gtk_css_value_enum_transition,
1386   NULL,
1387   NULL,
1388   gtk_css_font_variant_numeric_value_print
1389 };
1390 
1391 static gboolean
numeric_value_is_valid(GtkCssFontVariantNumeric numeric)1392 numeric_value_is_valid (GtkCssFontVariantNumeric numeric)
1393 {
1394   if (((numeric & GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL) &&
1395        (numeric != GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL)) ||
1396       ((numeric & GTK_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS) &&
1397        (numeric & GTK_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS)) ||
1398       ((numeric & GTK_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS) &&
1399        (numeric & GTK_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS)) ||
1400       ((numeric & GTK_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS) &&
1401        (numeric & GTK_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS)))
1402     return FALSE;
1403 
1404   return TRUE;
1405 }
1406 
1407 GtkCssValue *
_gtk_css_font_variant_numeric_value_new(GtkCssFontVariantNumeric numeric)1408 _gtk_css_font_variant_numeric_value_new (GtkCssFontVariantNumeric numeric)
1409 {
1410   GtkCssValue *value;
1411 
1412   if (!numeric_value_is_valid (numeric))
1413     return NULL;
1414 
1415   value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_FONT_VARIANT_NUMERIC);
1416   value->value = numeric;
1417   value->name = NULL;
1418   value->is_computed = TRUE;
1419 
1420   return value;
1421 }
1422 
1423 GtkCssFontVariantNumeric
_gtk_css_font_variant_numeric_try_parse_one(GtkCssParser * parser,GtkCssFontVariantNumeric base)1424 _gtk_css_font_variant_numeric_try_parse_one (GtkCssParser             *parser,
1425                                              GtkCssFontVariantNumeric  base)
1426 {
1427   guint i;
1428   GtkCssFontVariantNumeric value = 0;
1429 
1430   g_return_val_if_fail (parser != NULL, 0);
1431 
1432   for (i = 0; i < G_N_ELEMENTS (font_variant_numeric_values); i++)
1433     {
1434       if (gtk_css_parser_try_ident (parser, font_variant_numeric_values[i].name))
1435         {
1436           value = font_variant_numeric_values[i].value;
1437           break;
1438         }
1439     }
1440 
1441   if (value == 0)
1442     return base; /* not parsing this value */
1443 
1444   if ((base | value) == base)
1445     return 0; /* repeated value */
1446 
1447   if (!numeric_value_is_valid (base | value))
1448     return 0; /* bad combination */
1449 
1450   return base | value;
1451 }
1452 
1453 GtkCssFontVariantNumeric
_gtk_css_font_variant_numeric_value_get(const GtkCssValue * value)1454 _gtk_css_font_variant_numeric_value_get (const GtkCssValue *value)
1455 {
1456   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_NUMERIC, GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL);
1457 
1458   return value->value;
1459 }
1460 
1461 /* GtkCssFontVariantEastAsian */
1462 
1463 static FlagsValue font_variant_east_asian_values[] = {
1464   { GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL, "normal" },
1465   { GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS78, "jis78" },
1466   { GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS83, "jis83" },
1467   { GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS90, "jis90" },
1468   { GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS04, "jis04" },
1469   { GTK_CSS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED, "simplified" },
1470   { GTK_CSS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL, "traditional" },
1471   { GTK_CSS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH, "full-width" },
1472   { GTK_CSS_FONT_VARIANT_EAST_ASIAN_PROPORTIONAL, "proportional-width" },
1473   { GTK_CSS_FONT_VARIANT_EAST_ASIAN_RUBY, "ruby" }
1474 };
1475 
1476 static void
gtk_css_font_variant_east_asian_value_print(const GtkCssValue * value,GString * string)1477 gtk_css_font_variant_east_asian_value_print (const GtkCssValue *value,
1478                                              GString           *string)
1479 {
1480   gtk_css_value_flags_print (font_variant_east_asian_values,
1481                              G_N_ELEMENTS (font_variant_east_asian_values),
1482                              value, string);
1483 }
1484 
1485 static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN = {
1486   "GtkCssFontVariantEastAsianValue",
1487   gtk_css_value_enum_free,
1488   gtk_css_value_enum_compute,
1489   gtk_css_value_flags_equal,
1490   gtk_css_value_enum_transition,
1491   NULL,
1492   NULL,
1493   gtk_css_font_variant_east_asian_value_print
1494 };
1495 
1496 static gboolean
east_asian_value_is_valid(GtkCssFontVariantEastAsian east_asian)1497 east_asian_value_is_valid (GtkCssFontVariantEastAsian east_asian)
1498 {
1499   if ((east_asian & GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL) &&
1500       (east_asian != GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL))
1501     return FALSE;
1502 
1503   if (gtk_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS78 |
1504                                   GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS83 |
1505                                   GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS90 |
1506                                   GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS04 |
1507                                   GTK_CSS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED |
1508                                   GTK_CSS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL)) > 1)
1509     return FALSE;
1510 
1511   if (gtk_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH |
1512                                   GTK_CSS_FONT_VARIANT_EAST_ASIAN_PROPORTIONAL)) > 1)
1513     return FALSE;
1514 
1515   return TRUE;
1516 }
1517 
1518 GtkCssValue *
_gtk_css_font_variant_east_asian_value_new(GtkCssFontVariantEastAsian east_asian)1519 _gtk_css_font_variant_east_asian_value_new (GtkCssFontVariantEastAsian east_asian)
1520 {
1521   GtkCssValue *value;
1522 
1523   if (!east_asian_value_is_valid (east_asian))
1524     return NULL;
1525 
1526   value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN);
1527   value->value = east_asian;
1528   value->name = NULL;
1529   value->is_computed = TRUE;
1530 
1531   return value;
1532 }
1533 
1534 GtkCssFontVariantEastAsian
_gtk_css_font_variant_east_asian_try_parse_one(GtkCssParser * parser,GtkCssFontVariantEastAsian base)1535 _gtk_css_font_variant_east_asian_try_parse_one (GtkCssParser               *parser,
1536                                                 GtkCssFontVariantEastAsian  base)
1537 {
1538   guint i;
1539   GtkCssFontVariantEastAsian value = 0;
1540 
1541   g_return_val_if_fail (parser != NULL, 0);
1542 
1543   for (i = 0; i < G_N_ELEMENTS (font_variant_east_asian_values); i++)
1544     {
1545       if (gtk_css_parser_try_ident (parser, font_variant_east_asian_values[i].name))
1546         {
1547           value = font_variant_east_asian_values[i].value;
1548           break;
1549         }
1550     }
1551 
1552   if (value == 0)
1553     return base; /* not parsing this value */
1554 
1555   if ((base | value) == base)
1556     return 0; /* repeated value */
1557 
1558   if (!east_asian_value_is_valid (base | value))
1559     return 0; /* bad combination */
1560 
1561   return base | value;
1562 }
1563 
1564 GtkCssFontVariantEastAsian
_gtk_css_font_variant_east_asian_value_get(const GtkCssValue * value)1565 _gtk_css_font_variant_east_asian_value_get (const GtkCssValue *value)
1566 {
1567   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN, GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL);
1568 
1569   return value->value;
1570 }
1571