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 /* repeated API */
28 
29 struct _GtkCssValue {
30   GTK_CSS_VALUE_BASE
31   int value;
32   const char *name;
33 };
34 
35 static void
gtk_css_value_enum_free(GtkCssValue * value)36 gtk_css_value_enum_free (GtkCssValue *value)
37 {
38   g_slice_free (GtkCssValue, value);
39 }
40 
41 static GtkCssValue *
gtk_css_value_enum_compute(GtkCssValue * value,guint property_id,GtkStyleProviderPrivate * provider,GtkCssStyle * style,GtkCssStyle * parent_style)42 gtk_css_value_enum_compute (GtkCssValue             *value,
43                             guint                    property_id,
44                             GtkStyleProviderPrivate *provider,
45                             GtkCssStyle             *style,
46                             GtkCssStyle             *parent_style)
47 {
48   return _gtk_css_value_ref (value);
49 }
50 
51 static gboolean
gtk_css_value_enum_equal(const GtkCssValue * enum1,const GtkCssValue * enum2)52 gtk_css_value_enum_equal (const GtkCssValue *enum1,
53                           const GtkCssValue *enum2)
54 {
55   return enum1 == enum2;
56 }
57 
58 static GtkCssValue *
gtk_css_value_enum_transition(GtkCssValue * start,GtkCssValue * end,guint property_id,double progress)59 gtk_css_value_enum_transition (GtkCssValue *start,
60                                GtkCssValue *end,
61                                guint        property_id,
62                                double       progress)
63 {
64   return NULL;
65 }
66 
67 static void
gtk_css_value_enum_print(const GtkCssValue * value,GString * string)68 gtk_css_value_enum_print (const GtkCssValue *value,
69                           GString           *string)
70 {
71   g_string_append (string, value->name);
72 }
73 
74 /* GtkBorderStyle */
75 
76 static const GtkCssValueClass GTK_CSS_VALUE_BORDER_STYLE = {
77   gtk_css_value_enum_free,
78   gtk_css_value_enum_compute,
79   gtk_css_value_enum_equal,
80   gtk_css_value_enum_transition,
81   gtk_css_value_enum_print
82 };
83 
84 static GtkCssValue border_style_values[] = {
85   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_NONE, "none" },
86   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_SOLID, "solid" },
87   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_INSET, "inset" },
88   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_OUTSET, "outset" },
89   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_HIDDEN, "hidden" },
90   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DOTTED, "dotted" },
91   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DASHED, "dashed" },
92   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DOUBLE, "double" },
93   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_GROOVE, "groove" },
94   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_RIDGE, "ridge" }
95 };
96 
97 GtkCssValue *
_gtk_css_border_style_value_new(GtkBorderStyle border_style)98 _gtk_css_border_style_value_new (GtkBorderStyle border_style)
99 {
100   g_return_val_if_fail (border_style < G_N_ELEMENTS (border_style_values), NULL);
101 
102   return _gtk_css_value_ref (&border_style_values[border_style]);
103 }
104 
105 GtkCssValue *
_gtk_css_border_style_value_try_parse(GtkCssParser * parser)106 _gtk_css_border_style_value_try_parse (GtkCssParser *parser)
107 {
108   guint i;
109 
110   g_return_val_if_fail (parser != NULL, NULL);
111 
112   for (i = 0; i < G_N_ELEMENTS (border_style_values); i++)
113     {
114       if (_gtk_css_parser_try (parser, border_style_values[i].name, TRUE))
115         return _gtk_css_value_ref (&border_style_values[i]);
116     }
117 
118   return NULL;
119 }
120 
121 GtkBorderStyle
_gtk_css_border_style_value_get(const GtkCssValue * value)122 _gtk_css_border_style_value_get (const GtkCssValue *value)
123 {
124   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_BORDER_STYLE, GTK_BORDER_STYLE_NONE);
125 
126   return value->value;
127 }
128 
129 /* GtkCssBlendMode */
130 
131 static const GtkCssValueClass GTK_CSS_VALUE_BLEND_MODE = {
132   gtk_css_value_enum_free,
133   gtk_css_value_enum_compute,
134   gtk_css_value_enum_equal,
135   gtk_css_value_enum_transition,
136   gtk_css_value_enum_print
137 };
138 
139 static GtkCssValue blend_mode_values[] = {
140   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_COLOR_BURN, "color-burn" },
141   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_COLOR_DODGE, "color-dodge" },
142   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_COLOR, "color" },
143   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_DARKEN, "darken" },
144   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_DIFFERENCE, "difference" },
145   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_EXCLUSION, "exclusion" },
146   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_HARD_LIGHT, "hard-light" },
147   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_HUE, "hue" },
148   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_LIGHTEN, "lighten" },
149   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_LUMINOSITY, "luminosity" },
150   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_MULTIPLY, "multiply" },
151   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_NORMAL, "normal" },
152   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_OVERLAY, "overlay" },
153   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_SATURATE, "saturate" },
154   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_SCREEN, "screen" },
155   { &GTK_CSS_VALUE_BLEND_MODE, 1, GTK_CSS_BLEND_MODE_SOFT_LIGHT, "soft-light" }
156 };
157 
158 GtkCssValue *
_gtk_css_blend_mode_value_new(GtkCssBlendMode blend_mode)159 _gtk_css_blend_mode_value_new (GtkCssBlendMode blend_mode)
160 {
161   g_return_val_if_fail (blend_mode < G_N_ELEMENTS (blend_mode_values), NULL);
162 
163   return _gtk_css_value_ref (&blend_mode_values[blend_mode]);
164 }
165 
166 GtkCssValue *
_gtk_css_blend_mode_value_try_parse(GtkCssParser * parser)167 _gtk_css_blend_mode_value_try_parse (GtkCssParser *parser)
168 {
169   guint i;
170 
171   g_return_val_if_fail (parser != NULL, NULL);
172 
173   for (i = 0; i < G_N_ELEMENTS (blend_mode_values); i++)
174     {
175       if (_gtk_css_parser_try (parser, blend_mode_values[i].name, TRUE))
176         return _gtk_css_value_ref (&blend_mode_values[i]);
177     }
178 
179   return NULL;
180 }
181 
182 GtkCssBlendMode
_gtk_css_blend_mode_value_get(const GtkCssValue * value)183 _gtk_css_blend_mode_value_get (const GtkCssValue *value)
184 {
185   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_BLEND_MODE, GTK_CSS_BLEND_MODE_NORMAL);
186 
187   return value->value;
188 }
189 
190 /* GtkCssFontSize */
191 
192 static double
get_dpi(GtkCssStyle * style)193 get_dpi (GtkCssStyle *style)
194 {
195   return _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_DPI), 96);
196 }
197 
198 /* XXX: Kinda bad to have that machinery here, nobody expects vital font
199  * size code to appear in gtkcssvalueenum.c.
200  */
201 #define DEFAULT_FONT_SIZE_PT 10
202 
203 double
gtk_css_font_size_get_default_px(GtkStyleProviderPrivate * provider,GtkCssStyle * style)204 gtk_css_font_size_get_default_px (GtkStyleProviderPrivate *provider,
205                                   GtkCssStyle             *style)
206 {
207   GtkSettings *settings;
208   int font_size;
209 
210   settings = _gtk_style_provider_private_get_settings (provider);
211   if (settings == NULL)
212     return DEFAULT_FONT_SIZE_PT * get_dpi (style) / 72.0;
213 
214   font_size = gtk_settings_get_font_size (settings);
215   if (font_size == 0)
216     return DEFAULT_FONT_SIZE_PT * get_dpi (style) / 72.0;
217   else if (gtk_settings_get_font_size_is_absolute (settings))
218     return (double) font_size / PANGO_SCALE;
219   else
220     return ((double) font_size / PANGO_SCALE) * get_dpi (style) / 72.0;
221 }
222 
223 static GtkCssValue *
gtk_css_value_font_size_compute(GtkCssValue * value,guint property_id,GtkStyleProviderPrivate * provider,GtkCssStyle * style,GtkCssStyle * parent_style)224 gtk_css_value_font_size_compute (GtkCssValue             *value,
225                                  guint                    property_id,
226                                  GtkStyleProviderPrivate *provider,
227                                  GtkCssStyle             *style,
228                                  GtkCssStyle             *parent_style)
229 {
230   double font_size;
231 
232   switch (value->value)
233     {
234     case GTK_CSS_FONT_SIZE_XX_SMALL:
235       font_size = gtk_css_font_size_get_default_px (provider, style) * 3. / 5;
236       break;
237     case GTK_CSS_FONT_SIZE_X_SMALL:
238       font_size = gtk_css_font_size_get_default_px (provider, style) * 3. / 4;
239       break;
240     case GTK_CSS_FONT_SIZE_SMALL:
241       font_size = gtk_css_font_size_get_default_px (provider, style) * 8. / 9;
242       break;
243     default:
244       g_assert_not_reached ();
245       /* fall thru */
246     case GTK_CSS_FONT_SIZE_MEDIUM:
247       font_size = gtk_css_font_size_get_default_px (provider, style);
248       break;
249     case GTK_CSS_FONT_SIZE_LARGE:
250       font_size = gtk_css_font_size_get_default_px (provider, style) * 6. / 5;
251       break;
252     case GTK_CSS_FONT_SIZE_X_LARGE:
253       font_size = gtk_css_font_size_get_default_px (provider, style) * 3. / 2;
254       break;
255     case GTK_CSS_FONT_SIZE_XX_LARGE:
256       font_size = gtk_css_font_size_get_default_px (provider, style) * 2;
257       break;
258     case GTK_CSS_FONT_SIZE_SMALLER:
259       if (parent_style)
260         font_size = _gtk_css_number_value_get (gtk_css_style_get_value (parent_style, GTK_CSS_PROPERTY_FONT_SIZE), 100);
261       else
262         font_size = gtk_css_font_size_get_default_px (provider, style);
263       /* XXX: This is what WebKit does... */
264       font_size /= 1.2;
265       break;
266     case GTK_CSS_FONT_SIZE_LARGER:
267       if (parent_style)
268         font_size = _gtk_css_number_value_get (gtk_css_style_get_value (parent_style, GTK_CSS_PROPERTY_FONT_SIZE), 100);
269       else
270         font_size = gtk_css_font_size_get_default_px (provider, style);
271       /* XXX: This is what WebKit does... */
272       font_size *= 1.2;
273       break;
274   }
275 
276   return _gtk_css_number_value_new (font_size, GTK_CSS_PX);
277 }
278 
279 static const GtkCssValueClass GTK_CSS_VALUE_FONT_SIZE = {
280   gtk_css_value_enum_free,
281   gtk_css_value_font_size_compute,
282   gtk_css_value_enum_equal,
283   gtk_css_value_enum_transition,
284   gtk_css_value_enum_print
285 };
286 
287 static GtkCssValue font_size_values[] = {
288   { &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_SMALLER, "smaller" },
289   { &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_LARGER, "larger" },
290   { &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_XX_SMALL, "xx-small" },
291   { &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_X_SMALL, "x-small" },
292   { &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_SMALL, "small" },
293   { &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_MEDIUM, "medium" },
294   { &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_LARGE, "large" },
295   { &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_X_LARGE, "x-large" },
296   { &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_XX_LARGE, "xx-large" }
297 };
298 
299 GtkCssValue *
_gtk_css_font_size_value_new(GtkCssFontSize font_size)300 _gtk_css_font_size_value_new (GtkCssFontSize font_size)
301 {
302   g_return_val_if_fail (font_size < G_N_ELEMENTS (font_size_values), NULL);
303 
304   return _gtk_css_value_ref (&font_size_values[font_size]);
305 }
306 
307 GtkCssValue *
_gtk_css_font_size_value_try_parse(GtkCssParser * parser)308 _gtk_css_font_size_value_try_parse (GtkCssParser *parser)
309 {
310   guint i;
311 
312   g_return_val_if_fail (parser != NULL, NULL);
313 
314   for (i = 0; i < G_N_ELEMENTS (font_size_values); i++)
315     {
316       if (_gtk_css_parser_try (parser, font_size_values[i].name, TRUE))
317         return _gtk_css_value_ref (&font_size_values[i]);
318     }
319 
320   return NULL;
321 }
322 
323 GtkCssFontSize
_gtk_css_font_size_value_get(const GtkCssValue * value)324 _gtk_css_font_size_value_get (const GtkCssValue *value)
325 {
326   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_SIZE, GTK_CSS_FONT_SIZE_MEDIUM);
327 
328   return value->value;
329 }
330 
331 /* PangoStyle */
332 
333 static const GtkCssValueClass GTK_CSS_VALUE_FONT_STYLE = {
334   gtk_css_value_enum_free,
335   gtk_css_value_enum_compute,
336   gtk_css_value_enum_equal,
337   gtk_css_value_enum_transition,
338   gtk_css_value_enum_print
339 };
340 
341 static GtkCssValue font_style_values[] = {
342   { &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_NORMAL, "normal" },
343   { &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_OBLIQUE, "oblique" },
344   { &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_ITALIC, "italic" }
345 };
346 
347 GtkCssValue *
_gtk_css_font_style_value_new(PangoStyle font_style)348 _gtk_css_font_style_value_new (PangoStyle font_style)
349 {
350   g_return_val_if_fail (font_style < G_N_ELEMENTS (font_style_values), NULL);
351 
352   return _gtk_css_value_ref (&font_style_values[font_style]);
353 }
354 
355 GtkCssValue *
_gtk_css_font_style_value_try_parse(GtkCssParser * parser)356 _gtk_css_font_style_value_try_parse (GtkCssParser *parser)
357 {
358   guint i;
359 
360   g_return_val_if_fail (parser != NULL, NULL);
361 
362   for (i = 0; i < G_N_ELEMENTS (font_style_values); i++)
363     {
364       if (_gtk_css_parser_try (parser, font_style_values[i].name, TRUE))
365         return _gtk_css_value_ref (&font_style_values[i]);
366     }
367 
368   return NULL;
369 }
370 
371 PangoStyle
_gtk_css_font_style_value_get(const GtkCssValue * value)372 _gtk_css_font_style_value_get (const GtkCssValue *value)
373 {
374   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_STYLE, PANGO_STYLE_NORMAL);
375 
376   return value->value;
377 }
378 
379 /* PangoVariant */
380 
381 static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT = {
382   gtk_css_value_enum_free,
383   gtk_css_value_enum_compute,
384   gtk_css_value_enum_equal,
385   gtk_css_value_enum_transition,
386   gtk_css_value_enum_print
387 };
388 
389 static GtkCssValue font_variant_values[] = {
390   { &GTK_CSS_VALUE_FONT_VARIANT, 1, PANGO_VARIANT_NORMAL, "normal" },
391   { &GTK_CSS_VALUE_FONT_VARIANT, 1, PANGO_VARIANT_SMALL_CAPS, "small-caps" }
392 };
393 
394 GtkCssValue *
_gtk_css_font_variant_value_new(PangoVariant font_variant)395 _gtk_css_font_variant_value_new (PangoVariant font_variant)
396 {
397   g_return_val_if_fail ((gint)font_variant < G_N_ELEMENTS (font_variant_values), NULL);
398 
399   return _gtk_css_value_ref (&font_variant_values[font_variant]);
400 }
401 
402 GtkCssValue *
_gtk_css_font_variant_value_try_parse(GtkCssParser * parser)403 _gtk_css_font_variant_value_try_parse (GtkCssParser *parser)
404 {
405   guint i;
406 
407   g_return_val_if_fail (parser != NULL, NULL);
408 
409   for (i = 0; i < G_N_ELEMENTS (font_variant_values); i++)
410     {
411       if (_gtk_css_parser_try (parser, font_variant_values[i].name, TRUE))
412         return _gtk_css_value_ref (&font_variant_values[i]);
413     }
414 
415   return NULL;
416 }
417 
418 PangoVariant
_gtk_css_font_variant_value_get(const GtkCssValue * value)419 _gtk_css_font_variant_value_get (const GtkCssValue *value)
420 {
421   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT, PANGO_VARIANT_NORMAL);
422 
423   return value->value;
424 }
425 
426 /* PangoWeight */
427 
428 #define BOLDER -1
429 #define LIGHTER -2
430 
431 static GtkCssValue *
gtk_css_value_font_weight_compute(GtkCssValue * value,guint property_id,GtkStyleProviderPrivate * provider,GtkCssStyle * style,GtkCssStyle * parent_style)432 gtk_css_value_font_weight_compute (GtkCssValue             *value,
433                                    guint                    property_id,
434                                    GtkStyleProviderPrivate *provider,
435                                    GtkCssStyle             *style,
436                                    GtkCssStyle             *parent_style)
437 {
438   PangoWeight new_weight;
439   int parent_value;
440 
441   if (value->value >= 0)
442     return _gtk_css_value_ref (value);
443 
444   if (parent_style)
445     parent_value = gtk_css_style_get_value (parent_style, property_id)->value;
446   else
447     parent_value = 400;
448 
449   if (value->value == BOLDER)
450     {
451       if (parent_value < 400)
452         new_weight = PANGO_WEIGHT_NORMAL;
453       else if (parent_value < 600)
454         new_weight = PANGO_WEIGHT_BOLD;
455       else
456         new_weight = PANGO_WEIGHT_HEAVY;
457     }
458   else if (value->value == LIGHTER)
459     {
460       if (parent_value > 700)
461         new_weight = PANGO_WEIGHT_BOLD;
462       else if (parent_value > 500)
463         new_weight = PANGO_WEIGHT_NORMAL;
464       else
465         new_weight = PANGO_WEIGHT_THIN;
466     }
467   else
468     {
469       g_assert_not_reached ();
470       new_weight = PANGO_WEIGHT_NORMAL;
471     }
472 
473   return _gtk_css_font_weight_value_new (new_weight);
474 }
475 
476 static GtkCssValue *
gtk_css_value_font_weight_transition(GtkCssValue * start,GtkCssValue * end,guint property_id,double progress)477 gtk_css_value_font_weight_transition (GtkCssValue *start,
478                                       GtkCssValue *end,
479                                       guint        property_id,
480                                       double       progress)
481 {
482   PangoWeight new_weight;
483 
484   if (start->value < 0 || end->value < 0)
485     return NULL;
486 
487   new_weight = (start->value + end->value + 50) / 200 * 100;
488 
489   return _gtk_css_font_weight_value_new (new_weight);
490 }
491 
492 static const GtkCssValueClass GTK_CSS_VALUE_FONT_WEIGHT = {
493   gtk_css_value_enum_free,
494   gtk_css_value_font_weight_compute,
495   gtk_css_value_enum_equal,
496   gtk_css_value_font_weight_transition,
497   gtk_css_value_enum_print
498 };
499 
500 static GtkCssValue font_weight_values[] = {
501   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, BOLDER, "bolder" },
502   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, LIGHTER, "lighter" },
503   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_THIN, "100" },
504   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_ULTRALIGHT, "200" },
505   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_LIGHT, "300" },
506   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_NORMAL, "normal" },
507   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_MEDIUM, "500" },
508   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_SEMIBOLD, "600" },
509   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_BOLD, "bold" },
510   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_ULTRABOLD, "800" },
511   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_HEAVY, "900" },
512   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_ULTRAHEAVY, "1000" }
513 };
514 
515 GtkCssValue *
_gtk_css_font_weight_value_new(PangoWeight font_weight)516 _gtk_css_font_weight_value_new (PangoWeight font_weight)
517 {
518   guint i;
519   gint w;
520 
521   w = ((font_weight + 50) / 100) * 100;
522 
523   for (i = 2; i < G_N_ELEMENTS (font_weight_values); i++)
524     {
525       if (font_weight_values[i].value == w)
526         return _gtk_css_value_ref (&font_weight_values[i]);
527     }
528 
529   g_return_val_if_reached (NULL);
530 }
531 
532 GtkCssValue *
_gtk_css_font_weight_value_try_parse(GtkCssParser * parser)533 _gtk_css_font_weight_value_try_parse (GtkCssParser *parser)
534 {
535   guint i;
536 
537   g_return_val_if_fail (parser != NULL, NULL);
538 
539   for (i = 0; i < G_N_ELEMENTS (font_weight_values); i++)
540     {
541       if (_gtk_css_parser_try (parser, font_weight_values[i].name, TRUE))
542         return _gtk_css_value_ref (&font_weight_values[i]);
543     }
544   /* special cases go here */
545   if (_gtk_css_parser_try (parser, "400", TRUE))
546     return _gtk_css_value_ref (&font_weight_values[5]);
547   if (_gtk_css_parser_try (parser, "700", TRUE))
548     return _gtk_css_value_ref (&font_weight_values[8]);
549 
550   return NULL;
551 }
552 
553 PangoWeight
_gtk_css_font_weight_value_get(const GtkCssValue * value)554 _gtk_css_font_weight_value_get (const GtkCssValue *value)
555 {
556   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_WEIGHT, PANGO_WEIGHT_NORMAL);
557 
558   return value->value;
559 }
560 
561 #undef BOLDER
562 #undef LIGHTER
563 
564 /* PangoStretch */
565 
566 static const GtkCssValueClass GTK_CSS_VALUE_FONT_STRETCH = {
567   gtk_css_value_enum_free,
568   gtk_css_value_enum_compute,
569   gtk_css_value_enum_equal,
570   gtk_css_value_enum_transition,
571   gtk_css_value_enum_print
572 };
573 
574 static GtkCssValue font_stretch_values[] = {
575   { &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_ULTRA_CONDENSED, "ultra-condensed" },
576   { &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_EXTRA_CONDENSED, "extra-condensed" },
577   { &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_CONDENSED, "condensed" },
578   { &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_SEMI_CONDENSED, "semi-condensed" },
579   { &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_NORMAL, "normal" },
580   { &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_SEMI_EXPANDED, "semi-expanded" },
581   { &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_EXPANDED, "expanded" },
582   { &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_EXTRA_EXPANDED, "extra-expanded" },
583   { &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_ULTRA_EXPANDED, "ultra-expanded" },
584 };
585 
586 GtkCssValue *
_gtk_css_font_stretch_value_new(PangoStretch font_stretch)587 _gtk_css_font_stretch_value_new (PangoStretch font_stretch)
588 {
589   g_return_val_if_fail (font_stretch < G_N_ELEMENTS (font_stretch_values), NULL);
590 
591   return _gtk_css_value_ref (&font_stretch_values[font_stretch]);
592 }
593 
594 GtkCssValue *
_gtk_css_font_stretch_value_try_parse(GtkCssParser * parser)595 _gtk_css_font_stretch_value_try_parse (GtkCssParser *parser)
596 {
597   guint i;
598 
599   g_return_val_if_fail (parser != NULL, NULL);
600 
601   for (i = 0; i < G_N_ELEMENTS (font_stretch_values); i++)
602     {
603       if (_gtk_css_parser_try (parser, font_stretch_values[i].name, TRUE))
604         return _gtk_css_value_ref (&font_stretch_values[i]);
605     }
606 
607   return NULL;
608 }
609 
610 PangoStretch
_gtk_css_font_stretch_value_get(const GtkCssValue * value)611 _gtk_css_font_stretch_value_get (const GtkCssValue *value)
612 {
613   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_STRETCH, PANGO_STRETCH_NORMAL);
614 
615   return value->value;
616 }
617 
618 /* GtkTextDecorationLine */
619 
620 static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_LINE = {
621   gtk_css_value_enum_free,
622   gtk_css_value_enum_compute,
623   gtk_css_value_enum_equal,
624   gtk_css_value_enum_transition,
625   gtk_css_value_enum_print
626 };
627 
628 static GtkCssValue text_decoration_line_values[] = {
629   { &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, GTK_CSS_TEXT_DECORATION_LINE_NONE, "none" },
630   { &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE, "underline" },
631   { &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH, "line-through" },
632 };
633 
634 GtkCssValue *
_gtk_css_text_decoration_line_value_new(GtkTextDecorationLine line)635 _gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line)
636 {
637   g_return_val_if_fail (line < G_N_ELEMENTS (text_decoration_line_values), NULL);
638 
639   return _gtk_css_value_ref (&text_decoration_line_values[line]);
640 }
641 
642 GtkCssValue *
_gtk_css_text_decoration_line_value_try_parse(GtkCssParser * parser)643 _gtk_css_text_decoration_line_value_try_parse (GtkCssParser *parser)
644 {
645   guint i;
646 
647   g_return_val_if_fail (parser != NULL, NULL);
648 
649   for (i = 0; i < G_N_ELEMENTS (text_decoration_line_values); i++)
650     {
651       if (_gtk_css_parser_try (parser, text_decoration_line_values[i].name, TRUE))
652         return _gtk_css_value_ref (&text_decoration_line_values[i]);
653     }
654 
655   return NULL;
656 }
657 
658 GtkTextDecorationLine
_gtk_css_text_decoration_line_value_get(const GtkCssValue * value)659 _gtk_css_text_decoration_line_value_get (const GtkCssValue *value)
660 {
661   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_TEXT_DECORATION_LINE, GTK_CSS_TEXT_DECORATION_LINE_NONE);
662 
663   return value->value;
664 }
665 
666 /* GtkTextDecorationStyle */
667 
668 static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_STYLE = {
669   gtk_css_value_enum_free,
670   gtk_css_value_enum_compute,
671   gtk_css_value_enum_equal,
672   gtk_css_value_enum_transition,
673   gtk_css_value_enum_print
674 };
675 
676 static GtkCssValue text_decoration_style_values[] = {
677   { &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, GTK_CSS_TEXT_DECORATION_STYLE_SOLID, "solid" },
678   { &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, GTK_CSS_TEXT_DECORATION_STYLE_DOUBLE, "double" },
679   { &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, GTK_CSS_TEXT_DECORATION_STYLE_WAVY, "wavy" },
680 };
681 
682 GtkCssValue *
_gtk_css_text_decoration_style_value_new(GtkTextDecorationStyle style)683 _gtk_css_text_decoration_style_value_new (GtkTextDecorationStyle style)
684 {
685   g_return_val_if_fail (style < G_N_ELEMENTS (text_decoration_style_values), NULL);
686 
687   return _gtk_css_value_ref (&text_decoration_style_values[style]);
688 }
689 
690 GtkCssValue *
_gtk_css_text_decoration_style_value_try_parse(GtkCssParser * parser)691 _gtk_css_text_decoration_style_value_try_parse (GtkCssParser *parser)
692 {
693   guint i;
694 
695   g_return_val_if_fail (parser != NULL, NULL);
696 
697   for (i = 0; i < G_N_ELEMENTS (text_decoration_style_values); i++)
698     {
699       if (_gtk_css_parser_try (parser, text_decoration_style_values[i].name, TRUE))
700         return _gtk_css_value_ref (&text_decoration_style_values[i]);
701     }
702 
703   return NULL;
704 }
705 
706 GtkTextDecorationStyle
_gtk_css_text_decoration_style_value_get(const GtkCssValue * value)707 _gtk_css_text_decoration_style_value_get (const GtkCssValue *value)
708 {
709   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, GTK_CSS_TEXT_DECORATION_STYLE_SOLID);
710 
711   return value->value;
712 }
713 
714 /* GtkCssArea */
715 
716 static const GtkCssValueClass GTK_CSS_VALUE_AREA = {
717   gtk_css_value_enum_free,
718   gtk_css_value_enum_compute,
719   gtk_css_value_enum_equal,
720   gtk_css_value_enum_transition,
721   gtk_css_value_enum_print
722 };
723 
724 static GtkCssValue area_values[] = {
725   { &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_BORDER_BOX, "border-box" },
726   { &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_PADDING_BOX, "padding-box" },
727   { &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_CONTENT_BOX, "content-box" }
728 };
729 
730 GtkCssValue *
_gtk_css_area_value_new(GtkCssArea area)731 _gtk_css_area_value_new (GtkCssArea area)
732 {
733   guint i;
734 
735   for (i = 0; i < G_N_ELEMENTS (area_values); i++)
736     {
737       if (area_values[i].value == area)
738         return _gtk_css_value_ref (&area_values[i]);
739     }
740 
741   g_return_val_if_reached (NULL);
742 }
743 
744 GtkCssValue *
_gtk_css_area_value_try_parse(GtkCssParser * parser)745 _gtk_css_area_value_try_parse (GtkCssParser *parser)
746 {
747   guint i;
748 
749   g_return_val_if_fail (parser != NULL, NULL);
750 
751   for (i = 0; i < G_N_ELEMENTS (area_values); i++)
752     {
753       if (_gtk_css_parser_try (parser, area_values[i].name, TRUE))
754         return _gtk_css_value_ref (&area_values[i]);
755     }
756 
757   return NULL;
758 }
759 
760 GtkCssArea
_gtk_css_area_value_get(const GtkCssValue * value)761 _gtk_css_area_value_get (const GtkCssValue *value)
762 {
763   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_AREA, GTK_CSS_AREA_BORDER_BOX);
764 
765   return value->value;
766 }
767 
768 /* GtkCssDirection */
769 
770 static const GtkCssValueClass GTK_CSS_VALUE_DIRECTION = {
771   gtk_css_value_enum_free,
772   gtk_css_value_enum_compute,
773   gtk_css_value_enum_equal,
774   gtk_css_value_enum_transition,
775   gtk_css_value_enum_print
776 };
777 
778 static GtkCssValue direction_values[] = {
779   { &GTK_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_NORMAL, "normal" },
780   { &GTK_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_REVERSE, "reverse" },
781   { &GTK_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_ALTERNATE, "alternate" },
782   { &GTK_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_ALTERNATE_REVERSE, "alternate-reverse" }
783 };
784 
785 GtkCssValue *
_gtk_css_direction_value_new(GtkCssDirection direction)786 _gtk_css_direction_value_new (GtkCssDirection direction)
787 {
788   guint i;
789 
790   for (i = 0; i < G_N_ELEMENTS (direction_values); i++)
791     {
792       if (direction_values[i].value == direction)
793         return _gtk_css_value_ref (&direction_values[i]);
794     }
795 
796   g_return_val_if_reached (NULL);
797 }
798 
799 GtkCssValue *
_gtk_css_direction_value_try_parse(GtkCssParser * parser)800 _gtk_css_direction_value_try_parse (GtkCssParser *parser)
801 {
802   int i;
803 
804   g_return_val_if_fail (parser != NULL, NULL);
805 
806   /* need to parse backwards here, otherwise "alternate" will also match "alternate-reverse".
807    * Our parser rocks!
808    */
809   for (i = G_N_ELEMENTS (direction_values) - 1; i >= 0; i--)
810     {
811       if (_gtk_css_parser_try (parser, direction_values[i].name, TRUE))
812         return _gtk_css_value_ref (&direction_values[i]);
813     }
814 
815   return NULL;
816 }
817 
818 GtkCssDirection
_gtk_css_direction_value_get(const GtkCssValue * value)819 _gtk_css_direction_value_get (const GtkCssValue *value)
820 {
821   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_DIRECTION, GTK_CSS_DIRECTION_NORMAL);
822 
823   return value->value;
824 }
825 
826 /* GtkCssPlayState */
827 
828 static const GtkCssValueClass GTK_CSS_VALUE_PLAY_STATE = {
829   gtk_css_value_enum_free,
830   gtk_css_value_enum_compute,
831   gtk_css_value_enum_equal,
832   gtk_css_value_enum_transition,
833   gtk_css_value_enum_print
834 };
835 
836 static GtkCssValue play_state_values[] = {
837   { &GTK_CSS_VALUE_PLAY_STATE, 1, GTK_CSS_PLAY_STATE_RUNNING, "running" },
838   { &GTK_CSS_VALUE_PLAY_STATE, 1, GTK_CSS_PLAY_STATE_PAUSED, "paused" }
839 };
840 
841 GtkCssValue *
_gtk_css_play_state_value_new(GtkCssPlayState play_state)842 _gtk_css_play_state_value_new (GtkCssPlayState play_state)
843 {
844   guint i;
845 
846   for (i = 0; i < G_N_ELEMENTS (play_state_values); i++)
847     {
848       if (play_state_values[i].value == play_state)
849         return _gtk_css_value_ref (&play_state_values[i]);
850     }
851 
852   g_return_val_if_reached (NULL);
853 }
854 
855 GtkCssValue *
_gtk_css_play_state_value_try_parse(GtkCssParser * parser)856 _gtk_css_play_state_value_try_parse (GtkCssParser *parser)
857 {
858   guint i;
859 
860   g_return_val_if_fail (parser != NULL, NULL);
861 
862   for (i = 0; i < G_N_ELEMENTS (play_state_values); i++)
863     {
864       if (_gtk_css_parser_try (parser, play_state_values[i].name, TRUE))
865         return _gtk_css_value_ref (&play_state_values[i]);
866     }
867 
868   return NULL;
869 }
870 
871 GtkCssPlayState
_gtk_css_play_state_value_get(const GtkCssValue * value)872 _gtk_css_play_state_value_get (const GtkCssValue *value)
873 {
874   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_PLAY_STATE, GTK_CSS_PLAY_STATE_RUNNING);
875 
876   return value->value;
877 }
878 
879 /* GtkCssFillMode */
880 
881 static const GtkCssValueClass GTK_CSS_VALUE_FILL_MODE = {
882   gtk_css_value_enum_free,
883   gtk_css_value_enum_compute,
884   gtk_css_value_enum_equal,
885   gtk_css_value_enum_transition,
886   gtk_css_value_enum_print
887 };
888 
889 static GtkCssValue fill_mode_values[] = {
890   { &GTK_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_NONE, "none" },
891   { &GTK_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_FORWARDS, "forwards" },
892   { &GTK_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_BACKWARDS, "backwards" },
893   { &GTK_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_BOTH, "both" }
894 };
895 
896 GtkCssValue *
_gtk_css_fill_mode_value_new(GtkCssFillMode fill_mode)897 _gtk_css_fill_mode_value_new (GtkCssFillMode fill_mode)
898 {
899   guint i;
900 
901   for (i = 0; i < G_N_ELEMENTS (fill_mode_values); i++)
902     {
903       if (fill_mode_values[i].value == fill_mode)
904         return _gtk_css_value_ref (&fill_mode_values[i]);
905     }
906 
907   g_return_val_if_reached (NULL);
908 }
909 
910 GtkCssValue *
_gtk_css_fill_mode_value_try_parse(GtkCssParser * parser)911 _gtk_css_fill_mode_value_try_parse (GtkCssParser *parser)
912 {
913   guint i;
914 
915   g_return_val_if_fail (parser != NULL, NULL);
916 
917   for (i = 0; i < G_N_ELEMENTS (fill_mode_values); i++)
918     {
919       if (_gtk_css_parser_try (parser, fill_mode_values[i].name, TRUE))
920         return _gtk_css_value_ref (&fill_mode_values[i]);
921     }
922 
923   return NULL;
924 }
925 
926 GtkCssFillMode
_gtk_css_fill_mode_value_get(const GtkCssValue * value)927 _gtk_css_fill_mode_value_get (const GtkCssValue *value)
928 {
929   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FILL_MODE, GTK_CSS_FILL_NONE);
930 
931   return value->value;
932 }
933 
934 /* GtkCssIconEffect */
935 
936 static const GtkCssValueClass GTK_CSS_VALUE_ICON_EFFECT = {
937   gtk_css_value_enum_free,
938   gtk_css_value_enum_compute,
939   gtk_css_value_enum_equal,
940   gtk_css_value_enum_transition,
941   gtk_css_value_enum_print
942 };
943 
944 static GtkCssValue image_effect_values[] = {
945   { &GTK_CSS_VALUE_ICON_EFFECT, 1, GTK_CSS_ICON_EFFECT_NONE, "none" },
946   { &GTK_CSS_VALUE_ICON_EFFECT, 1, GTK_CSS_ICON_EFFECT_HIGHLIGHT, "highlight" },
947   { &GTK_CSS_VALUE_ICON_EFFECT, 1, GTK_CSS_ICON_EFFECT_DIM, "dim" }
948 };
949 
950 GtkCssValue *
_gtk_css_icon_effect_value_new(GtkCssIconEffect image_effect)951 _gtk_css_icon_effect_value_new (GtkCssIconEffect image_effect)
952 {
953   guint i;
954 
955   for (i = 0; i < G_N_ELEMENTS (image_effect_values); i++)
956     {
957       if (image_effect_values[i].value == image_effect)
958         return _gtk_css_value_ref (&image_effect_values[i]);
959     }
960 
961   g_return_val_if_reached (NULL);
962 }
963 
964 GtkCssValue *
_gtk_css_icon_effect_value_try_parse(GtkCssParser * parser)965 _gtk_css_icon_effect_value_try_parse (GtkCssParser *parser)
966 {
967   guint i;
968 
969   g_return_val_if_fail (parser != NULL, NULL);
970 
971   for (i = 0; i < G_N_ELEMENTS (image_effect_values); i++)
972     {
973       if (_gtk_css_parser_try (parser, image_effect_values[i].name, TRUE))
974         return _gtk_css_value_ref (&image_effect_values[i]);
975     }
976 
977   return NULL;
978 }
979 
980 GtkCssIconEffect
_gtk_css_icon_effect_value_get(const GtkCssValue * value)981 _gtk_css_icon_effect_value_get (const GtkCssValue *value)
982 {
983   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_ICON_EFFECT, GTK_CSS_ICON_EFFECT_NONE);
984 
985   return value->value;
986 }
987 
988 void
gtk_css_icon_effect_apply(GtkCssIconEffect icon_effect,cairo_surface_t * surface)989 gtk_css_icon_effect_apply (GtkCssIconEffect  icon_effect,
990                            cairo_surface_t  *surface)
991 {
992   cairo_t *cr;
993 
994   switch (icon_effect)
995     {
996     case GTK_CSS_ICON_EFFECT_DIM:
997       cr = cairo_create (surface);
998       cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
999       cairo_set_source_rgba (cr, 0, 0, 0, 0); /* transparent */
1000       cairo_paint_with_alpha (cr, 0.5);
1001       cairo_destroy (cr);
1002       break;
1003 
1004     case GTK_CSS_ICON_EFFECT_HIGHLIGHT:
1005       cr = cairo_create (surface);
1006       cairo_set_source_rgb (cr, 0.1, 0.1, 0.1);
1007       cairo_set_operator (cr, CAIRO_OPERATOR_COLOR_DODGE);
1008       /* DANGER: We mask with ourself - that works for images, but... */
1009       cairo_mask_surface (cr, surface, 0, 0);
1010       cairo_destroy (cr);
1011       break;
1012 
1013     default:
1014       g_warn_if_reached ();
1015       /* fall through */
1016     case GTK_CSS_ICON_EFFECT_NONE:
1017       break;
1018     }
1019 }
1020 
1021 /* GtkCssIconStyle */
1022 
1023 static const GtkCssValueClass GTK_CSS_VALUE_ICON_STYLE = {
1024   gtk_css_value_enum_free,
1025   gtk_css_value_enum_compute,
1026   gtk_css_value_enum_equal,
1027   gtk_css_value_enum_transition,
1028   gtk_css_value_enum_print
1029 };
1030 
1031 static GtkCssValue icon_style_values[] = {
1032   { &GTK_CSS_VALUE_ICON_STYLE, 1, GTK_CSS_ICON_STYLE_REQUESTED, "requested" },
1033   { &GTK_CSS_VALUE_ICON_STYLE, 1, GTK_CSS_ICON_STYLE_REGULAR, "regular" },
1034   { &GTK_CSS_VALUE_ICON_STYLE, 1, GTK_CSS_ICON_STYLE_SYMBOLIC, "symbolic" }
1035 };
1036 
1037 GtkCssValue *
_gtk_css_icon_style_value_new(GtkCssIconStyle icon_style)1038 _gtk_css_icon_style_value_new (GtkCssIconStyle icon_style)
1039 {
1040   guint i;
1041 
1042   for (i = 0; i < G_N_ELEMENTS (icon_style_values); i++)
1043     {
1044       if (icon_style_values[i].value == icon_style)
1045         return _gtk_css_value_ref (&icon_style_values[i]);
1046     }
1047 
1048   g_return_val_if_reached (NULL);
1049 }
1050 
1051 GtkCssValue *
_gtk_css_icon_style_value_try_parse(GtkCssParser * parser)1052 _gtk_css_icon_style_value_try_parse (GtkCssParser *parser)
1053 {
1054   guint i;
1055 
1056   g_return_val_if_fail (parser != NULL, NULL);
1057 
1058   for (i = 0; i < G_N_ELEMENTS (icon_style_values); i++)
1059     {
1060       if (_gtk_css_parser_try (parser, icon_style_values[i].name, TRUE))
1061         return _gtk_css_value_ref (&icon_style_values[i]);
1062     }
1063 
1064   return NULL;
1065 }
1066 
1067 GtkCssIconStyle
_gtk_css_icon_style_value_get(const GtkCssValue * value)1068 _gtk_css_icon_style_value_get (const GtkCssValue *value)
1069 {
1070   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_ICON_STYLE, GTK_CSS_ICON_STYLE_REQUESTED);
1071 
1072   return value->value;
1073 }
1074