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, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
24 #include "gtkshadowprivate.h"
25 #include "gtkstylecontext.h"
26 #include "gtkthemingengineprivate.h"
27 #include "gtkthemingengine.h"
29 #include "gtkthemingengineprivate.h"
31 typedef struct _GtkShadowElement GtkShadowElement;
33 struct _GtkShadowElement {
42 GtkSymbolicColor *symbolic_color;
46 shadow_element_print (GtkShadowElement *element,
52 g_string_append (str, "inset ");
54 g_string_append_printf (str, "%d %d ",
55 (gint) element->hoffset,
56 (gint) element->voffset);
58 if (element->radius != 0)
59 g_string_append_printf (str, "%d ", (gint) element->radius);
61 if (element->spread != 0)
62 g_string_append_printf (str, "%d ", (gint) element->spread);
64 if (element->symbolic_color != NULL)
65 color_str = gtk_symbolic_color_to_string (element->symbolic_color);
67 color_str = gdk_rgba_to_string (&element->color);
69 g_string_append (str, color_str);
74 shadow_element_free (GtkShadowElement *element)
76 if (element->symbolic_color != NULL)
77 gtk_symbolic_color_unref (element->symbolic_color);
79 g_slice_free (GtkShadowElement, element);
82 static GtkShadowElement *
83 shadow_element_new (gdouble hoffset,
89 GtkSymbolicColor *symbolic_color)
91 GtkShadowElement *retval;
93 retval = g_slice_new0 (GtkShadowElement);
95 retval->hoffset = hoffset;
96 retval->voffset = voffset;
97 retval->radius = radius;
98 retval->spread = spread;
99 retval->inset = inset;
101 if (symbolic_color != NULL)
102 retval->symbolic_color = gtk_symbolic_color_ref (symbolic_color);
105 retval->color = *color;
114 G_DEFINE_BOXED_TYPE (GtkShadow, _gtk_shadow,
115 _gtk_shadow_ref, _gtk_shadow_unref)
125 _gtk_shadow_new (void)
129 retval = g_slice_new0 (GtkShadow);
130 retval->ref_count = 1;
131 retval->resolved = FALSE;
137 _gtk_shadow_ref (GtkShadow *shadow)
139 g_return_val_if_fail (shadow != NULL, NULL);
147 _gtk_shadow_get_resolved (GtkShadow *shadow)
149 return shadow->resolved;
153 _gtk_shadow_unref (GtkShadow *shadow)
155 g_return_if_fail (shadow != NULL);
159 if (shadow->ref_count == 0)
161 g_list_free_full (shadow->elements,
162 (GDestroyNotify) shadow_element_free);
163 g_slice_free (GtkShadow, shadow);
168 _gtk_shadow_append (GtkShadow *shadow,
174 GtkSymbolicColor *color)
176 GtkShadowElement *element;
178 g_return_if_fail (shadow != NULL);
179 g_return_if_fail (color != NULL);
181 element = shadow_element_new (hoffset, voffset,
182 radius, spread, inset,
185 shadow->elements = g_list_append (shadow->elements, element);
189 _gtk_shadow_resolve (GtkShadow *shadow,
190 GtkStyleProperties *props)
192 GtkShadow *resolved_shadow;
193 GtkShadowElement *element, *resolved_element;
197 if (shadow->resolved)
198 return _gtk_shadow_ref (shadow);
200 resolved_shadow = _gtk_shadow_new ();
202 for (l = shadow->elements; l != NULL; l = l->next)
206 if (!gtk_symbolic_color_resolve (element->symbolic_color,
210 _gtk_shadow_unref (resolved_shadow);
215 shadow_element_new (element->hoffset, element->voffset,
216 element->radius, element->spread, element->inset,
219 resolved_shadow->elements =
220 g_list_append (resolved_shadow->elements, resolved_element);
223 resolved_shadow->resolved = TRUE;
225 return resolved_shadow;
229 _gtk_shadow_print (GtkShadow *shadow,
235 length = g_list_length (shadow->elements);
240 shadow_element_print (shadow->elements->data, str);
245 for (l = g_list_next (shadow->elements); l != NULL; l = l->next)
247 g_string_append (str, ", ");
248 shadow_element_print (l->data, str);
253 _gtk_text_shadow_paint_layout (GtkShadow *shadow,
258 GtkShadowElement *element;
260 if (!cairo_has_current_point (cr))
261 cairo_move_to (cr, 0, 0);
263 /* render shadows starting from the last one,
264 * and the others on top.
266 for (l = g_list_last (shadow->elements); l != NULL; l = l->prev)
272 cairo_rel_move_to (cr, element->hoffset, element->voffset);
273 gdk_cairo_set_source_rgba (cr, &element->color);
274 _gtk_pango_fill_layout (cr, layout);
276 cairo_rel_move_to (cr, -element->hoffset, -element->voffset);
282 _gtk_icon_shadow_paint (GtkShadow *shadow,
286 GtkShadowElement *element;
287 cairo_pattern_t *pattern;
289 for (l = g_list_last (shadow->elements); l != NULL; l = l->prev)
294 pattern = cairo_pattern_reference (cairo_get_source (cr));
295 gdk_cairo_set_source_rgba (cr, &element->color);
297 cairo_translate (cr, element->hoffset, element->voffset);
298 cairo_mask (cr, pattern);
301 cairo_pattern_destroy (pattern);
306 _gtk_icon_shadow_paint_spinner (GtkShadow *shadow,
311 GtkShadowElement *element;
314 for (l = g_list_last (shadow->elements); l != NULL; l = l->prev)
320 cairo_translate (cr, element->hoffset, element->voffset);
321 _gtk_theming_engine_paint_spinner (cr,
330 _gtk_box_shadow_render (GtkShadow *shadow,
332 const GtkRoundedBox *padding_box)
334 GtkShadowElement *element;
339 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
341 _gtk_rounded_box_path (padding_box, cr);
344 /* render shadows starting from the last one,
345 * and the others on top.
347 for (l = g_list_last (shadow->elements); l != NULL; l = l->prev)
355 _gtk_rounded_box_move (&box, element->hoffset, element->voffset);
356 _gtk_rounded_box_shrink (&box,
357 element->spread, element->spread,
358 element->spread, element->spread);
360 _gtk_rounded_box_path (&box, cr);
361 _gtk_rounded_box_clip_path (padding_box, cr);
363 gdk_cairo_set_source_rgba (cr, &element->color);