1 | /* |
2 | * Copyright © 2012 Red Hat Inc. |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2.1 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
16 | * |
17 | * Authors: Benjamin Otte <otte@gnome.org> |
18 | */ |
19 | |
20 | #include "config.h" |
21 | |
22 | #include "gtkcssimageiconthemeprivate.h" |
23 | |
24 | #include <math.h> |
25 | |
26 | #include "gtk/css/gtkcssserializerprivate.h" |
27 | #include "gtksettingsprivate.h" |
28 | #include "gtksnapshot.h" |
29 | #include "gtkstyleproviderprivate.h" |
30 | #include "gtksymbolicpaintable.h" |
31 | #include "gtkiconthemeprivate.h" |
32 | |
33 | G_DEFINE_TYPE (GtkCssImageIconTheme, _gtk_css_image_icon_theme, GTK_TYPE_CSS_IMAGE) |
34 | |
35 | static double |
36 | gtk_css_image_icon_theme_get_aspect_ratio (GtkCssImage *image) |
37 | { |
38 | /* icon theme icons only take a single size when requesting, so we insist on being square */ |
39 | return 1.0; |
40 | } |
41 | |
42 | static void |
43 | gtk_css_image_icon_theme_snapshot (GtkCssImage *image, |
44 | GtkSnapshot *snapshot, |
45 | double width, |
46 | double height) |
47 | { |
48 | GtkCssImageIconTheme *icon_theme = GTK_CSS_IMAGE_ICON_THEME (image); |
49 | GtkIconPaintable *icon; |
50 | double icon_width, icon_height; |
51 | int size; |
52 | double x, y; |
53 | |
54 | size = floor (MIN (width, height)); |
55 | if (size <= 0) |
56 | return; |
57 | |
58 | if (size == icon_theme->cached_size && |
59 | icon_theme->cached_icon != NULL) |
60 | { |
61 | icon = icon_theme->cached_icon; |
62 | } |
63 | else |
64 | { |
65 | icon = gtk_icon_theme_lookup_icon (self: icon_theme->icon_theme, |
66 | icon_name: icon_theme->name, |
67 | NULL, |
68 | size, |
69 | scale: icon_theme->scale, |
70 | direction: GTK_TEXT_DIR_NONE, |
71 | flags: 0); |
72 | |
73 | g_assert (icon != NULL); |
74 | |
75 | g_clear_object (&icon_theme->cached_icon); |
76 | |
77 | icon_theme->cached_size = size; |
78 | icon_theme->cached_icon = icon; |
79 | } |
80 | |
81 | icon_width = (double) MIN (gdk_paintable_get_intrinsic_width (GDK_PAINTABLE (icon)), width); |
82 | icon_height = (double) MIN (gdk_paintable_get_intrinsic_height (GDK_PAINTABLE (icon)), height); |
83 | |
84 | x = (width - icon_width) / 2; |
85 | y = (height - icon_height) / 2; |
86 | |
87 | if (x != 0 || y != 0) |
88 | { |
89 | gtk_snapshot_save (snapshot); |
90 | gtk_snapshot_translate (snapshot, point: &GRAPHENE_POINT_INIT (x, y)); |
91 | } |
92 | gtk_symbolic_paintable_snapshot_symbolic (paintable: GTK_SYMBOLIC_PAINTABLE (ptr: icon), |
93 | snapshot, |
94 | width: icon_width, |
95 | height: icon_height, |
96 | colors: icon_theme->colors, |
97 | G_N_ELEMENTS (icon_theme->colors)); |
98 | if (x != 0 || y != 0) |
99 | gtk_snapshot_restore (snapshot); |
100 | } |
101 | |
102 | static guint |
103 | gtk_css_image_icon_theme_parse_arg (GtkCssParser *parser, |
104 | guint arg, |
105 | gpointer data) |
106 | { |
107 | GtkCssImageIconTheme *icon_theme = data; |
108 | |
109 | icon_theme->name = gtk_css_parser_consume_string (self: parser); |
110 | if (icon_theme->name == NULL) |
111 | return 0; |
112 | |
113 | return 1; |
114 | } |
115 | |
116 | static gboolean |
117 | gtk_css_image_icon_theme_parse (GtkCssImage *image, |
118 | GtkCssParser *parser) |
119 | { |
120 | if (!gtk_css_parser_has_function (self: parser, name: "-gtk-icontheme" )) |
121 | { |
122 | gtk_css_parser_error_syntax (self: parser, format: "Expected '-gtk-icontheme('" ); |
123 | return FALSE; |
124 | } |
125 | |
126 | return gtk_css_parser_consume_function (self: parser, min_args: 1, max_args: 1, parse_func: gtk_css_image_icon_theme_parse_arg, data: image); |
127 | } |
128 | |
129 | static void |
130 | gtk_css_image_icon_theme_print (GtkCssImage *image, |
131 | GString *string) |
132 | { |
133 | GtkCssImageIconTheme *icon_theme = GTK_CSS_IMAGE_ICON_THEME (image); |
134 | |
135 | g_string_append (string, val: "-gtk-icontheme(" ); |
136 | gtk_css_print_string (str: string, string: icon_theme->name, FALSE); |
137 | g_string_append (string, val: ")" ); |
138 | } |
139 | |
140 | static GtkCssImage * |
141 | gtk_css_image_icon_theme_compute (GtkCssImage *image, |
142 | guint property_id, |
143 | GtkStyleProvider *provider, |
144 | GtkCssStyle *style, |
145 | GtkCssStyle *parent_style) |
146 | { |
147 | GtkCssImageIconTheme *icon_theme = GTK_CSS_IMAGE_ICON_THEME (image); |
148 | GtkCssImageIconTheme *copy; |
149 | GtkSettings *settings; |
150 | GdkDisplay *display; |
151 | |
152 | copy = g_object_new (GTK_TYPE_CSS_IMAGE_ICON_THEME, NULL); |
153 | copy->name = g_strdup (str: icon_theme->name); |
154 | settings = gtk_style_provider_get_settings (provider); |
155 | display = _gtk_settings_get_display (settings); |
156 | copy->icon_theme = gtk_icon_theme_get_for_display (display); |
157 | copy->serial = gtk_icon_theme_get_serial (self: copy->icon_theme); |
158 | copy->scale = gtk_style_provider_get_scale (provider); |
159 | gtk_icon_theme_lookup_symbolic_colors (style, color_out: copy->colors); |
160 | |
161 | return GTK_CSS_IMAGE (copy); |
162 | } |
163 | |
164 | static gboolean |
165 | gtk_css_image_icon_theme_equal (GtkCssImage *image1, |
166 | GtkCssImage *image2) |
167 | { |
168 | GtkCssImageIconTheme *icon_theme1 = (GtkCssImageIconTheme *) image1; |
169 | GtkCssImageIconTheme *icon_theme2 = (GtkCssImageIconTheme *) image2; |
170 | |
171 | return icon_theme1->serial == icon_theme2->serial && |
172 | icon_theme1->icon_theme == icon_theme2->icon_theme && |
173 | g_str_equal (v1: icon_theme1->name, v2: icon_theme2->name); |
174 | } |
175 | |
176 | static void |
177 | gtk_css_image_icon_theme_dispose (GObject *object) |
178 | { |
179 | GtkCssImageIconTheme *icon_theme = GTK_CSS_IMAGE_ICON_THEME (object); |
180 | |
181 | g_free (mem: icon_theme->name); |
182 | icon_theme->name = NULL; |
183 | |
184 | g_clear_object (&icon_theme->cached_icon); |
185 | |
186 | G_OBJECT_CLASS (_gtk_css_image_icon_theme_parent_class)->dispose (object); |
187 | } |
188 | |
189 | static void |
190 | _gtk_css_image_icon_theme_class_init (GtkCssImageIconThemeClass *klass) |
191 | { |
192 | GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass); |
193 | GObjectClass *object_class = G_OBJECT_CLASS (klass); |
194 | |
195 | image_class->get_aspect_ratio = gtk_css_image_icon_theme_get_aspect_ratio; |
196 | image_class->snapshot = gtk_css_image_icon_theme_snapshot; |
197 | image_class->parse = gtk_css_image_icon_theme_parse; |
198 | image_class->print = gtk_css_image_icon_theme_print; |
199 | image_class->compute = gtk_css_image_icon_theme_compute; |
200 | image_class->equal = gtk_css_image_icon_theme_equal; |
201 | |
202 | object_class->dispose = gtk_css_image_icon_theme_dispose; |
203 | } |
204 | |
205 | static void |
206 | _gtk_css_image_icon_theme_init (GtkCssImageIconTheme *icon_theme) |
207 | { |
208 | icon_theme->icon_theme = gtk_icon_theme_get_for_display (display: gdk_display_get_default ()); |
209 | icon_theme->scale = 1; |
210 | icon_theme->cached_size = -1; |
211 | icon_theme->cached_icon = NULL; |
212 | } |
213 | |
214 | |