]> Pileus Git - ~andy/gtk/blob - gtk/gtkcssshadowsvalue.c
notebook: restore previous behaviour wrt. unparenting of tab labels
[~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 gboolean
51 gtk_css_value_shadows_equal (const GtkCssValue *value1,
52                              const GtkCssValue *value2)
53 {
54   guint i;
55
56   /* XXX: Should we fill up here? */
57   if (value1->len != value2->len)
58     return FALSE;
59
60   for (i = 0; i < value1->len; i++)
61     {
62       if (!_gtk_css_value_equal (value1->values[i],
63                                  value2->values[i]))
64         return FALSE;
65     }
66
67   return TRUE;
68 }
69
70 static GtkCssValue *
71 gtk_css_value_shadows_transition (GtkCssValue *start,
72                                   GtkCssValue *end,
73                                   double       progress)
74 {
75   GtkCssValue *result;
76   guint i;
77
78   /* catches the important case of 2 none values */
79   if (start == end)
80     return _gtk_css_value_ref (start);
81
82   if (start->len > end->len)
83     result = gtk_css_shadows_value_new (start->values, start->len);
84   else
85     result = gtk_css_shadows_value_new (end->values, end->len);
86
87   for (i = 0; i < MIN (start->len, end->len); i++)
88     {
89       result->values[i] = _gtk_css_value_transition (start->values[i], end->values[i], progress);
90     }
91   if (start->len > end->len)
92     {
93       for (; i < result->len; i++)
94         {
95           GtkCssValue *fill = _gtk_css_shadow_value_new_for_transition (start->values[i]);
96           result->values[i] = _gtk_css_value_transition (start->values[i], fill, progress);
97           _gtk_css_value_unref (fill);
98         }
99     }
100   else
101     {
102       for (; i < result->len; i++)
103         {
104           GtkCssValue *fill = _gtk_css_shadow_value_new_for_transition (end->values[i]);
105           result->values[i] = _gtk_css_value_transition (fill, end->values[i], progress);
106           _gtk_css_value_unref (fill);
107         }
108     }
109
110   return result;
111 }
112
113 static void
114 gtk_css_value_shadows_print (const GtkCssValue *value,
115                              GString           *string)
116 {
117   guint i;
118
119   if (value->len == 0)
120     {
121       g_string_append (string, "none");
122       return;
123     }
124
125   for (i = 0; i < value->len; i++)
126     {
127       if (i > 0)
128         g_string_append (string, ", ");
129       _gtk_css_value_print (value->values[i], string);
130     }
131 }
132
133 static const GtkCssValueClass GTK_CSS_VALUE_SHADOWS = {
134   gtk_css_value_shadows_free,
135   gtk_css_value_shadows_equal,
136   gtk_css_value_shadows_transition,
137   gtk_css_value_shadows_print
138 };
139
140 static GtkCssValue none_singleton = { &GTK_CSS_VALUE_SHADOWS, 1, 0, { NULL } };
141
142 GtkCssValue *
143 _gtk_css_shadows_value_new_none (void)
144 {
145   return _gtk_css_value_ref (&none_singleton);
146 }
147
148 static GtkCssValue *
149 gtk_css_shadows_value_new (GtkCssValue **values,
150                            guint         len)
151 {
152   GtkCssValue *result;
153            
154   g_return_val_if_fail (values != NULL, NULL);
155   g_return_val_if_fail (len > 0, NULL);
156          
157   result = _gtk_css_value_alloc (&GTK_CSS_VALUE_SHADOWS, sizeof (GtkCssValue) + sizeof (GtkCssValue *) * (len - 1));
158   result->len = len;
159   memcpy (&result->values[0], values, sizeof (GtkCssValue *) * len);
160             
161   return result;
162 }
163
164 GtkCssValue *
165 _gtk_css_shadows_value_parse (GtkCssParser *parser)
166 {
167   GtkCssValue *value, *result;
168   GPtrArray *values;
169
170   if (_gtk_css_parser_try (parser, "none", TRUE))
171     return _gtk_css_shadows_value_new_none ();
172
173   values = g_ptr_array_new ();
174
175   do {
176     value = _gtk_css_shadow_value_parse (parser);
177
178     if (value == NULL)
179       {
180         g_ptr_array_set_free_func (values, (GDestroyNotify) _gtk_css_value_unref);
181         g_ptr_array_free (values, TRUE);
182         return NULL;
183       }
184
185     g_ptr_array_add (values, value);
186   } while (_gtk_css_parser_try (parser, ",", TRUE));
187
188   result = gtk_css_shadows_value_new ((GtkCssValue **) values->pdata, values->len);
189   g_ptr_array_free (values, TRUE);
190   return result;
191 }
192
193 GtkCssValue *
194 _gtk_css_shadows_value_compute (GtkCssValue     *value,
195                                 GtkStyleContext *context)
196 {
197   GtkCssValue *result;
198   guint i;
199
200   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_SHADOWS, NULL);
201
202   if (value->len == 0)
203     return _gtk_css_value_ref (value);
204
205   result = gtk_css_shadows_value_new (value->values, value->len);
206   for (i = 0; i < value->len; i++)
207     {
208       result->values[i] = _gtk_css_shadow_value_compute (value->values[i], context);
209     }
210
211   return result;
212 }
213
214 void
215 _gtk_css_shadows_value_paint_layout (const GtkCssValue *shadows,
216                                      cairo_t           *cr,
217                                      PangoLayout       *layout)
218 {
219   guint i;
220
221   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
222
223   for (i = 0; i < shadows->len; i++)
224     {
225       _gtk_css_shadow_value_paint_layout (shadows->values[i], cr, layout);
226     }
227 }
228
229 void
230 _gtk_css_shadows_value_paint_icon (const GtkCssValue *shadows,
231                                    cairo_t           *cr)
232 {
233   guint i;
234
235   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
236
237   for (i = 0; i < shadows->len; i++)
238     {
239       _gtk_css_shadow_value_paint_icon (shadows->values[i], cr);
240     }
241 }
242
243 void
244 _gtk_css_shadows_value_paint_spinner (const GtkCssValue *shadows,
245                                       cairo_t           *cr,
246                                       gdouble            radius,
247                                       gdouble            progress)
248 {
249   guint i;
250
251   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
252
253   for (i = 0; i < shadows->len; i++)
254     {
255       _gtk_css_shadow_value_paint_spinner (shadows->values[i], cr, radius, progress);
256     }
257 }
258
259 void
260 _gtk_css_shadows_value_paint_box (const GtkCssValue   *shadows,
261                                   cairo_t             *cr,
262                                   const GtkRoundedBox *padding_box)
263 {
264   guint i;
265
266   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
267
268   for (i = 0; i < shadows->len; i++)
269     {
270       _gtk_css_shadow_value_paint_box (shadows->values[i], cr, padding_box);
271     }
272 }