1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2011 Red Hat, Inc.
4 * Author: Cosimo Cecchi <cosimoc@gnome.org>
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.
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.
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/>.
22 #include "gtkshadowprivate.h"
24 #include "gtkstylecontextprivate.h"
25 #include "gtkthemingengineprivate.h"
28 typedef struct _GtkShadowElement GtkShadowElement;
30 struct _GtkShadowElement {
39 GtkSymbolicColor *symbolic_color;
43 shadow_element_print (GtkShadowElement *element,
49 g_string_append (str, "inset ");
51 g_string_append_printf (str, "%d %d ",
52 (gint) element->hoffset,
53 (gint) element->voffset);
55 if (element->radius != 0)
56 g_string_append_printf (str, "%d ", (gint) element->radius);
58 if (element->spread != 0)
59 g_string_append_printf (str, "%d ", (gint) element->spread);
61 if (element->symbolic_color != NULL)
62 color_str = gtk_symbolic_color_to_string (element->symbolic_color);
64 color_str = gdk_rgba_to_string (&element->color);
66 g_string_append (str, color_str);
71 shadow_element_free (GtkShadowElement *element)
73 if (element->symbolic_color != NULL)
74 gtk_symbolic_color_unref (element->symbolic_color);
76 g_slice_free (GtkShadowElement, element);
79 static GtkShadowElement *
80 shadow_element_new (gdouble hoffset,
86 GtkSymbolicColor *symbolic_color)
88 GtkShadowElement *retval;
90 retval = g_slice_new0 (GtkShadowElement);
92 retval->hoffset = hoffset;
93 retval->voffset = voffset;
94 retval->radius = radius;
95 retval->spread = spread;
96 retval->inset = inset;
98 if (symbolic_color != NULL)
99 retval->symbolic_color = gtk_symbolic_color_ref (symbolic_color);
102 retval->color = *color;
111 G_DEFINE_BOXED_TYPE (GtkShadow, _gtk_shadow,
112 _gtk_shadow_ref, _gtk_shadow_unref)
122 _gtk_shadow_new (void)
126 retval = g_slice_new0 (GtkShadow);
127 retval->ref_count = 1;
128 retval->resolved = FALSE;
134 _gtk_shadow_ref (GtkShadow *shadow)
136 g_return_val_if_fail (shadow != NULL, NULL);
144 _gtk_shadow_get_resolved (GtkShadow *shadow)
146 return shadow->resolved;
150 _gtk_shadow_unref (GtkShadow *shadow)
152 g_return_if_fail (shadow != NULL);
156 if (shadow->ref_count == 0)
158 g_list_free_full (shadow->elements,
159 (GDestroyNotify) shadow_element_free);
160 g_slice_free (GtkShadow, shadow);
165 _gtk_shadow_append (GtkShadow *shadow,
171 GtkSymbolicColor *color)
173 GtkShadowElement *element;
175 g_return_if_fail (shadow != NULL);
176 g_return_if_fail (color != NULL);
178 element = shadow_element_new (hoffset, voffset,
179 radius, spread, inset,
182 shadow->elements = g_list_append (shadow->elements, element);
186 _gtk_shadow_resolve (GtkShadow *shadow,
187 GtkStyleContext *context)
189 GtkShadow *resolved_shadow;
190 GtkShadowElement *element, *resolved_element;
194 if (shadow->resolved)
195 return _gtk_shadow_ref (shadow);
197 resolved_shadow = _gtk_shadow_new ();
199 for (l = shadow->elements; l != NULL; l = l->next)
203 if (!_gtk_style_context_resolve_color (context,
204 element->symbolic_color,
207 _gtk_shadow_unref (resolved_shadow);
212 shadow_element_new (element->hoffset, element->voffset,
213 element->radius, element->spread, element->inset,
216 resolved_shadow->elements =
217 g_list_append (resolved_shadow->elements, resolved_element);
220 resolved_shadow->resolved = TRUE;
222 return resolved_shadow;
226 _gtk_shadow_print (GtkShadow *shadow,
232 length = g_list_length (shadow->elements);
237 shadow_element_print (shadow->elements->data, str);
242 for (l = g_list_next (shadow->elements); l != NULL; l = l->next)
244 g_string_append (str, ", ");
245 shadow_element_print (l->data, str);
250 _gtk_text_shadow_paint_layout (GtkShadow *shadow,
255 GtkShadowElement *element;
257 if (!cairo_has_current_point (cr))
258 cairo_move_to (cr, 0, 0);
260 /* render shadows starting from the last one,
261 * and the others on top.
263 for (l = g_list_last (shadow->elements); l != NULL; l = l->prev)
269 cairo_rel_move_to (cr, element->hoffset, element->voffset);
270 gdk_cairo_set_source_rgba (cr, &element->color);
271 _gtk_pango_fill_layout (cr, layout);
273 cairo_rel_move_to (cr, -element->hoffset, -element->voffset);
279 _gtk_icon_shadow_paint (GtkShadow *shadow,
283 GtkShadowElement *element;
284 cairo_pattern_t *pattern;
286 for (l = g_list_last (shadow->elements); l != NULL; l = l->prev)
291 pattern = cairo_pattern_reference (cairo_get_source (cr));
292 gdk_cairo_set_source_rgba (cr, &element->color);
294 cairo_translate (cr, element->hoffset, element->voffset);
295 cairo_mask (cr, pattern);
298 cairo_pattern_destroy (pattern);
303 _gtk_icon_shadow_paint_spinner (GtkShadow *shadow,
308 GtkShadowElement *element;
311 for (l = g_list_last (shadow->elements); l != NULL; l = l->prev)
317 cairo_translate (cr, element->hoffset, element->voffset);
318 _gtk_theming_engine_paint_spinner (cr,
327 _gtk_box_shadow_render (GtkShadow *shadow,
329 const GtkRoundedBox *padding_box)
331 GtkShadowElement *element;
336 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
338 _gtk_rounded_box_path (padding_box, cr);
341 /* render shadows starting from the last one,
342 * and the others on top.
344 for (l = g_list_last (shadow->elements); l != NULL; l = l->prev)
352 _gtk_rounded_box_move (&box, element->hoffset, element->voffset);
353 _gtk_rounded_box_shrink (&box,
354 element->spread, element->spread,
355 element->spread, element->spread);
357 _gtk_rounded_box_path (&box, cr);
358 _gtk_rounded_box_clip_path (padding_box, cr);
360 gdk_cairo_set_source_rgba (cr, &element->color);