1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2011 Red Hat, Inc.
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.
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.
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/>.
20 #include "gtkcssenumvalueprivate.h"
22 #include "gtkcsscomputedvaluesprivate.h"
23 #include "gtkcssnumbervalueprivate.h"
24 #include "gtkstyleproviderprivate.h"
35 gtk_css_value_enum_free (GtkCssValue *value)
37 g_slice_free (GtkCssValue, value);
41 gtk_css_value_enum_compute (GtkCssValue *value,
43 GtkStyleProviderPrivate *provider,
44 GtkCssComputedValues *values,
45 GtkCssComputedValues *parent_values,
46 GtkCssDependencies *dependencies)
48 return _gtk_css_value_ref (value);
52 gtk_css_value_enum_equal (const GtkCssValue *enum1,
53 const GtkCssValue *enum2)
55 return enum1 == enum2;
59 gtk_css_value_enum_transition (GtkCssValue *start,
68 gtk_css_value_enum_print (const GtkCssValue *value,
71 g_string_append (string, value->name);
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
84 static GtkCssValue border_style_values[] = {
85 { >K_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_NONE, "none" },
86 { >K_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_SOLID, "solid" },
87 { >K_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_INSET, "inset" },
88 { >K_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_OUTSET, "outset" },
89 { >K_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_HIDDEN, "hidden" },
90 { >K_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DOTTED, "dotted" },
91 { >K_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DASHED, "dashed" },
92 { >K_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DOUBLE, "double" },
93 { >K_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_GROOVE, "groove" },
94 { >K_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_RIDGE, "ridge" }
98 _gtk_css_border_style_value_new (GtkBorderStyle border_style)
100 g_return_val_if_fail (border_style < G_N_ELEMENTS (border_style_values), NULL);
102 return _gtk_css_value_ref (&border_style_values[border_style]);
106 _gtk_css_border_style_value_try_parse (GtkCssParser *parser)
110 g_return_val_if_fail (parser != NULL, NULL);
112 for (i = 0; i < G_N_ELEMENTS (border_style_values); i++)
114 if (_gtk_css_parser_try (parser, border_style_values[i].name, TRUE))
115 return _gtk_css_value_ref (&border_style_values[i]);
122 _gtk_css_border_style_value_get (const GtkCssValue *value)
124 g_return_val_if_fail (value->class == >K_CSS_VALUE_BORDER_STYLE, GTK_BORDER_STYLE_NONE);
131 /* XXX: Kinda bad to have that machinery here, nobody expects vital font
132 * size code to appear in gtkcssvalueenum.c.
134 #define DEFAULT_FONT_SIZE 10
137 _gtk_css_font_size_get_default (GtkStyleProviderPrivate *provider)
139 GtkSettings *settings;
140 PangoFontDescription *description;
144 settings = _gtk_style_provider_private_get_settings (provider);
145 if (settings == NULL)
146 return DEFAULT_FONT_SIZE;
148 g_object_get (settings, "gtk-font-name", &font_name, NULL);
149 description = pango_font_description_from_string (font_name);
151 if (description == NULL)
152 return DEFAULT_FONT_SIZE;
154 if (pango_font_description_get_set_fields (description) & PANGO_FONT_MASK_SIZE)
155 font_size = (double) pango_font_description_get_size (description) / PANGO_SCALE;
157 font_size = DEFAULT_FONT_SIZE;
159 pango_font_description_free (description);
164 gtk_css_value_font_size_compute (GtkCssValue *value,
166 GtkStyleProviderPrivate *provider,
167 GtkCssComputedValues *values,
168 GtkCssComputedValues *parent_values,
169 GtkCssDependencies *dependencies)
173 switch (value->value)
175 case GTK_CSS_FONT_SIZE_XX_SMALL:
176 font_size = _gtk_css_font_size_get_default (provider) * 3. / 5;
178 case GTK_CSS_FONT_SIZE_X_SMALL:
179 font_size = _gtk_css_font_size_get_default (provider) * 3. / 4;
181 case GTK_CSS_FONT_SIZE_SMALL:
182 font_size = _gtk_css_font_size_get_default (provider) * 8. / 9;
185 g_assert_not_reached ();
187 case GTK_CSS_FONT_SIZE_MEDIUM:
188 font_size = _gtk_css_font_size_get_default (provider);
190 case GTK_CSS_FONT_SIZE_LARGE:
191 font_size = _gtk_css_font_size_get_default (provider) * 6. / 5;
193 case GTK_CSS_FONT_SIZE_X_LARGE:
194 font_size = _gtk_css_font_size_get_default (provider) * 3. / 2;
196 case GTK_CSS_FONT_SIZE_XX_LARGE:
197 font_size = _gtk_css_font_size_get_default (provider) * 2;
199 case GTK_CSS_FONT_SIZE_SMALLER:
200 *dependencies = GTK_CSS_DEPENDS_ON_PARENT;
202 font_size = _gtk_css_number_value_get (_gtk_css_computed_values_get_value (parent_values, GTK_CSS_PROPERTY_FONT_SIZE), 100);
204 font_size = _gtk_css_font_size_get_default (provider);
205 /* XXX: This is what WebKit does... */
208 case GTK_CSS_FONT_SIZE_LARGER:
209 *dependencies = GTK_CSS_DEPENDS_ON_PARENT;
211 font_size = _gtk_css_number_value_get (_gtk_css_computed_values_get_value (parent_values, GTK_CSS_PROPERTY_FONT_SIZE), 100);
213 font_size = _gtk_css_font_size_get_default (provider);
214 /* XXX: This is what WebKit does... */
219 return _gtk_css_number_value_new (font_size, GTK_CSS_PX);
222 static const GtkCssValueClass GTK_CSS_VALUE_FONT_SIZE = {
223 gtk_css_value_enum_free,
224 gtk_css_value_font_size_compute,
225 gtk_css_value_enum_equal,
226 gtk_css_value_enum_transition,
227 gtk_css_value_enum_print
230 static GtkCssValue font_size_values[] = {
231 { >K_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_SMALLER, "smaller" },
232 { >K_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_LARGER, "larger" },
233 { >K_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_XX_SMALL, "xx-small" },
234 { >K_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_X_SMALL, "x-small" },
235 { >K_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_SMALL, "small" },
236 { >K_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_MEDIUM, "medium" },
237 { >K_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_LARGE, "large" },
238 { >K_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_X_LARGE, "x-large" },
239 { >K_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_XX_LARGE, "xx-large" }
243 _gtk_css_font_size_value_new (GtkCssFontSize font_size)
245 g_return_val_if_fail (font_size < G_N_ELEMENTS (font_size_values), NULL);
247 return _gtk_css_value_ref (&font_size_values[font_size]);
251 _gtk_css_font_size_value_try_parse (GtkCssParser *parser)
255 g_return_val_if_fail (parser != NULL, NULL);
257 for (i = 0; i < G_N_ELEMENTS (font_size_values); i++)
259 if (_gtk_css_parser_try (parser, font_size_values[i].name, TRUE))
260 return _gtk_css_value_ref (&font_size_values[i]);
267 _gtk_css_font_size_value_get (const GtkCssValue *value)
269 g_return_val_if_fail (value->class == >K_CSS_VALUE_FONT_SIZE, GTK_CSS_FONT_SIZE_MEDIUM);
276 static const GtkCssValueClass GTK_CSS_VALUE_FONT_STYLE = {
277 gtk_css_value_enum_free,
278 gtk_css_value_enum_compute,
279 gtk_css_value_enum_equal,
280 gtk_css_value_enum_transition,
281 gtk_css_value_enum_print
284 static GtkCssValue font_style_values[] = {
285 { >K_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_NORMAL, "normal" },
286 { >K_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_OBLIQUE, "oblique" },
287 { >K_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_ITALIC, "italic" }
291 _gtk_css_font_style_value_new (PangoStyle font_style)
293 g_return_val_if_fail (font_style < G_N_ELEMENTS (font_style_values), NULL);
295 return _gtk_css_value_ref (&font_style_values[font_style]);
299 _gtk_css_font_style_value_try_parse (GtkCssParser *parser)
303 g_return_val_if_fail (parser != NULL, NULL);
305 for (i = 0; i < G_N_ELEMENTS (font_style_values); i++)
307 if (_gtk_css_parser_try (parser, font_style_values[i].name, TRUE))
308 return _gtk_css_value_ref (&font_style_values[i]);
315 _gtk_css_font_style_value_get (const GtkCssValue *value)
317 g_return_val_if_fail (value->class == >K_CSS_VALUE_FONT_STYLE, PANGO_STYLE_NORMAL);
324 static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT = {
325 gtk_css_value_enum_free,
326 gtk_css_value_enum_compute,
327 gtk_css_value_enum_equal,
328 gtk_css_value_enum_transition,
329 gtk_css_value_enum_print
332 static GtkCssValue font_variant_values[] = {
333 { >K_CSS_VALUE_FONT_VARIANT, 1, PANGO_VARIANT_NORMAL, "normal" },
334 { >K_CSS_VALUE_FONT_VARIANT, 1, PANGO_VARIANT_SMALL_CAPS, "small-caps" }
338 _gtk_css_font_variant_value_new (PangoVariant font_variant)
340 g_return_val_if_fail (font_variant < G_N_ELEMENTS (font_variant_values), NULL);
342 return _gtk_css_value_ref (&font_variant_values[font_variant]);
346 _gtk_css_font_variant_value_try_parse (GtkCssParser *parser)
350 g_return_val_if_fail (parser != NULL, NULL);
352 for (i = 0; i < G_N_ELEMENTS (font_variant_values); i++)
354 if (_gtk_css_parser_try (parser, font_variant_values[i].name, TRUE))
355 return _gtk_css_value_ref (&font_variant_values[i]);
362 _gtk_css_font_variant_value_get (const GtkCssValue *value)
364 g_return_val_if_fail (value->class == >K_CSS_VALUE_FONT_VARIANT, PANGO_VARIANT_NORMAL);
371 static const GtkCssValueClass GTK_CSS_VALUE_FONT_WEIGHT = {
372 gtk_css_value_enum_free,
373 gtk_css_value_enum_compute,
374 gtk_css_value_enum_equal,
375 gtk_css_value_enum_transition,
376 gtk_css_value_enum_print
379 static GtkCssValue font_weight_values[] = {
380 { >K_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_THIN, "100" },
381 { >K_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_ULTRALIGHT, "200" },
382 { >K_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_LIGHT, "300" },
383 { >K_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_NORMAL, "normal" },
384 { >K_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_MEDIUM, "500" },
385 { >K_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_SEMIBOLD, "600" },
386 { >K_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_BOLD, "bold" },
387 { >K_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_ULTRABOLD, "800" },
388 { >K_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_HEAVY, "900" }
392 _gtk_css_font_weight_value_new (PangoWeight font_weight)
397 w = ((font_weight + 50) / 100) * 100;
399 for (i = 0; i < G_N_ELEMENTS (font_weight_values); i++)
401 if (font_weight_values[i].value == w)
402 return _gtk_css_value_ref (&font_weight_values[i]);
405 g_return_val_if_reached (NULL);
409 _gtk_css_font_weight_value_try_parse (GtkCssParser *parser)
413 g_return_val_if_fail (parser != NULL, NULL);
415 for (i = 0; i < G_N_ELEMENTS (font_weight_values); i++)
417 if (_gtk_css_parser_try (parser, font_weight_values[i].name, TRUE))
418 return _gtk_css_value_ref (&font_weight_values[i]);
420 /* special cases go here */
421 if (_gtk_css_parser_try (parser, "400", TRUE))
422 return _gtk_css_value_ref (&font_weight_values[3]);
423 if (_gtk_css_parser_try (parser, "700", TRUE))
424 return _gtk_css_value_ref (&font_weight_values[6]);
430 _gtk_css_font_weight_value_get (const GtkCssValue *value)
432 g_return_val_if_fail (value->class == >K_CSS_VALUE_FONT_WEIGHT, PANGO_WEIGHT_NORMAL);
439 static const GtkCssValueClass GTK_CSS_VALUE_AREA = {
440 gtk_css_value_enum_free,
441 gtk_css_value_enum_compute,
442 gtk_css_value_enum_equal,
443 gtk_css_value_enum_transition,
444 gtk_css_value_enum_print
447 static GtkCssValue area_values[] = {
448 { >K_CSS_VALUE_AREA, 1, GTK_CSS_AREA_BORDER_BOX, "border-box" },
449 { >K_CSS_VALUE_AREA, 1, GTK_CSS_AREA_PADDING_BOX, "padding-box" },
450 { >K_CSS_VALUE_AREA, 1, GTK_CSS_AREA_CONTENT_BOX, "content-box" }
454 _gtk_css_area_value_new (GtkCssArea area)
458 for (i = 0; i < G_N_ELEMENTS (area_values); i++)
460 if (area_values[i].value == area)
461 return _gtk_css_value_ref (&area_values[i]);
464 g_return_val_if_reached (NULL);
468 _gtk_css_area_value_try_parse (GtkCssParser *parser)
472 g_return_val_if_fail (parser != NULL, NULL);
474 for (i = 0; i < G_N_ELEMENTS (area_values); i++)
476 if (_gtk_css_parser_try (parser, area_values[i].name, TRUE))
477 return _gtk_css_value_ref (&area_values[i]);
484 _gtk_css_area_value_get (const GtkCssValue *value)
486 g_return_val_if_fail (value->class == >K_CSS_VALUE_AREA, GTK_CSS_AREA_BORDER_BOX);
491 /* GtkCssDirection */
493 static const GtkCssValueClass GTK_CSS_VALUE_DIRECTION = {
494 gtk_css_value_enum_free,
495 gtk_css_value_enum_compute,
496 gtk_css_value_enum_equal,
497 gtk_css_value_enum_transition,
498 gtk_css_value_enum_print
501 static GtkCssValue direction_values[] = {
502 { >K_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_NORMAL, "normal" },
503 { >K_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_REVERSE, "reverse" },
504 { >K_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_ALTERNATE, "alternate" },
505 { >K_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_ALTERNATE_REVERSE, "alternate-reverse" }
509 _gtk_css_direction_value_new (GtkCssDirection direction)
513 for (i = 0; i < G_N_ELEMENTS (direction_values); i++)
515 if (direction_values[i].value == direction)
516 return _gtk_css_value_ref (&direction_values[i]);
519 g_return_val_if_reached (NULL);
523 _gtk_css_direction_value_try_parse (GtkCssParser *parser)
527 g_return_val_if_fail (parser != NULL, NULL);
529 for (i = 0; i < G_N_ELEMENTS (direction_values); i++)
531 if (_gtk_css_parser_try (parser, direction_values[i].name, TRUE))
532 return _gtk_css_value_ref (&direction_values[i]);
539 _gtk_css_direction_value_get (const GtkCssValue *value)
541 g_return_val_if_fail (value->class == >K_CSS_VALUE_DIRECTION, GTK_CSS_DIRECTION_NORMAL);
546 /* GtkCssPlayState */
548 static const GtkCssValueClass GTK_CSS_VALUE_PLAY_STATE = {
549 gtk_css_value_enum_free,
550 gtk_css_value_enum_compute,
551 gtk_css_value_enum_equal,
552 gtk_css_value_enum_transition,
553 gtk_css_value_enum_print
556 static GtkCssValue play_state_values[] = {
557 { >K_CSS_VALUE_PLAY_STATE, 1, GTK_CSS_PLAY_STATE_RUNNING, "running" },
558 { >K_CSS_VALUE_PLAY_STATE, 1, GTK_CSS_PLAY_STATE_PAUSED, "paused" }
562 _gtk_css_play_state_value_new (GtkCssPlayState play_state)
566 for (i = 0; i < G_N_ELEMENTS (play_state_values); i++)
568 if (play_state_values[i].value == play_state)
569 return _gtk_css_value_ref (&play_state_values[i]);
572 g_return_val_if_reached (NULL);
576 _gtk_css_play_state_value_try_parse (GtkCssParser *parser)
580 g_return_val_if_fail (parser != NULL, NULL);
582 for (i = 0; i < G_N_ELEMENTS (play_state_values); i++)
584 if (_gtk_css_parser_try (parser, play_state_values[i].name, TRUE))
585 return _gtk_css_value_ref (&play_state_values[i]);
592 _gtk_css_play_state_value_get (const GtkCssValue *value)
594 g_return_val_if_fail (value->class == >K_CSS_VALUE_PLAY_STATE, GTK_CSS_PLAY_STATE_RUNNING);
601 static const GtkCssValueClass GTK_CSS_VALUE_FILL_MODE = {
602 gtk_css_value_enum_free,
603 gtk_css_value_enum_compute,
604 gtk_css_value_enum_equal,
605 gtk_css_value_enum_transition,
606 gtk_css_value_enum_print
609 static GtkCssValue fill_mode_values[] = {
610 { >K_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_NONE, "none" },
611 { >K_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_FORWARDS, "forwards" },
612 { >K_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_BACKWARDS, "backwards" },
613 { >K_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_BOTH, "both" }
617 _gtk_css_fill_mode_value_new (GtkCssFillMode fill_mode)
621 for (i = 0; i < G_N_ELEMENTS (fill_mode_values); i++)
623 if (fill_mode_values[i].value == fill_mode)
624 return _gtk_css_value_ref (&fill_mode_values[i]);
627 g_return_val_if_reached (NULL);
631 _gtk_css_fill_mode_value_try_parse (GtkCssParser *parser)
635 g_return_val_if_fail (parser != NULL, NULL);
637 for (i = 0; i < G_N_ELEMENTS (fill_mode_values); i++)
639 if (_gtk_css_parser_try (parser, fill_mode_values[i].name, TRUE))
640 return _gtk_css_value_ref (&fill_mode_values[i]);
647 _gtk_css_fill_mode_value_get (const GtkCssValue *value)
649 g_return_val_if_fail (value->class == >K_CSS_VALUE_FILL_MODE, GTK_CSS_FILL_NONE);