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 { >K_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_NONE, "none" },
91 { >K_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_SOLID, "solid" },
92 { >K_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_INSET, "inset" },
93 { >K_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_OUTSET, "outset" },
94 { >K_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_HIDDEN, "hidden" },
95 { >K_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DOTTED, "dotted" },
96 { >K_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DASHED, "dashed" },
97 { >K_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DOUBLE, "double" },
98 { >K_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_GROOVE, "groove" },
99 { >K_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 == >K_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 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DEFAULT, "normal" },
149 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_MULTIPLY, "multiply" },
150 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SCREEN, "screen" },
151 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_OVERLAY, "overlay" },
152 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DARKEN, "darken" },
153 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_LIGHTEN, "lighten" },
154 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR_DODGE, "color-dodge" },
155 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR_BURN, "color-burn" },
156 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_HARD_LIGHT, "hard-light" },
157 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SOFT_LIGHT, "soft-light" },
158 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DIFFERENCE, "difference" },
159 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_EXCLUSION, "exclusion" },
160 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR, "color" },
161 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_HUE, "hue" },
162 { >K_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SATURATION, "saturation" },
163 { >K_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 == >K_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 { >K_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_SMALLER, "smaller" },
300 { >K_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_LARGER, "larger" },
301 { >K_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_XX_SMALL, "xx-small" },
302 { >K_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_X_SMALL, "x-small" },
303 { >K_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_SMALL, "small" },
304 { >K_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_MEDIUM, "medium" },
305 { >K_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_LARGE, "large" },
306 { >K_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_X_LARGE, "x-large" },
307 { >K_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 == >K_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 { >K_CSS_VALUE_FONT_STYLE, 1, TRUE, PANGO_STYLE_NORMAL, "normal" },
357 { >K_CSS_VALUE_FONT_STYLE, 1, TRUE, PANGO_STYLE_OBLIQUE, "oblique" },
358 { >K_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 == >K_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 { >K_CSS_VALUE_FONT_WEIGHT, 1, FALSE, BOLDER, "bolder" },
456 { >K_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 == >K_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 { >K_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_ULTRA_CONDENSED, "ultra-condensed" },
506 { >K_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXTRA_CONDENSED, "extra-condensed" },
507 { >K_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_CONDENSED, "condensed" },
508 { >K_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_SEMI_CONDENSED, "semi-condensed" },
509 { >K_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_NORMAL, "normal" },
510 { >K_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_SEMI_EXPANDED, "semi-expanded" },
511 { >K_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXPANDED, "expanded" },
512 { >K_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXTRA_EXPANDED, "extra-expanded" },
513 { >K_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 == >K_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 { >K_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, GTK_CSS_TEXT_DECORATION_STYLE_SOLID, "solid" },
563 { >K_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, GTK_CSS_TEXT_DECORATION_STYLE_DOUBLE, "double" },
564 { >K_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 == >K_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 { >K_CSS_VALUE_AREA, 1, TRUE, GTK_CSS_AREA_BORDER_BOX, "border-box" },
614 { >K_CSS_VALUE_AREA, 1, TRUE, GTK_CSS_AREA_PADDING_BOX, "padding-box" },
615 { >K_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 == >K_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 { >K_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_NORMAL, "normal" },
671 { >K_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_REVERSE, "reverse" },
672 { >K_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_ALTERNATE, "alternate" },
673 { >K_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 == >K_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 { >K_CSS_VALUE_PLAY_STATE, 1, TRUE, GTK_CSS_PLAY_STATE_RUNNING, "running" },
732 { >K_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 == >K_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 { >K_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_NONE, "none" },
788 { >K_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_FORWARDS, "forwards" },
789 { >K_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_BACKWARDS, "backwards" },
790 { >K_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 == >K_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 { >K_CSS_VALUE_ICON_STYLE, 1, TRUE, GTK_CSS_ICON_STYLE_REQUESTED, "requested" },
846 { >K_CSS_VALUE_ICON_STYLE, 1, TRUE, GTK_CSS_ICON_STYLE_REGULAR, "regular" },
847 { >K_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 == >K_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 { >K_CSS_VALUE_FONT_KERNING, 1, TRUE, GTK_CSS_FONT_KERNING_AUTO, "auto" },
903 { >K_CSS_VALUE_FONT_KERNING, 1, TRUE, GTK_CSS_FONT_KERNING_NORMAL, "normal" },
904 { >K_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 == >K_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 { >K_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, GTK_CSS_FONT_VARIANT_POSITION_NORMAL, "normal" },
960 { >K_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, GTK_CSS_FONT_VARIANT_POSITION_SUB, "sub" },
961 { >K_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 == >K_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 { >K_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_NORMAL, "normal" },
1017 { >K_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_SMALL_CAPS, "small-caps" },
1018 { >K_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_ALL_SMALL_CAPS, "all-small-caps" },
1019 { >K_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_PETITE_CAPS, "petite-caps" },
1020 { >K_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_ALL_PETITE_CAPS, "all-petite-caps" },
1021 { >K_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_UNICASE, "unicase" },
1022 { >K_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 == >K_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 { >K_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, TRUE, GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL, "normal" },
1078 { >K_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 == >K_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, >K_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 == >K_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, >K_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 == >K_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, >K_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 == >K_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, >K_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 == >K_CSS_VALUE_FONT_VARIANT_EAST_ASIAN, GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL);
1568
1569 return value->value;
1570 }
1571