]> Pileus Git - ~andy/gtk/blob - gtk/gtkcssshadowsvalue.c
267c41c43991b04a8d6bfea8c8493fcfc10be8a1
[~andy/gtk] / gtk / gtkcssshadowsvalue.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2011 Red Hat, Inc.
3  *
4  * Author: Cosimo Cecchi <cosimoc@gnome.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "config.h"
21
22 #include "gtkcssshadowsvalueprivate.h"
23
24 #include "gtkcssshadowvalueprivate.h"
25
26 #include <string.h>
27
28 struct _GtkCssValue {
29   GTK_CSS_VALUE_BASE
30   guint         len;
31   GtkCssValue  *values[1];
32 };
33
34 static GtkCssValue *    gtk_css_shadows_value_new       (GtkCssValue **values,
35                                                          guint         len);
36
37 static void
38 gtk_css_value_shadows_free (GtkCssValue *value)
39 {
40   guint i;
41
42   for (i = 0; i < value->len; i++)
43     {
44       _gtk_css_value_unref (value->values[i]);
45     }
46
47   g_slice_free1 (sizeof (GtkCssValue) + sizeof (GtkCssValue *) * (value->len - 1), value);
48 }
49
50 static GtkCssValue *
51 gtk_css_value_shadows_compute (GtkCssValue             *value,
52                                guint                    property_id,
53                                GtkStyleProviderPrivate *provider,
54                                GtkCssComputedValues    *values,
55                                GtkCssComputedValues    *parent_values,
56                                GtkCssDependencies      *dependencies)
57 {
58   GtkCssValue *result;
59   GtkCssDependencies child_deps;
60   guint i;
61
62   if (value->len == 0)
63     return _gtk_css_value_ref (value);
64
65   result = gtk_css_shadows_value_new (value->values, value->len);
66   for (i = 0; i < value->len; i++)
67     {
68       result->values[i] = _gtk_css_value_compute (value->values[i], property_id, provider, values, parent_values, &child_deps);
69       *dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
70     }
71
72   return result;
73 }
74
75 static gboolean
76 gtk_css_value_shadows_equal (const GtkCssValue *value1,
77                              const GtkCssValue *value2)
78 {
79   guint i;
80
81   /* XXX: Should we fill up here? */
82   if (value1->len != value2->len)
83     return FALSE;
84
85   for (i = 0; i < value1->len; i++)
86     {
87       if (!_gtk_css_value_equal (value1->values[i],
88                                  value2->values[i]))
89         return FALSE;
90     }
91
92   return TRUE;
93 }
94
95 static GtkCssValue *
96 gtk_css_value_shadows_transition (GtkCssValue *start,
97                                   GtkCssValue *end,
98                                   guint        property_id,
99                                   double       progress)
100 {
101   GtkCssValue *result;
102   guint i;
103
104   /* catches the important case of 2 none values */
105   if (start == end)
106     return _gtk_css_value_ref (start);
107
108   if (start->len > end->len)
109     result = gtk_css_shadows_value_new (start->values, start->len);
110   else
111     result = gtk_css_shadows_value_new (end->values, end->len);
112
113   for (i = 0; i < MIN (start->len, end->len); i++)
114     {
115       result->values[i] = _gtk_css_value_transition (start->values[i], end->values[i], property_id, progress);
116     }
117   if (start->len > end->len)
118     {
119       for (; i < result->len; i++)
120         {
121           GtkCssValue *fill = _gtk_css_shadow_value_new_for_transition (start->values[i]);
122           result->values[i] = _gtk_css_value_transition (start->values[i], fill, property_id, progress);
123           _gtk_css_value_unref (fill);
124         }
125     }
126   else
127     {
128       for (; i < result->len; i++)
129         {
130           GtkCssValue *fill = _gtk_css_shadow_value_new_for_transition (end->values[i]);
131           result->values[i] = _gtk_css_value_transition (fill, end->values[i], property_id, progress);
132           _gtk_css_value_unref (fill);
133         }
134     }
135
136   return result;
137 }
138
139 static void
140 gtk_css_value_shadows_print (const GtkCssValue *value,
141                              GString           *string)
142 {
143   guint i;
144
145   if (value->len == 0)
146     {
147       g_string_append (string, "none");
148       return;
149     }
150
151   for (i = 0; i < value->len; i++)
152     {
153       if (i > 0)
154         g_string_append (string, ", ");
155       _gtk_css_value_print (value->values[i], string);
156     }
157 }
158
159 static const GtkCssValueClass GTK_CSS_VALUE_SHADOWS = {
160   gtk_css_value_shadows_free,
161   gtk_css_value_shadows_compute,
162   gtk_css_value_shadows_equal,
163   gtk_css_value_shadows_transition,
164   gtk_css_value_shadows_print
165 };
166
167 static GtkCssValue none_singleton = { &GTK_CSS_VALUE_SHADOWS, 1, 0, { NULL } };
168
169 GtkCssValue *
170 _gtk_css_shadows_value_new_none (void)
171 {
172   return _gtk_css_value_ref (&none_singleton);
173 }
174
175 static GtkCssValue *
176 gtk_css_shadows_value_new (GtkCssValue **values,
177                            guint         len)
178 {
179   GtkCssValue *result;
180            
181   g_return_val_if_fail (values != NULL, NULL);
182   g_return_val_if_fail (len > 0, NULL);
183          
184   result = _gtk_css_value_alloc (&GTK_CSS_VALUE_SHADOWS, sizeof (GtkCssValue) + sizeof (GtkCssValue *) * (len - 1));
185   result->len = len;
186   memcpy (&result->values[0], values, sizeof (GtkCssValue *) * len);
187             
188   return result;
189 }
190
191 GtkCssValue *
192 _gtk_css_shadows_value_parse (GtkCssParser *parser)
193 {
194   GtkCssValue *value, *result;
195   GPtrArray *values;
196
197   if (_gtk_css_parser_try (parser, "none", TRUE))
198     return _gtk_css_shadows_value_new_none ();
199
200   values = g_ptr_array_new ();
201
202   do {
203     value = _gtk_css_shadow_value_parse (parser);
204
205     if (value == NULL)
206       {
207         g_ptr_array_set_free_func (values, (GDestroyNotify) _gtk_css_value_unref);
208         g_ptr_array_free (values, TRUE);
209         return NULL;
210       }
211
212     g_ptr_array_add (values, value);
213   } while (_gtk_css_parser_try (parser, ",", TRUE));
214
215   result = gtk_css_shadows_value_new ((GtkCssValue **) values->pdata, values->len);
216   g_ptr_array_free (values, TRUE);
217   return result;
218 }
219
220 void
221 _gtk_css_shadows_value_paint_layout (const GtkCssValue *shadows,
222                                      cairo_t           *cr,
223                                      PangoLayout       *layout)
224 {
225   guint i;
226
227   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
228
229   for (i = 0; i < shadows->len; i++)
230     {
231       _gtk_css_shadow_value_paint_layout (shadows->values[i], cr, layout);
232     }
233 }
234
235 void
236 _gtk_css_shadows_value_paint_icon (const GtkCssValue *shadows,
237                                    cairo_t           *cr)
238 {
239   guint i;
240
241   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
242
243   for (i = 0; i < shadows->len; i++)
244     {
245       _gtk_css_shadow_value_paint_icon (shadows->values[i], cr);
246     }
247 }
248
249 void
250 _gtk_css_shadows_value_paint_spinner (const GtkCssValue *shadows,
251                                       cairo_t           *cr,
252                                       gdouble            radius,
253                                       gdouble            progress)
254 {
255   guint i;
256
257   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
258
259   for (i = 0; i < shadows->len; i++)
260     {
261       _gtk_css_shadow_value_paint_spinner (shadows->values[i], cr, radius, progress);
262     }
263 }
264
265 void
266 _gtk_css_shadows_value_paint_box (const GtkCssValue   *shadows,
267                                   cairo_t             *cr,
268                                   const GtkRoundedBox *padding_box)
269 {
270   guint i;
271
272   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
273
274   for (i = 0; i < shadows->len; i++)
275     {
276       _gtk_css_shadow_value_paint_box (shadows->values[i], cr, padding_box);
277     }
278 }