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
33G_DEFINE_TYPE (GtkCssImageIconTheme, _gtk_css_image_icon_theme, GTK_TYPE_CSS_IMAGE)
34
35static double
36gtk_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
42static void
43gtk_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
102static guint
103gtk_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
116static gboolean
117gtk_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
129static void
130gtk_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
140static GtkCssImage *
141gtk_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
164static gboolean
165gtk_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
176static void
177gtk_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
189static 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
205static 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

source code of gtk/gtk/gtkcssimageicontheme.c