]> Pileus Git - ~andy/gtk/blob - gtk/gtkcssvalue.c
css: Add GtkCssValue, an immutable refcounted css value
[~andy/gtk] / gtk / gtkcssvalue.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 "gtkcssvalueprivate.h"
21 #include "gtktypebuiltins.h"
22 #include "gtkgradient.h"
23 #include <cairo-gobject.h>
24 #include "gtkprivatetypebuiltins.h"
25
26 struct _GtkCssValue
27 {
28   volatile gint ref_count;
29   GValue g_value;
30 };
31
32 G_DEFINE_BOXED_TYPE (GtkCssValue, _gtk_css_value, _gtk_css_value_ref, _gtk_css_value_unref)
33
34 static GtkCssValue *
35 _gtk_css_value_new (void)
36 {
37   GtkCssValue *value;
38
39   value = g_slice_new0 (GtkCssValue);
40
41   value->ref_count = 1;
42
43   return value;
44 }
45
46 GtkCssValue *
47 _gtk_css_value_new_from_gvalue (const GValue *g_value)
48 {
49   GtkCssValue *value;
50
51   g_return_val_if_fail (g_value != NULL, NULL);
52
53   value = _gtk_css_value_new ();
54
55   g_value_init (&value->g_value, G_VALUE_TYPE (g_value));
56   g_value_copy (g_value, &value->g_value);
57
58   return value;
59 }
60
61 GtkCssValue *
62 _gtk_css_value_new_take_gvalue (GValue *g_value)
63 {
64   GtkCssValue *value;
65
66   g_return_val_if_fail (g_value != NULL, NULL);
67
68   value = _gtk_css_value_new ();
69   value->g_value = *g_value;
70
71   return value;
72 }
73
74 GtkCssValue *
75 _gtk_css_value_new_from_int (gint val)
76 {
77   GtkCssValue *value;
78
79   value = _gtk_css_value_new ();
80   g_value_init (&value->g_value, G_TYPE_INT);
81   g_value_set_int (&value->g_value, val);
82
83   return value;
84 }
85
86 GtkCssValue *
87 _gtk_css_value_new_take_string (char *string)
88 {
89   GtkCssValue *value;
90
91   value = _gtk_css_value_new ();
92   g_value_init (&value->g_value, G_TYPE_STRING);
93   g_value_take_string (&value->g_value, string);
94
95   return value;
96 }
97
98 GtkCssValue *
99 _gtk_css_value_new_from_string (const char *string)
100 {
101   GtkCssValue *value;
102
103   value = _gtk_css_value_new ();
104   g_value_init (&value->g_value, G_TYPE_STRING);
105   g_value_set_string (&value->g_value, string);
106
107   return value;
108 }
109
110 GtkCssValue *
111 _gtk_css_value_new_from_border (const GtkBorder *border)
112 {
113   GtkCssValue *value;
114
115   value = _gtk_css_value_new ();
116   g_value_init (&value->g_value, GTK_TYPE_BORDER);
117   g_value_set_boxed (&value->g_value, border);
118
119   return value;
120 }
121
122 GtkCssValue *
123 _gtk_css_value_new_take_pattern (cairo_pattern_t *v)
124 {
125   GtkCssValue *value;
126
127   value = _gtk_css_value_new ();
128   g_value_init (&value->g_value, CAIRO_GOBJECT_TYPE_PATTERN);
129   g_value_take_boxed (&value->g_value, v);
130
131   return value;
132 }
133
134 GtkCssValue *
135 _gtk_css_value_new_from_pattern (const cairo_pattern_t *v)
136 {
137   GtkCssValue *value;
138
139   value = _gtk_css_value_new ();
140   g_value_init (&value->g_value, CAIRO_GOBJECT_TYPE_PATTERN);
141   g_value_set_boxed (&value->g_value, v);
142
143   return value;
144 }
145
146 GtkCssValue *
147 _gtk_css_value_new_take_shadow (GtkShadow *v)
148 {
149   GtkCssValue *value;
150
151   value = _gtk_css_value_new ();
152   g_value_init (&value->g_value, GTK_TYPE_SHADOW);
153   g_value_take_boxed (&value->g_value, v);
154
155   return value;
156 }
157
158 GtkCssValue *
159 _gtk_css_value_new_take_font_description (PangoFontDescription *v)
160 {
161   GtkCssValue *value;
162
163   value = _gtk_css_value_new ();
164   g_value_init (&value->g_value, PANGO_TYPE_FONT_DESCRIPTION);
165   g_value_take_boxed (&value->g_value, v);
166
167   return value;
168 }
169
170 GtkCssValue *
171 _gtk_css_value_new_take_image (GtkCssImage *v)
172 {
173   GtkCssValue *value;
174
175   value = _gtk_css_value_new ();
176   g_value_init (&value->g_value, GTK_TYPE_CSS_IMAGE);
177   g_value_take_object (&value->g_value, v);
178
179   return value;
180 }
181
182 GtkCssValue *
183 _gtk_css_value_new_from_number (const GtkCssNumber *v)
184 {
185   GtkCssValue *value;
186
187   value = _gtk_css_value_new ();
188   g_value_init (&value->g_value, GTK_TYPE_CSS_NUMBER);
189   g_value_set_boxed (&value->g_value, v);
190
191   return value;
192 }
193
194 GtkCssValue *
195 _gtk_css_value_new_from_rgba (const GdkRGBA *v)
196 {
197   GtkCssValue *value;
198
199   value = _gtk_css_value_new ();
200   g_value_init (&value->g_value, GDK_TYPE_RGBA);
201   g_value_set_boxed (&value->g_value, v);
202
203   return value;
204 }
205
206 GtkCssValue *
207 _gtk_css_value_new_from_color (const GdkColor *v)
208 {
209   GtkCssValue *value;
210
211   value = _gtk_css_value_new ();
212   g_value_init (&value->g_value, GDK_TYPE_COLOR);
213   g_value_set_boxed (&value->g_value, v);
214
215   return value;
216 }
217
218 GtkCssValue *
219 _gtk_css_value_new_from_background_size (const GtkCssBackgroundSize *v)
220 {
221   GtkCssValue *value;
222
223   value = _gtk_css_value_new ();
224   g_value_init (&value->g_value, GTK_TYPE_CSS_BACKGROUND_SIZE);
225   g_value_set_boxed (&value->g_value, v);
226
227   return value;
228 }
229
230 GtkCssValue *
231 _gtk_css_value_new_take_symbolic_color (GtkSymbolicColor *v)
232 {
233   GtkCssValue *value;
234
235   value = _gtk_css_value_new ();
236   g_value_init (&value->g_value, GTK_TYPE_SYMBOLIC_COLOR);
237   g_value_take_boxed (&value->g_value, v);
238
239   return value;
240 }
241
242 GtkCssValue *
243 _gtk_css_value_ref (GtkCssValue *value)
244 {
245   g_return_val_if_fail (value != NULL, NULL);
246
247   g_atomic_int_add (&value->ref_count, 1);
248
249   return value;
250 }
251
252 void
253 _gtk_css_value_unref (GtkCssValue *value)
254 {
255   if (value == NULL)
256     return;
257
258   if (!g_atomic_int_dec_and_test (&value->ref_count))
259     return;
260
261   g_value_unset (&value->g_value);
262   g_slice_free (GtkCssValue, value);
263 }
264
265 GType
266 _gtk_css_value_get_content_type (GtkCssValue *value)
267 {
268   return G_VALUE_TYPE (&value->g_value);
269 }
270
271 gboolean
272 _gtk_css_value_holds (GtkCssValue *value, GType type)
273 {
274   return G_VALUE_HOLDS (&value->g_value, type);
275 }
276
277 void
278 _gtk_css_value_init_gvalue (GtkCssValue *value,
279                             GValue      *g_value)
280 {
281   if (value != NULL)
282     {
283       g_value_init (g_value, G_VALUE_TYPE (&value->g_value));
284       g_value_copy (&value->g_value, g_value);
285     }
286 }
287
288 void
289 _gtk_css_value_to_gvalue (GtkCssValue *value,
290                           GValue      *g_value)
291 {
292   if (G_VALUE_TYPE (&value->g_value) == G_VALUE_TYPE (g_value))
293     g_value_copy (&value->g_value, g_value);
294   else if (g_value_type_transformable (G_VALUE_TYPE (&value->g_value), G_VALUE_TYPE (g_value)))
295     g_value_transform (&value->g_value, g_value);
296   else
297     g_warning ("can't convert css value of type `%s' as value of type `%s'",
298                G_VALUE_TYPE_NAME (&value->g_value),
299                G_VALUE_TYPE_NAME (g_value));
300 }
301
302 gboolean
303 _gtk_css_value_is_special  (GtkCssValue *value)
304 {
305   return _gtk_css_value_holds (value, GTK_TYPE_CSS_SPECIAL_VALUE);
306 }
307
308 GtkCssSpecialValue
309 _gtk_css_value_get_special_kind  (GtkCssValue *value)
310 {
311   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_SPECIAL_VALUE), 0);
312   return g_value_get_enum (&value->g_value);
313 }
314
315 GtkCssNumber *
316 _gtk_css_value_get_number  (GtkCssValue *value)
317 {
318   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_NUMBER), NULL);
319   return g_value_get_boxed (&value->g_value);
320 }
321
322 GtkSymbolicColor *
323 _gtk_css_value_get_symbolic_color  (GtkCssValue *value)
324 {
325   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_SYMBOLIC_COLOR), NULL);
326   return g_value_get_boxed (&value->g_value);
327 }
328
329 int
330 _gtk_css_value_get_int (GtkCssValue *value)
331 {
332   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_INT), 0);
333   return g_value_get_int (&value->g_value);
334 }
335
336 double
337 _gtk_css_value_get_double (GtkCssValue *value)
338 {
339   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_DOUBLE), 0);
340   return g_value_get_double (&value->g_value);
341 }
342
343 const char *
344 _gtk_css_value_get_string (GtkCssValue *value)
345 {
346   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_STRING), 0);
347   return g_value_get_string (&value->g_value);
348 }
349
350 gpointer
351 _gtk_css_value_dup_object (GtkCssValue *value)
352 {
353   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_OBJECT), NULL);
354   return g_value_dup_object (&value->g_value);
355 }
356
357 gpointer
358 _gtk_css_value_get_object (GtkCssValue *value)
359 {
360   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_OBJECT), NULL);
361   return g_value_get_object (&value->g_value);
362 }
363
364 gpointer
365 _gtk_css_value_get_boxed (GtkCssValue *value)
366 {
367   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_BOXED), NULL);
368   return g_value_get_boxed (&value->g_value);
369 }
370
371 const char **
372 _gtk_css_value_get_strv (GtkCssValue *value)
373 {
374   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_STRV), NULL);
375   return g_value_get_boxed (&value->g_value);
376 }
377
378 GtkCssImage *
379 _gtk_css_value_get_image (GtkCssValue *value)
380 {
381   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_IMAGE), NULL);
382   return g_value_get_object (&value->g_value);
383 }
384
385 GtkBorderStyle
386 _gtk_css_value_get_border_style (GtkCssValue *value)
387 {
388   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_BORDER_STYLE), 0);
389   return g_value_get_enum (&value->g_value);
390 }
391
392 GtkCssBackgroundSize *
393 _gtk_css_value_get_background_size (GtkCssValue *value)
394 {
395   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BACKGROUND_SIZE), NULL);
396   return g_value_get_boxed (&value->g_value);
397 }
398
399 GtkCssBorderImageRepeat *
400 _gtk_css_value_get_border_image_repeat (GtkCssValue *value)
401 {
402   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT), NULL);
403   return g_value_get_boxed (&value->g_value);
404 }
405
406 GtkCssBorderCornerRadius *
407 _gtk_css_value_get_border_corner_radius (GtkCssValue *value)
408 {
409   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS), NULL);
410   return g_value_get_boxed (&value->g_value);
411 }
412
413 PangoFontDescription *
414 _gtk_css_value_get_font_description (GtkCssValue *value)
415 {
416   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_FONT_DESCRIPTION), 0);
417   return g_value_get_boxed (&value->g_value);
418 }
419
420 PangoStyle
421 _gtk_css_value_get_pango_style (GtkCssValue *value)
422 {
423   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_STYLE), 0);
424   return g_value_get_enum (&value->g_value);
425 }
426
427 PangoVariant
428 _gtk_css_value_get_pango_variant (GtkCssValue *value)
429 {
430   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_VARIANT), 0);
431   return g_value_get_enum (&value->g_value);
432 }
433
434 PangoWeight
435 _gtk_css_value_get_pango_weight (GtkCssValue *value)
436 {
437   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_WEIGHT), 0);
438   return g_value_get_enum (&value->g_value);
439 }
440
441 GdkRGBA *
442 _gtk_css_value_get_rgba (GtkCssValue *value)
443 {
444   g_return_val_if_fail (_gtk_css_value_holds (value, GDK_TYPE_RGBA), NULL);
445   return g_value_get_boxed (&value->g_value);
446 }
447
448 cairo_pattern_t *
449 _gtk_css_value_get_pattern (GtkCssValue *value)
450 {
451   g_return_val_if_fail (_gtk_css_value_holds (value, CAIRO_GOBJECT_TYPE_PATTERN), NULL);
452   return g_value_get_boxed (&value->g_value);
453 }
454
455 GtkGradient *
456 _gtk_css_value_get_gradient (GtkCssValue *value)
457 {
458   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_GRADIENT), NULL);
459   return g_value_get_boxed (&value->g_value);
460 }
461
462 GtkShadow *
463 _gtk_css_value_get_shadow (GtkCssValue *value)
464 {
465   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_SHADOW), NULL);
466   return g_value_get_boxed (&value->g_value);
467 }