1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2014,2015 Benjamin Otte
3  *
4  * Authors: Benjamin Otte <otte@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 "gtkrendericonprivate.h"
23 
24 #include "gtkcssfiltervalueprivate.h"
25 #include "gtkcssimagevalueprivate.h"
26 #include "gtkcssshadowvalueprivate.h"
27 #include "gtkcssstyleprivate.h"
28 #include "gtkcsstransformvalueprivate.h"
29 #include "gtkiconthemeprivate.h"
30 #include "gtksnapshot.h"
31 #include "gsktransform.h"
32 
33 #include <math.h>
34 
35 void
gtk_css_style_snapshot_icon(GtkCssStyle * style,GtkSnapshot * snapshot,double width,double height)36 gtk_css_style_snapshot_icon (GtkCssStyle            *style,
37                              GtkSnapshot            *snapshot,
38                              double                  width,
39                              double                  height)
40 {
41   GskTransform *transform;
42   GtkCssImage *image;
43   gboolean has_shadow;
44 
45   g_return_if_fail (GTK_IS_CSS_STYLE (style));
46   g_return_if_fail (snapshot != NULL);
47 
48   if (width == 0.0 || height == 0.0)
49     return;
50 
51   image = _gtk_css_image_value_get_image (style->other->icon_source);
52   if (image == NULL)
53     return;
54 
55   transform = gtk_css_transform_value_get_transform (style->other->icon_transform);
56 
57   gtk_snapshot_push_debug (snapshot, "CSS Icon @ %gx%g", width, height);
58 
59   gtk_css_filter_value_push_snapshot (style->other->icon_filter, snapshot);
60 
61   has_shadow = gtk_css_shadow_value_push_snapshot (style->icon->icon_shadow, snapshot);
62 
63   if (transform == NULL)
64     {
65       gtk_css_image_snapshot (image, snapshot, width, height);
66     }
67   else
68     {
69       gtk_snapshot_save (snapshot);
70 
71       /* XXX: Implement -gtk-icon-transform-origin instead of hardcoding "50% 50%" here */
72       gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width / 2.0, height / 2.0));
73       gtk_snapshot_transform (snapshot, transform);
74       gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- width / 2.0, - height / 2.0));
75 
76       gtk_css_image_snapshot (image, snapshot, width, height);
77 
78       gtk_snapshot_restore (snapshot);
79     }
80 
81   if (has_shadow)
82     gtk_snapshot_pop (snapshot);
83 
84   gtk_css_filter_value_pop_snapshot (style->other->icon_filter, snapshot);
85 
86   gtk_snapshot_pop (snapshot);
87 
88   gsk_transform_unref (transform);
89 }
90 
91 void
gtk_css_style_snapshot_icon_paintable(GtkCssStyle * style,GtkSnapshot * snapshot,GdkPaintable * paintable,double width,double height)92 gtk_css_style_snapshot_icon_paintable (GtkCssStyle  *style,
93                                        GtkSnapshot  *snapshot,
94                                        GdkPaintable *paintable,
95                                        double        width,
96                                        double        height)
97 {
98   GskTransform *transform;
99   gboolean has_shadow;
100   gboolean is_icon_paintable;
101   GdkRGBA fg, sc, wc, ec;
102 
103   g_return_if_fail (GTK_IS_CSS_STYLE (style));
104   g_return_if_fail (snapshot != NULL);
105   g_return_if_fail (GDK_IS_PAINTABLE (paintable));
106   g_return_if_fail (width > 0);
107   g_return_if_fail (height > 0);
108 
109   transform = gtk_css_transform_value_get_transform (style->other->icon_transform);
110 
111   gtk_css_filter_value_push_snapshot (style->other->icon_filter, snapshot);
112 
113   has_shadow = gtk_css_shadow_value_push_snapshot (style->icon->icon_shadow, snapshot);
114 
115   is_icon_paintable = GTK_IS_ICON_PAINTABLE (paintable);
116   if (is_icon_paintable)
117     {
118       gtk_icon_theme_lookup_symbolic_colors (style, &fg, &sc, &wc, &ec);
119 
120       if (fg.alpha == 0.0f)
121         goto transparent;
122     }
123 
124   if (transform == NULL)
125     {
126       if (is_icon_paintable)
127         gtk_icon_paintable_snapshot_with_colors (GTK_ICON_PAINTABLE (paintable), snapshot, width, height, &fg, &sc, &wc, &ec);
128       else
129         gdk_paintable_snapshot (paintable, snapshot, width, height);
130     }
131   else
132     {
133       gtk_snapshot_save (snapshot);
134 
135       /* XXX: Implement -gtk-icon-transform-origin instead of hardcoding "50% 50%" here */
136       gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width / 2.0, height / 2.0));
137       gtk_snapshot_transform (snapshot, transform);
138       gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- width / 2.0, - height / 2.0));
139 
140       if (is_icon_paintable)
141         gtk_icon_paintable_snapshot_with_colors (GTK_ICON_PAINTABLE (paintable), snapshot, width, height, &fg, &sc, &wc, &ec);
142       else
143         gdk_paintable_snapshot (paintable, snapshot, width, height);
144 
145       gtk_snapshot_restore (snapshot);
146     }
147 
148 transparent:
149   if (has_shadow)
150     gtk_snapshot_pop (snapshot);
151 
152   gtk_css_filter_value_pop_snapshot (style->other->icon_filter, snapshot);
153 
154   gsk_transform_unref (transform);
155 }
156