]> Pileus Git - ~andy/gtk/blob - gtk/gtkcssenumvalue.c
Deal with non-multiple-of-100 font weights
[~andy/gtk] / gtk / gtkcssenumvalue.c
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 "gtkstylepropertyprivate.h"
23
24 /* repeated API */
25
26 struct _GtkCssValue {
27   GTK_CSS_VALUE_BASE
28   int value;
29   const char *name;
30 };
31
32 static void
33 gtk_css_value_enum_free (GtkCssValue *value)
34 {
35   g_slice_free (GtkCssValue, value);
36 }
37
38 static gboolean
39 gtk_css_value_enum_equal (const GtkCssValue *enum1,
40                           const GtkCssValue *enum2)
41 {
42   return enum1 == enum2;
43 }
44
45 static GtkCssValue *
46 gtk_css_value_enum_transition (GtkCssValue *start,
47                                GtkCssValue *end,
48                                double       progress)
49 {
50   return NULL;
51 }
52
53 static void
54 gtk_css_value_enum_print (const GtkCssValue *value,
55                           GString           *string)
56 {
57   g_string_append (string, value->name);
58 }
59
60 /* GtkBorderStyle */
61
62 static const GtkCssValueClass GTK_CSS_VALUE_BORDER_STYLE = {
63   gtk_css_value_enum_free,
64   gtk_css_value_enum_equal,
65   gtk_css_value_enum_transition,
66   gtk_css_value_enum_print
67 };
68
69 static GtkCssValue border_style_values[] = {
70   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_NONE, "none" },
71   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_SOLID, "solid" },
72   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_INSET, "inset" },
73   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_OUTSET, "outset" },
74   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_HIDDEN, "hidden" },
75   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DOTTED, "dotted" },
76   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DASHED, "dashed" },
77   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DOUBLE, "double" },
78   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_GROOVE, "groove" },
79   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_RIDGE, "ridge" }
80 };
81
82 GtkCssValue *
83 _gtk_css_border_style_value_new (GtkBorderStyle border_style)
84 {
85   g_return_val_if_fail (border_style < G_N_ELEMENTS (border_style_values), NULL);
86
87   return _gtk_css_value_ref (&border_style_values[border_style]);
88 }
89
90 GtkCssValue *
91 _gtk_css_border_style_value_try_parse (GtkCssParser *parser)
92 {
93   guint i;
94
95   g_return_val_if_fail (parser != NULL, NULL);
96
97   for (i = 0; i < G_N_ELEMENTS (border_style_values); i++)
98     {
99       if (_gtk_css_parser_try (parser, border_style_values[i].name, TRUE))
100         return _gtk_css_value_ref (&border_style_values[i]);
101     }
102
103   return NULL;
104 }
105
106 GtkBorderStyle
107 _gtk_css_border_style_value_get (const GtkCssValue *value)
108 {
109   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_BORDER_STYLE, GTK_BORDER_STYLE_NONE);
110
111   return value->value;
112 }
113
114 /* PangoStyle */
115
116 static const GtkCssValueClass GTK_CSS_VALUE_FONT_STYLE = {
117   gtk_css_value_enum_free,
118   gtk_css_value_enum_equal,
119   gtk_css_value_enum_transition,
120   gtk_css_value_enum_print
121 };
122
123 static GtkCssValue font_style_values[] = {
124   { &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_NORMAL, "normal" },
125   { &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_OBLIQUE, "oblique" },
126   { &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_ITALIC, "italic" }
127 };
128
129 GtkCssValue *
130 _gtk_css_font_style_value_new (PangoStyle font_style)
131 {
132   g_return_val_if_fail (font_style < G_N_ELEMENTS (font_style_values), NULL);
133
134   return _gtk_css_value_ref (&font_style_values[font_style]);
135 }
136
137 GtkCssValue *
138 _gtk_css_font_style_value_try_parse (GtkCssParser *parser)
139 {
140   guint i;
141
142   g_return_val_if_fail (parser != NULL, NULL);
143
144   for (i = 0; i < G_N_ELEMENTS (font_style_values); i++)
145     {
146       if (_gtk_css_parser_try (parser, font_style_values[i].name, TRUE))
147         return _gtk_css_value_ref (&font_style_values[i]);
148     }
149
150   return NULL;
151 }
152
153 PangoStyle
154 _gtk_css_font_style_value_get (const GtkCssValue *value)
155 {
156   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_STYLE, PANGO_STYLE_NORMAL);
157
158   return value->value;
159 }
160
161 /* PangoVariant */
162
163 static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT = {
164   gtk_css_value_enum_free,
165   gtk_css_value_enum_equal,
166   gtk_css_value_enum_transition,
167   gtk_css_value_enum_print
168 };
169
170 static GtkCssValue font_variant_values[] = {
171   { &GTK_CSS_VALUE_FONT_VARIANT, 1, PANGO_VARIANT_NORMAL, "normal" },
172   { &GTK_CSS_VALUE_FONT_VARIANT, 1, PANGO_VARIANT_SMALL_CAPS, "small-caps" }
173 };
174
175 GtkCssValue *
176 _gtk_css_font_variant_value_new (PangoVariant font_variant)
177 {
178   g_return_val_if_fail (font_variant < G_N_ELEMENTS (font_variant_values), NULL);
179
180   return _gtk_css_value_ref (&font_variant_values[font_variant]);
181 }
182
183 GtkCssValue *
184 _gtk_css_font_variant_value_try_parse (GtkCssParser *parser)
185 {
186   guint i;
187
188   g_return_val_if_fail (parser != NULL, NULL);
189
190   for (i = 0; i < G_N_ELEMENTS (font_variant_values); i++)
191     {
192       if (_gtk_css_parser_try (parser, font_variant_values[i].name, TRUE))
193         return _gtk_css_value_ref (&font_variant_values[i]);
194     }
195
196   return NULL;
197 }
198
199 PangoVariant
200 _gtk_css_font_variant_value_get (const GtkCssValue *value)
201 {
202   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT, PANGO_VARIANT_NORMAL);
203
204   return value->value;
205 }
206
207 /* PangoWeight */
208
209 static const GtkCssValueClass GTK_CSS_VALUE_FONT_WEIGHT = {
210   gtk_css_value_enum_free,
211   gtk_css_value_enum_equal,
212   gtk_css_value_enum_transition,
213   gtk_css_value_enum_print
214 };
215
216 static GtkCssValue font_weight_values[] = {
217   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_THIN, "100" },
218   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_ULTRALIGHT, "200" },
219   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_LIGHT, "300" },
220   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_NORMAL, "normal" },
221   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_MEDIUM, "500" },
222   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_SEMIBOLD, "600" },
223   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_BOLD, "bold" },
224   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_ULTRABOLD, "800" },
225   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_HEAVY, "900" }
226 };
227
228 GtkCssValue *
229 _gtk_css_font_weight_value_new (PangoWeight font_weight)
230 {
231   guint i;
232   gint w;
233
234   w = ((font_weight + 50) / 100) * 100;
235
236   for (i = 0; i < G_N_ELEMENTS (font_weight_values); i++)
237     {
238       if (font_weight_values[i].value == w)
239         return _gtk_css_value_ref (&font_weight_values[i]);
240     }
241
242   g_return_val_if_reached (NULL);
243 }
244
245 GtkCssValue *
246 _gtk_css_font_weight_value_try_parse (GtkCssParser *parser)
247 {
248   guint i;
249
250   g_return_val_if_fail (parser != NULL, NULL);
251
252   for (i = 0; i < G_N_ELEMENTS (font_weight_values); i++)
253     {
254       if (_gtk_css_parser_try (parser, font_weight_values[i].name, TRUE))
255         return _gtk_css_value_ref (&font_weight_values[i]);
256     }
257   /* special cases go here */
258   if (_gtk_css_parser_try (parser, "400", TRUE))
259     return _gtk_css_value_ref (&font_weight_values[3]);
260   if (_gtk_css_parser_try (parser, "700", TRUE))
261     return _gtk_css_value_ref (&font_weight_values[6]);
262
263   return NULL;
264 }
265
266 PangoWeight
267 _gtk_css_font_weight_value_get (const GtkCssValue *value)
268 {
269   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_WEIGHT, PANGO_WEIGHT_NORMAL);
270
271   return value->value;
272 }
273
274 /* GtkCssArea */
275
276 static const GtkCssValueClass GTK_CSS_VALUE_AREA = {
277   gtk_css_value_enum_free,
278   gtk_css_value_enum_equal,
279   gtk_css_value_enum_transition,
280   gtk_css_value_enum_print
281 };
282
283 static GtkCssValue area_values[] = {
284   { &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_BORDER_BOX, "border-box" },
285   { &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_PADDING_BOX, "padding-box" },
286   { &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_CONTENT_BOX, "content-box" }
287 };
288
289 GtkCssValue *
290 _gtk_css_area_value_new (GtkCssArea area)
291 {
292   guint i;
293
294   for (i = 0; i < G_N_ELEMENTS (area_values); i++)
295     {
296       if (area_values[i].value == area)
297         return _gtk_css_value_ref (&area_values[i]);
298     }
299
300   g_return_val_if_reached (NULL);
301 }
302
303 GtkCssValue *
304 _gtk_css_area_value_try_parse (GtkCssParser *parser)
305 {
306   guint i;
307
308   g_return_val_if_fail (parser != NULL, NULL);
309
310   for (i = 0; i < G_N_ELEMENTS (area_values); i++)
311     {
312       if (_gtk_css_parser_try (parser, area_values[i].name, TRUE))
313         return _gtk_css_value_ref (&area_values[i]);
314     }
315
316   return NULL;
317 }
318
319 GtkCssArea
320 _gtk_css_area_value_get (const GtkCssValue *value)
321 {
322   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_AREA, GTK_CSS_AREA_BORDER_BOX);
323
324   return value->value;
325 }
326