File: | ctk/ctkicontheme.c |
Warning: | line 2849, column 7 This statement is never executed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* CtkIconTheme - a loader for icon themes |
2 | * ctk-icon-theme.c Copyright (C) 2002, 2003 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 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 | |
18 | #include "config.h" |
19 | |
20 | #include <sys/types.h> |
21 | #include <sys/stat.h> |
22 | #ifdef HAVE_UNISTD_H1 |
23 | #include <unistd.h> |
24 | #endif |
25 | #include <string.h> |
26 | #include <stdlib.h> |
27 | #include <math.h> |
28 | #include <glib.h> |
29 | #include <glib/gstdio.h> |
30 | |
31 | #ifdef G_OS_WIN32 |
32 | #ifndef S_ISDIR |
33 | #define S_ISDIR(mode)((((mode)) & 0170000) == (0040000)) ((mode)&_S_IFDIR) |
34 | #endif |
35 | #define WIN32_LEAN_AND_MEAN |
36 | #include <windows.h> |
37 | #include <shellapi.h> |
38 | #include "win32/cdkwin32.h" |
39 | #endif /* G_OS_WIN32 */ |
40 | |
41 | #include "ctkiconthemeprivate.h" |
42 | #include "ctkcsspalettevalueprivate.h" |
43 | #include "ctkcssrgbavalueprivate.h" |
44 | #include "ctkdebug.h" |
45 | #include "ctkiconfactory.h" |
46 | #include "ctkiconcache.h" |
47 | #include "ctkintl.h" |
48 | #include "ctkmain.h" |
49 | #include "deprecated/ctknumerableiconprivate.h" |
50 | #include "ctksettingsprivate.h" |
51 | #include "ctkstylecontextprivate.h" |
52 | #include "ctkprivate.h" |
53 | #include "gdkpixbufutilsprivate.h" |
54 | |
55 | #undef CDK_DEPRECATED |
56 | #undef CDK_DEPRECATED_FOR |
57 | #define CDK_DEPRECATED |
58 | #define CDK_DEPRECATED_FOR(f) |
59 | |
60 | #include "ctkstyle.h" |
61 | |
62 | /* this is in case round() is not provided by the compiler, |
63 | * such as in the case of C89 compilers, like MSVC |
64 | */ |
65 | #include "fallback-c89.c" |
66 | |
67 | /** |
68 | * SECTION:ctkicontheme |
69 | * @Short_description: Looking up icons by name |
70 | * @Title: CtkIconTheme |
71 | * |
72 | * #CtkIconTheme provides a facility for looking up icons by name |
73 | * and size. The main reason for using a name rather than simply |
74 | * providing a filename is to allow different icons to be used |
75 | * depending on what “icon theme” is selected |
76 | * by the user. The operation of icon themes on Linux and Unix |
77 | * follows the [Icon Theme Specification](http://www.freedesktop.org/Standards/icon-theme-spec) |
78 | * There is a fallback icon theme, named `hicolor`, where applications |
79 | * should install their icons, but additional icon themes can be installed |
80 | * as operating system vendors and users choose. |
81 | * |
82 | * Named icons are similar to the deprecated [Stock Items][ctkstock], |
83 | * and the distinction between the two may be a bit confusing. |
84 | * A few things to keep in mind: |
85 | * |
86 | * - Stock images usually are used in conjunction with |
87 | * [Stock Items][ctkstock], such as %CTK_STOCK_OK or |
88 | * %CTK_STOCK_OPEN. Named icons are easier to set up and therefore |
89 | * are more useful for new icons that an application wants to |
90 | * add, such as application icons or window icons. |
91 | * |
92 | * - Stock images can only be loaded at the symbolic sizes defined |
93 | * by the #CtkIconSize enumeration, or by custom sizes defined |
94 | * by ctk_icon_size_register(), while named icons are more flexible |
95 | * and any pixel size can be specified. |
96 | * |
97 | * - Because stock images are closely tied to stock items, and thus |
98 | * to actions in the user interface, stock images may come in |
99 | * multiple variants for different widget states or writing |
100 | * directions. |
101 | * |
102 | * A good rule of thumb is that if there is a stock image for what |
103 | * you want to use, use it, otherwise use a named icon. It turns |
104 | * out that internally stock images are generally defined in |
105 | * terms of one or more named icons. (An example of the |
106 | * more than one case is icons that depend on writing direction; |
107 | * %CTK_STOCK_GO_FORWARD uses the two themed icons |
108 | * “ctk-stock-go-forward-ltr” and “ctk-stock-go-forward-rtl”.) |
109 | * |
110 | * In many cases, named themes are used indirectly, via #CtkImage |
111 | * or stock items, rather than directly, but looking up icons |
112 | * directly is also simple. The #CtkIconTheme object acts |
113 | * as a database of all the icons in the current theme. You |
114 | * can create new #CtkIconTheme objects, but it’s much more |
115 | * efficient to use the standard icon theme for the #CdkScreen |
116 | * so that the icon information is shared with other people |
117 | * looking up icons. |
118 | * |[<!-- language="C" --> |
119 | * GError *error = NULL; |
120 | * CtkIconTheme *icon_theme; |
121 | * GdkPixbuf *pixbuf; |
122 | * |
123 | * icon_theme = ctk_icon_theme_get_default (); |
124 | * pixbuf = ctk_icon_theme_load_icon (icon_theme, |
125 | * "my-icon-name", // icon name |
126 | * 48, // icon size |
127 | * 0, // flags |
128 | * &error); |
129 | * if (!pixbuf) |
130 | * { |
131 | * g_warning ("Couldn’t load icon: %s", error->message); |
132 | * g_error_free (error); |
133 | * } |
134 | * else |
135 | * { |
136 | * // Use the pixbuf |
137 | * g_object_unref (pixbuf); |
138 | * } |
139 | * ]| |
140 | */ |
141 | |
142 | #define FALLBACK_ICON_THEME"hicolor" "hicolor" |
143 | |
144 | typedef enum |
145 | { |
146 | ICON_THEME_DIR_FIXED, |
147 | ICON_THEME_DIR_SCALABLE, |
148 | ICON_THEME_DIR_THRESHOLD, |
149 | ICON_THEME_DIR_UNTHEMED |
150 | } IconThemeDirType; |
151 | |
152 | /* In reverse search order: */ |
153 | typedef enum |
154 | { |
155 | ICON_SUFFIX_NONE = 0, |
156 | ICON_SUFFIX_XPM = 1 << 0, |
157 | ICON_SUFFIX_SVG = 1 << 1, |
158 | ICON_SUFFIX_PNG = 1 << 2, |
159 | HAS_ICON_FILE = 1 << 3, |
160 | ICON_SUFFIX_SYMBOLIC_PNG = 1 << 4 |
161 | } IconSuffix; |
162 | |
163 | #define INFO_CACHE_LRU_SIZE32 32 |
164 | #if 0 |
165 | #define DEBUG_CACHE(args) g_print args |
166 | #else |
167 | #define DEBUG_CACHE(args) |
168 | #endif |
169 | |
170 | struct _CtkIconThemePrivate |
171 | { |
172 | GHashTable *info_cache; |
173 | GList *info_cache_lru; |
174 | |
175 | gchar *current_theme; |
176 | gchar **search_path; |
177 | gint search_path_len; |
178 | GList *resource_paths; |
179 | |
180 | guint custom_theme : 1; |
181 | guint is_screen_singleton : 1; |
182 | guint pixbuf_supports_svg : 1; |
183 | guint themes_valid : 1; |
184 | guint loading_themes : 1; |
185 | |
186 | /* A list of all the themes needed to look up icons. |
187 | * In search order, without duplicates |
188 | */ |
189 | GList *themes; |
190 | GHashTable *unthemed_icons; |
191 | |
192 | /* CdkScreen for the icon theme (may be NULL) */ |
193 | CdkScreen *screen; |
194 | |
195 | /* time when we last stat:ed for theme changes */ |
196 | gint64 last_stat_time; |
197 | GList *dir_mtimes; |
198 | |
199 | gulong theme_changed_idle; |
200 | }; |
201 | |
202 | typedef struct { |
203 | gchar **icon_names; |
204 | gint size; |
205 | gint scale; |
206 | CtkIconLookupFlags flags; |
207 | } IconInfoKey; |
208 | |
209 | typedef struct _SymbolicPixbufCache SymbolicPixbufCache; |
210 | |
211 | struct _SymbolicPixbufCache { |
212 | GdkPixbuf *pixbuf; |
213 | GdkPixbuf *proxy_pixbuf; |
214 | CdkRGBA fg; |
215 | CdkRGBA success_color; |
216 | CdkRGBA warning_color; |
217 | CdkRGBA error_color; |
218 | SymbolicPixbufCache *next; |
219 | }; |
220 | |
221 | struct _CtkIconInfoClass |
222 | { |
223 | GObjectClass parent_class; |
224 | }; |
225 | |
226 | struct _CtkIconInfo |
227 | { |
228 | GObject parent_instance; |
229 | |
230 | /* Information about the source |
231 | */ |
232 | IconInfoKey key; |
233 | CtkIconTheme *in_cache; |
234 | |
235 | gchar *filename; |
236 | GFile *icon_file; |
237 | GLoadableIcon *loadable; |
238 | GSList *emblem_infos; |
239 | |
240 | /* Cache pixbuf (if there is any) */ |
241 | GdkPixbuf *cache_pixbuf; |
242 | |
243 | /* Information about the directory where |
244 | * the source was found |
245 | */ |
246 | IconThemeDirType dir_type; |
247 | gint dir_size; |
248 | gint dir_scale; |
249 | gint min_size; |
250 | gint max_size; |
251 | |
252 | /* Parameters influencing the scaled icon |
253 | */ |
254 | gint desired_size; |
255 | gint desired_scale; |
256 | guint forced_size : 1; |
257 | guint emblems_applied : 1; |
258 | guint is_svg : 1; |
259 | guint is_resource : 1; |
260 | |
261 | /* Cached information if we go ahead and try to load |
262 | * the icon. |
263 | */ |
264 | GdkPixbuf *pixbuf; |
265 | GdkPixbuf *proxy_pixbuf; |
266 | GError *load_error; |
267 | gdouble unscaled_scale; |
268 | gdouble scale; |
269 | |
270 | SymbolicPixbufCache *symbolic_pixbuf_cache; |
271 | |
272 | gint symbolic_width; |
273 | gint symbolic_height; |
274 | }; |
275 | |
276 | typedef struct |
277 | { |
278 | gchar *name; |
279 | gchar *display_name; |
280 | gchar *comment; |
281 | gchar *example; |
282 | |
283 | /* In search order */ |
284 | GList *dirs; |
285 | } IconTheme; |
286 | |
287 | typedef struct |
288 | { |
289 | IconThemeDirType type; |
290 | GQuark context; |
291 | |
292 | gint size; |
293 | gint min_size; |
294 | gint max_size; |
295 | gint threshold; |
296 | gint scale; |
297 | gboolean is_resource; |
298 | |
299 | gchar *dir; |
300 | gchar *subdir; |
301 | gint subdir_index; |
302 | |
303 | CtkIconCache *cache; |
304 | |
305 | GHashTable *icons; |
306 | } IconThemeDir; |
307 | |
308 | typedef struct |
309 | { |
310 | gchar *svg_filename; |
311 | gchar *no_svg_filename; |
312 | gboolean is_resource; |
313 | } UnthemedIcon; |
314 | |
315 | typedef struct |
316 | { |
317 | gint size; |
318 | GdkPixbuf *pixbuf; |
319 | } BuiltinIcon; |
320 | |
321 | typedef struct |
322 | { |
323 | gchar *dir; |
324 | time_t mtime; |
325 | CtkIconCache *cache; |
326 | gboolean exists; |
327 | } IconThemeDirMtime; |
328 | |
329 | static void ctk_icon_theme_finalize (GObject *object); |
330 | static void theme_dir_destroy (IconThemeDir *dir); |
331 | static void theme_destroy (IconTheme *theme); |
332 | static CtkIconInfo *theme_lookup_icon (IconTheme *theme, |
333 | const gchar *icon_name, |
334 | gint size, |
335 | gint scale, |
336 | gboolean allow_svg, |
337 | gboolean use_default_icons); |
338 | static void theme_list_icons (IconTheme *theme, |
339 | GHashTable *icons, |
340 | GQuark context); |
341 | static gboolean theme_has_icon (IconTheme *theme, |
342 | const gchar *icon_name); |
343 | static void theme_list_contexts (IconTheme *theme, |
344 | GHashTable *contexts); |
345 | static void theme_subdir_load (CtkIconTheme *icon_theme, |
346 | IconTheme *theme, |
347 | GKeyFile *theme_file, |
348 | gchar *subdir); |
349 | static void do_theme_change (CtkIconTheme *icon_theme); |
350 | static void blow_themes (CtkIconTheme *icon_themes); |
351 | static gboolean rescan_themes (CtkIconTheme *icon_themes); |
352 | static IconSuffix theme_dir_get_icon_suffix (IconThemeDir *dir, |
353 | const gchar *icon_name, |
354 | gboolean *has_icon_file); |
355 | static CtkIconInfo *icon_info_new (IconThemeDirType type, |
356 | gint dir_size, |
357 | gint dir_scale); |
358 | static CtkIconInfo *icon_info_new_builtin (BuiltinIcon *icon); |
359 | static IconSuffix suffix_from_name (const gchar *name); |
360 | static BuiltinIcon *find_builtin_icon (const gchar *icon_name, |
361 | gint size, |
362 | gint scale, |
363 | gint *min_difference_p); |
364 | static void remove_from_lru_cache (CtkIconTheme *icon_theme, |
365 | CtkIconInfo *icon_info); |
366 | static gboolean icon_info_ensure_scale_and_pixbuf (CtkIconInfo* icon_info); |
367 | |
368 | static guint signal_changed = 0; |
369 | |
370 | static GHashTable *icon_theme_builtin_icons; |
371 | |
372 | static guint |
373 | icon_info_key_hash (gconstpointer _key) |
374 | { |
375 | const IconInfoKey *key = _key; |
376 | guint h = 0; |
377 | int i; |
378 | for (i = 0; key->icon_names[i] != NULL((void*)0); i++) |
379 | h ^= g_str_hash (key->icon_names[i]); |
380 | |
381 | h ^= key->size * 0x10001; |
382 | h ^= key->scale * 0x1000010; |
383 | h ^= key->flags * 0x100000100; |
384 | |
385 | return h; |
386 | } |
387 | |
388 | static gboolean |
389 | icon_info_key_equal (gconstpointer _a, |
390 | gconstpointer _b) |
391 | { |
392 | const IconInfoKey *a = _a; |
393 | const IconInfoKey *b = _b; |
394 | int i; |
395 | |
396 | if (a->size != b->size) |
397 | return FALSE(0); |
398 | |
399 | if (a->scale != b->scale) |
400 | return FALSE(0); |
401 | |
402 | if (a->flags != b->flags) |
403 | return FALSE(0); |
404 | |
405 | for (i = 0; |
406 | a->icon_names[i] != NULL((void*)0) && |
407 | b->icon_names[i] != NULL((void*)0); i++) |
408 | { |
409 | if (strcmp (a->icon_names[i], b->icon_names[i]) != 0) |
410 | return FALSE(0); |
411 | } |
412 | |
413 | return a->icon_names[i] == NULL((void*)0) && b->icon_names[i] == NULL((void*)0); |
414 | } |
415 | |
416 | G_DEFINE_TYPE_WITH_PRIVATE (CtkIconTheme, ctk_icon_theme, G_TYPE_OBJECT)static void ctk_icon_theme_init (CtkIconTheme *self); static void ctk_icon_theme_class_init (CtkIconThemeClass *klass); static GType ctk_icon_theme_get_type_once (void); static gpointer ctk_icon_theme_parent_class = ((void*)0); static gint CtkIconTheme_private_offset; static void ctk_icon_theme_class_intern_init (gpointer klass) { ctk_icon_theme_parent_class = g_type_class_peek_parent (klass); if (CtkIconTheme_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkIconTheme_private_offset ); ctk_icon_theme_class_init ((CtkIconThemeClass*) klass); } __attribute__ ((__unused__)) static inline gpointer ctk_icon_theme_get_instance_private (CtkIconTheme *self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkIconTheme_private_offset)))); } GType ctk_icon_theme_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); (void) ( 0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0)) ; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = ctk_icon_theme_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id ) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id )); })) ; } return static_g_define_type_id; } __attribute__ ( (__noinline__)) static GType ctk_icon_theme_get_type_once (void ) { GType g_define_type_id = g_type_register_static_simple (( (GType) ((20) << (2))), g_intern_static_string ("CtkIconTheme" ), sizeof (CtkIconThemeClass), (GClassInitFunc)(void (*)(void )) ctk_icon_theme_class_intern_init, sizeof (CtkIconTheme), ( GInstanceInitFunc)(void (*)(void)) ctk_icon_theme_init, (GTypeFlags ) 0); { {{ CtkIconTheme_private_offset = g_type_add_instance_private (g_define_type_id, sizeof (CtkIconThemePrivate)); };} } return g_define_type_id; } |
417 | |
418 | /** |
419 | * ctk_icon_theme_new: |
420 | * |
421 | * Creates a new icon theme object. Icon theme objects are used |
422 | * to lookup up an icon by name in a particular icon theme. |
423 | * Usually, you’ll want to use ctk_icon_theme_get_default() |
424 | * or ctk_icon_theme_get_for_screen() rather than creating |
425 | * a new icon theme object for scratch. |
426 | * |
427 | * Returns: the newly created #CtkIconTheme object. |
428 | * |
429 | * Since: 2.4 |
430 | */ |
431 | CtkIconTheme * |
432 | ctk_icon_theme_new (void) |
433 | { |
434 | return g_object_new (CTK_TYPE_ICON_THEME(ctk_icon_theme_get_type ()), NULL((void*)0)); |
435 | } |
436 | |
437 | /** |
438 | * ctk_icon_theme_get_default: |
439 | * |
440 | * Gets the icon theme for the default screen. See |
441 | * ctk_icon_theme_get_for_screen(). |
442 | * |
443 | * Returns: (transfer none): A unique #CtkIconTheme associated with |
444 | * the default screen. This icon theme is associated with |
445 | * the screen and can be used as long as the screen |
446 | * is open. Do not ref or unref it. |
447 | * |
448 | * Since: 2.4 |
449 | */ |
450 | CtkIconTheme * |
451 | ctk_icon_theme_get_default (void) |
452 | { |
453 | return ctk_icon_theme_get_for_screen (cdk_screen_get_default ()); |
454 | } |
455 | |
456 | /** |
457 | * ctk_icon_theme_get_for_screen: |
458 | * @screen: a #CdkScreen |
459 | * |
460 | * Gets the icon theme object associated with @screen; if this |
461 | * function has not previously been called for the given |
462 | * screen, a new icon theme object will be created and |
463 | * associated with the screen. Icon theme objects are |
464 | * fairly expensive to create, so using this function |
465 | * is usually a better choice than calling than ctk_icon_theme_new() |
466 | * and setting the screen yourself; by using this function |
467 | * a single icon theme object will be shared between users. |
468 | * |
469 | * Returns: (transfer none): A unique #CtkIconTheme associated with |
470 | * the given screen. This icon theme is associated with |
471 | * the screen and can be used as long as the screen |
472 | * is open. Do not ref or unref it. |
473 | * |
474 | * Since: 2.4 |
475 | */ |
476 | CtkIconTheme * |
477 | ctk_icon_theme_get_for_screen (CdkScreen *screen) |
478 | { |
479 | CtkIconTheme *icon_theme; |
480 | |
481 | g_return_val_if_fail (CDK_IS_SCREEN (screen), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((screen)); GType __t = ((cdk_screen_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CDK_IS_SCREEN (screen)"); return (((void*)0)); } } while (0); |
482 | |
483 | icon_theme = g_object_get_data (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((screen)), (((GType) ((20) << (2)))))))), "ctk-icon-theme"); |
484 | if (!icon_theme) |
485 | { |
486 | CtkIconThemePrivate *priv; |
487 | |
488 | icon_theme = ctk_icon_theme_new (); |
489 | ctk_icon_theme_set_screen (icon_theme, screen); |
490 | |
491 | priv = icon_theme->priv; |
492 | priv->is_screen_singleton = TRUE(!(0)); |
493 | |
494 | g_object_set_data (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((screen)), (((GType) ((20) << (2)))))))), I_("ctk-icon-theme")g_intern_static_string ("ctk-icon-theme"), icon_theme); |
495 | } |
496 | |
497 | return icon_theme; |
498 | } |
499 | |
500 | static void |
501 | ctk_icon_theme_class_init (CtkIconThemeClass *klass) |
502 | { |
503 | GObjectClass *gobject_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); |
504 | |
505 | gobject_class->finalize = ctk_icon_theme_finalize; |
506 | |
507 | /** |
508 | * CtkIconTheme::changed: |
509 | * @icon_theme: the icon theme |
510 | * |
511 | * Emitted when the current icon theme is switched or CTK+ detects |
512 | * that a change has occurred in the contents of the current |
513 | * icon theme. |
514 | */ |
515 | signal_changed = g_signal_new (I_("changed")g_intern_static_string ("changed"), |
516 | G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type), |
517 | G_SIGNAL_RUN_LAST, |
518 | G_STRUCT_OFFSET (CtkIconThemeClass, changed)((glong) __builtin_offsetof(CtkIconThemeClass, changed)), |
519 | NULL((void*)0), NULL((void*)0), |
520 | NULL((void*)0), |
521 | G_TYPE_NONE((GType) ((1) << (2))), 0); |
522 | } |
523 | |
524 | |
525 | /* Callback when the display that the icon theme is attached |
526 | * to is closed; unset the screen, and if it’s the unique theme |
527 | * for the screen, drop the reference |
528 | */ |
529 | static void |
530 | display_closed (CdkDisplay *display G_GNUC_UNUSED__attribute__ ((__unused__)), |
531 | gboolean is_error G_GNUC_UNUSED__attribute__ ((__unused__)), |
532 | CtkIconTheme *icon_theme) |
533 | { |
534 | CtkIconThemePrivate *priv = icon_theme->priv; |
535 | CdkScreen *screen = priv->screen; |
536 | gboolean was_screen_singleton = priv->is_screen_singleton; |
537 | |
538 | if (was_screen_singleton) |
539 | { |
540 | g_object_set_data (G_OBJECT (screen)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((screen)), (((GType) ((20) << (2)))))))), I_("ctk-icon-theme")g_intern_static_string ("ctk-icon-theme"), NULL((void*)0)); |
541 | priv->is_screen_singleton = FALSE(0); |
542 | } |
543 | |
544 | ctk_icon_theme_set_screen (icon_theme, NULL((void*)0)); |
545 | |
546 | if (was_screen_singleton) |
547 | { |
548 | g_object_unref (icon_theme); |
549 | } |
550 | } |
551 | |
552 | static void |
553 | update_current_theme (CtkIconTheme *icon_theme) |
554 | { |
555 | #define theme_changed(_old, _new) \ |
556 | ((_old && !_new) || (!_old && _new) || \ |
557 | (_old && _new && strcmp (_old, _new) != 0)) |
558 | CtkIconThemePrivate *priv = icon_theme->priv; |
559 | |
560 | if (!priv->custom_theme) |
561 | { |
562 | gchar *theme = NULL((void*)0); |
563 | gboolean changed = FALSE(0); |
564 | |
565 | if (priv->screen) |
566 | { |
567 | CtkSettings *settings = ctk_settings_get_for_screen (priv->screen); |
568 | g_object_get (settings, "ctk-icon-theme-name", &theme, NULL((void*)0)); |
569 | } |
570 | |
571 | if (theme_changed (priv->current_theme, theme)) |
572 | { |
573 | g_free (priv->current_theme); |
574 | priv->current_theme = theme; |
575 | changed = TRUE(!(0)); |
576 | } |
577 | else |
578 | g_free (theme); |
579 | |
580 | if (changed) |
581 | do_theme_change (icon_theme); |
582 | } |
583 | #undef theme_changed |
584 | } |
585 | |
586 | /* Callback when the icon theme CtkSetting changes |
587 | */ |
588 | static void |
589 | theme_changed (CtkSettings *settings G_GNUC_UNUSED__attribute__ ((__unused__)), |
590 | GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__)), |
591 | CtkIconTheme *icon_theme) |
592 | { |
593 | update_current_theme (icon_theme); |
594 | } |
595 | |
596 | static void |
597 | unset_screen (CtkIconTheme *icon_theme) |
598 | { |
599 | CtkIconThemePrivate *priv = icon_theme->priv; |
600 | CtkSettings *settings; |
601 | CdkDisplay *display; |
602 | |
603 | if (priv->screen) |
604 | { |
605 | settings = ctk_settings_get_for_screen (priv->screen); |
606 | display = cdk_screen_get_display (priv->screen); |
607 | |
608 | g_signal_handlers_disconnect_by_func (display,g_signal_handlers_disconnect_matched ((display), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), ((gpointer) display_closed), (icon_theme)) |
609 | (gpointer) display_closed,g_signal_handlers_disconnect_matched ((display), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), ((gpointer) display_closed), (icon_theme)) |
610 | icon_theme)g_signal_handlers_disconnect_matched ((display), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), ((gpointer) display_closed), (icon_theme)); |
611 | if (settings) |
612 | g_signal_handlers_disconnect_by_func (settings,g_signal_handlers_disconnect_matched ((settings), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), ((gpointer) theme_changed), (icon_theme)) |
613 | (gpointer) theme_changed,g_signal_handlers_disconnect_matched ((settings), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), ((gpointer) theme_changed), (icon_theme)) |
614 | icon_theme)g_signal_handlers_disconnect_matched ((settings), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), ((gpointer) theme_changed), (icon_theme)); |
615 | |
616 | priv->screen = NULL((void*)0); |
617 | } |
618 | } |
619 | |
620 | /** |
621 | * ctk_icon_theme_set_screen: |
622 | * @icon_theme: a #CtkIconTheme |
623 | * @screen: a #CdkScreen |
624 | * |
625 | * Sets the screen for an icon theme; the screen is used |
626 | * to track the user’s currently configured icon theme, |
627 | * which might be different for different screens. |
628 | * |
629 | * Since: 2.4 |
630 | */ |
631 | void |
632 | ctk_icon_theme_set_screen (CtkIconTheme *icon_theme, |
633 | CdkScreen *screen) |
634 | { |
635 | CtkIconThemePrivate *priv; |
636 | CtkSettings *settings; |
637 | CdkDisplay *display; |
638 | |
639 | g_return_if_fail (CTK_ICON_THEME (icon_theme))do { if ((((((CtkIconTheme*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((icon_theme)), ((ctk_icon_theme_get_type ( ))))))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_ICON_THEME (icon_theme)"); return; } } while (0); |
640 | g_return_if_fail (screen == NULL || CDK_IS_SCREEN (screen))do { if ((screen == ((void*)0) || (((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((screen)); GType __t = ((cdk_screen_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "screen == NULL || CDK_IS_SCREEN (screen)" ); return; } } while (0); |
641 | |
642 | priv = icon_theme->priv; |
643 | |
644 | unset_screen (icon_theme); |
645 | |
646 | if (screen) |
647 | { |
648 | display = cdk_screen_get_display (screen); |
649 | settings = ctk_settings_get_for_screen (screen); |
650 | |
651 | priv->screen = screen; |
652 | |
653 | g_signal_connect (display, "closed",g_signal_connect_data ((display), ("closed"), (((GCallback) ( display_closed))), (icon_theme), ((void*)0), (GConnectFlags) 0 ) |
654 | G_CALLBACK (display_closed), icon_theme)g_signal_connect_data ((display), ("closed"), (((GCallback) ( display_closed))), (icon_theme), ((void*)0), (GConnectFlags) 0 ); |
655 | g_signal_connect (settings, "notify::ctk-icon-theme-name",g_signal_connect_data ((settings), ("notify::ctk-icon-theme-name" ), (((GCallback) (theme_changed))), (icon_theme), ((void*)0), (GConnectFlags) 0) |
656 | G_CALLBACK (theme_changed), icon_theme)g_signal_connect_data ((settings), ("notify::ctk-icon-theme-name" ), (((GCallback) (theme_changed))), (icon_theme), ((void*)0), (GConnectFlags) 0); |
657 | } |
658 | |
659 | update_current_theme (icon_theme); |
660 | } |
661 | |
662 | /* Checks whether a loader for SVG files has been registered |
663 | * with GdkPixbuf. |
664 | */ |
665 | static gboolean |
666 | pixbuf_supports_svg (void) |
667 | { |
668 | GSList *formats; |
669 | GSList *tmp_list; |
670 | static gint found_svg = -1; |
671 | |
672 | if (found_svg != -1) |
673 | return found_svg; |
674 | |
675 | formats = gdk_pixbuf_get_formats (); |
676 | |
677 | found_svg = FALSE(0); |
678 | for (tmp_list = formats; tmp_list && !found_svg; tmp_list = tmp_list->next) |
679 | { |
680 | gchar **mime_types = gdk_pixbuf_format_get_mime_types (tmp_list->data); |
681 | gchar **mime_type; |
682 | |
683 | for (mime_type = mime_types; *mime_type && !found_svg; mime_type++) |
684 | { |
685 | if (strcmp (*mime_type, "image/svg") == 0) |
686 | found_svg = TRUE(!(0)); |
687 | } |
688 | |
689 | g_strfreev (mime_types); |
690 | } |
691 | |
692 | g_slist_free (formats); |
693 | |
694 | return found_svg; |
695 | } |
696 | |
697 | /* The icon info was removed from the icon_info_hash hash table */ |
698 | static void |
699 | icon_info_uncached (CtkIconInfo *icon_info) |
700 | { |
701 | CtkIconTheme *icon_theme = icon_info->in_cache; |
702 | |
703 | DEBUG_CACHE (("removing %p (%s %d 0x%x) from cache (icon_them: %p) (cache size %d)\n", |
704 | icon_info, |
705 | g_strjoinv (",", icon_info->key.icon_names), |
706 | icon_info->key.size, icon_info->key.flags, |
707 | icon_theme, |
708 | icon_theme != NULL ? g_hash_table_size (icon_theme->priv->info_cache) : 0)); |
709 | |
710 | icon_info->in_cache = NULL((void*)0); |
711 | |
712 | if (icon_theme != NULL((void*)0)) |
713 | remove_from_lru_cache (icon_theme, icon_info); |
714 | } |
715 | |
716 | static void |
717 | ctk_icon_theme_init (CtkIconTheme *icon_theme) |
718 | { |
719 | CtkIconThemePrivate *priv; |
720 | const gchar * const *xdg_data_dirs; |
721 | int i, j; |
722 | |
723 | priv = ctk_icon_theme_get_instance_private (icon_theme); |
724 | icon_theme->priv = priv; |
725 | |
726 | priv->info_cache = g_hash_table_new_full (icon_info_key_hash, icon_info_key_equal, NULL((void*)0), |
727 | (GDestroyNotify)icon_info_uncached); |
728 | |
729 | priv->custom_theme = FALSE(0); |
730 | |
731 | xdg_data_dirs = g_get_system_data_dirs (); |
732 | for (i = 0; xdg_data_dirs[i]; i++) ; |
733 | |
734 | priv->search_path_len = 2 * i + 2; |
735 | |
736 | priv->search_path = g_new (char *, priv->search_path_len)((char * *) g_malloc_n ((priv->search_path_len), sizeof (char *))); |
737 | |
738 | i = 0; |
739 | priv->search_path[i++] = g_build_filename (g_get_user_data_dir (), "icons", NULL((void*)0)); |
740 | priv->search_path[i++] = g_build_filename (g_get_home_dir (), ".icons", NULL((void*)0)); |
741 | |
742 | for (j = 0; xdg_data_dirs[j]; j++) |
743 | priv->search_path[i++] = g_build_filename (xdg_data_dirs[j], "icons", NULL((void*)0)); |
744 | |
745 | for (j = 0; xdg_data_dirs[j]; j++) |
746 | priv->search_path[i++] = g_build_filename (xdg_data_dirs[j], "pixmaps", NULL((void*)0)); |
747 | |
748 | priv->resource_paths = g_list_append (NULL((void*)0), g_strdup ("/org/ctk/libctk/icons/")g_strdup_inline ("/org/ctk/libctk/icons/")); |
749 | |
750 | priv->themes_valid = FALSE(0); |
751 | priv->themes = NULL((void*)0); |
752 | priv->unthemed_icons = NULL((void*)0); |
753 | |
754 | priv->pixbuf_supports_svg = pixbuf_supports_svg (); |
755 | } |
756 | |
757 | static void |
758 | free_dir_mtime (IconThemeDirMtime *dir_mtime) |
759 | { |
760 | if (dir_mtime->cache) |
761 | _ctk_icon_cache_unref (dir_mtime->cache); |
762 | |
763 | g_free (dir_mtime->dir); |
764 | g_slice_free (IconThemeDirMtime, dir_mtime)do { if (1) g_slice_free1 (sizeof (IconThemeDirMtime), (dir_mtime )); else (void) ((IconThemeDirMtime*) 0 == (dir_mtime)); } while (0); |
765 | } |
766 | |
767 | static gboolean |
768 | theme_changed_idle (gpointer user_data) |
769 | { |
770 | CtkIconTheme *icon_theme; |
771 | CtkIconThemePrivate *priv; |
772 | |
773 | icon_theme = CTK_ICON_THEME (user_data)((((CtkIconTheme*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((user_data)), ((ctk_icon_theme_get_type ())))))); |
774 | priv = icon_theme->priv; |
775 | |
776 | g_signal_emit (icon_theme, signal_changed, 0); |
777 | |
778 | if (priv->screen && priv->is_screen_singleton) |
779 | ctk_style_context_reset_widgets (priv->screen); |
780 | |
781 | priv->theme_changed_idle = 0; |
782 | |
783 | return FALSE(0); |
784 | } |
785 | |
786 | static void |
787 | queue_theme_changed (CtkIconTheme *icon_theme) |
788 | { |
789 | CtkIconThemePrivate *priv = icon_theme->priv; |
790 | |
791 | if (!priv->theme_changed_idle) |
792 | { |
793 | priv->theme_changed_idle = |
794 | cdk_threads_add_idle_full (CTK_PRIORITY_RESIZE(100 + 10) - 2, |
795 | theme_changed_idle, icon_theme, NULL((void*)0)); |
796 | g_source_set_name_by_id (priv->theme_changed_idle, "[ctk+] theme_changed_idle"); |
797 | } |
798 | } |
799 | |
800 | static void |
801 | do_theme_change (CtkIconTheme *icon_theme) |
802 | { |
803 | CtkIconThemePrivate *priv = icon_theme->priv; |
804 | |
805 | g_hash_table_remove_all (priv->info_cache); |
806 | |
807 | if (!priv->themes_valid) |
808 | return; |
809 | |
810 | CTK_NOTE (ICONTHEME,do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { g_message ("change to icon theme \"%s\"", priv->current_theme ); }; } while (0) |
811 | g_message ("change to icon theme \"%s\"", priv->current_theme))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { g_message ("change to icon theme \"%s\"", priv->current_theme ); }; } while (0); |
812 | blow_themes (icon_theme); |
813 | |
814 | queue_theme_changed (icon_theme); |
815 | |
816 | } |
817 | |
818 | static void |
819 | blow_themes (CtkIconTheme *icon_theme) |
820 | { |
821 | CtkIconThemePrivate *priv = icon_theme->priv; |
822 | |
823 | if (priv->themes_valid) |
824 | { |
825 | g_list_free_full (priv->themes, (GDestroyNotify) theme_destroy); |
826 | g_list_free_full (priv->dir_mtimes, (GDestroyNotify) free_dir_mtime); |
827 | g_hash_table_destroy (priv->unthemed_icons); |
828 | } |
829 | priv->themes = NULL((void*)0); |
830 | priv->unthemed_icons = NULL((void*)0); |
831 | priv->dir_mtimes = NULL((void*)0); |
832 | priv->themes_valid = FALSE(0); |
833 | } |
834 | |
835 | static void |
836 | ctk_icon_theme_finalize (GObject *object) |
837 | { |
838 | CtkIconTheme *icon_theme; |
839 | CtkIconThemePrivate *priv; |
840 | int i; |
841 | |
842 | icon_theme = CTK_ICON_THEME (object)((((CtkIconTheme*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((ctk_icon_theme_get_type ())))))); |
843 | priv = icon_theme->priv; |
844 | |
845 | g_hash_table_destroy (priv->info_cache); |
846 | g_assert (priv->info_cache_lru == NULL)do { if (priv->info_cache_lru == ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkicontheme.c", 846, ((const char*) (__func__)), "priv->info_cache_lru == NULL" ); } while (0); |
847 | |
848 | if (priv->theme_changed_idle) |
849 | g_source_remove (priv->theme_changed_idle); |
850 | |
851 | unset_screen (icon_theme); |
852 | |
853 | g_free (priv->current_theme); |
854 | |
855 | for (i = 0; i < priv->search_path_len; i++) |
856 | g_free (priv->search_path[i]); |
857 | g_free (priv->search_path); |
858 | |
859 | g_list_free_full (priv->resource_paths, g_free); |
860 | |
861 | blow_themes (icon_theme); |
862 | |
863 | G_OBJECT_CLASS (ctk_icon_theme_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_icon_theme_parent_class)), (((GType) ((20) << ( 2))))))))->finalize (object); |
864 | } |
865 | |
866 | /** |
867 | * ctk_icon_theme_set_search_path: |
868 | * @icon_theme: a #CtkIconTheme |
869 | * @path: (array length=n_elements) (element-type filename): array of |
870 | * directories that are searched for icon themes |
871 | * @n_elements: number of elements in @path. |
872 | * |
873 | * Sets the search path for the icon theme object. When looking |
874 | * for an icon theme, CTK+ will search for a subdirectory of |
875 | * one or more of the directories in @path with the same name |
876 | * as the icon theme containing an index.theme file. (Themes from |
877 | * multiple of the path elements are combined to allow themes to be |
878 | * extended by adding icons in the user’s home directory.) |
879 | * |
880 | * In addition if an icon found isn’t found either in the current |
881 | * icon theme or the default icon theme, and an image file with |
882 | * the right name is found directly in one of the elements of |
883 | * @path, then that image will be used for the icon name. |
884 | * (This is legacy feature, and new icons should be put |
885 | * into the fallback icon theme, which is called hicolor, |
886 | * rather than directly on the icon path.) |
887 | * |
888 | * Since: 2.4 |
889 | */ |
890 | void |
891 | ctk_icon_theme_set_search_path (CtkIconTheme *icon_theme, |
892 | const gchar *path[], |
893 | gint n_elements) |
894 | { |
895 | CtkIconThemePrivate *priv; |
896 | gint i; |
897 | |
898 | g_return_if_fail (CTK_IS_ICON_THEME (icon_theme))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return; } } while (0); |
899 | |
900 | priv = icon_theme->priv; |
901 | for (i = 0; i < priv->search_path_len; i++) |
902 | g_free (priv->search_path[i]); |
903 | |
904 | g_free (priv->search_path); |
905 | |
906 | priv->search_path = g_new (gchar *, n_elements)((gchar * *) g_malloc_n ((n_elements), sizeof (gchar *))); |
907 | priv->search_path_len = n_elements; |
908 | |
909 | for (i = 0; i < priv->search_path_len; i++) |
910 | priv->search_path[i] = g_strdup (path[i])g_strdup_inline (path[i]); |
911 | |
912 | do_theme_change (icon_theme); |
913 | } |
914 | |
915 | /** |
916 | * ctk_icon_theme_get_search_path: |
917 | * @icon_theme: a #CtkIconTheme |
918 | * @path: (allow-none) (array length=n_elements) (element-type filename) (out): |
919 | * location to store a list of icon theme path directories or %NULL. |
920 | * The stored value should be freed with g_strfreev(). |
921 | * @n_elements: location to store number of elements in @path, or %NULL |
922 | * |
923 | * Gets the current search path. See ctk_icon_theme_set_search_path(). |
924 | * |
925 | * Since: 2.4 |
926 | */ |
927 | void |
928 | ctk_icon_theme_get_search_path (CtkIconTheme *icon_theme, |
929 | gchar **path[], |
930 | gint *n_elements) |
931 | { |
932 | CtkIconThemePrivate *priv; |
933 | gint i; |
934 | |
935 | g_return_if_fail (CTK_IS_ICON_THEME (icon_theme))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return; } } while (0); |
936 | |
937 | priv = icon_theme->priv; |
938 | |
939 | if (n_elements) |
940 | *n_elements = priv->search_path_len; |
941 | |
942 | if (path) |
943 | { |
944 | *path = g_new (gchar *, priv->search_path_len + 1)((gchar * *) g_malloc_n ((priv->search_path_len + 1), sizeof (gchar *))); |
945 | for (i = 0; i < priv->search_path_len; i++) |
946 | (*path)[i] = g_strdup (priv->search_path[i])g_strdup_inline (priv->search_path[i]); |
947 | (*path)[i] = NULL((void*)0); |
948 | } |
949 | } |
950 | |
951 | /** |
952 | * ctk_icon_theme_append_search_path: |
953 | * @icon_theme: a #CtkIconTheme |
954 | * @path: (type filename): directory name to append to the icon path |
955 | * |
956 | * Appends a directory to the search path. |
957 | * See ctk_icon_theme_set_search_path(). |
958 | * |
959 | * Since: 2.4 |
960 | */ |
961 | void |
962 | ctk_icon_theme_append_search_path (CtkIconTheme *icon_theme, |
963 | const gchar *path) |
964 | { |
965 | CtkIconThemePrivate *priv; |
966 | |
967 | g_return_if_fail (CTK_IS_ICON_THEME (icon_theme))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return; } } while (0); |
968 | g_return_if_fail (path != NULL)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "path != NULL"); return; } } while (0); |
969 | |
970 | priv = icon_theme->priv; |
971 | |
972 | priv->search_path_len++; |
973 | |
974 | priv->search_path = g_renew (gchar *, priv->search_path, priv->search_path_len)((gchar * *) g_realloc_n (priv->search_path, (priv->search_path_len ), sizeof (gchar *))); |
975 | priv->search_path[priv->search_path_len-1] = g_strdup (path)g_strdup_inline (path); |
976 | |
977 | do_theme_change (icon_theme); |
978 | } |
979 | |
980 | /** |
981 | * ctk_icon_theme_prepend_search_path: |
982 | * @icon_theme: a #CtkIconTheme |
983 | * @path: (type filename): directory name to prepend to the icon path |
984 | * |
985 | * Prepends a directory to the search path. |
986 | * See ctk_icon_theme_set_search_path(). |
987 | * |
988 | * Since: 2.4 |
989 | */ |
990 | void |
991 | ctk_icon_theme_prepend_search_path (CtkIconTheme *icon_theme, |
992 | const gchar *path) |
993 | { |
994 | CtkIconThemePrivate *priv; |
995 | gint i; |
996 | |
997 | g_return_if_fail (CTK_IS_ICON_THEME (icon_theme))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return; } } while (0); |
998 | g_return_if_fail (path != NULL)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "path != NULL"); return; } } while (0); |
999 | |
1000 | priv = icon_theme->priv; |
1001 | |
1002 | priv->search_path_len++; |
1003 | priv->search_path = g_renew (gchar *, priv->search_path, priv->search_path_len)((gchar * *) g_realloc_n (priv->search_path, (priv->search_path_len ), sizeof (gchar *))); |
1004 | |
1005 | for (i = priv->search_path_len - 1; i > 0; i--) |
1006 | priv->search_path[i] = priv->search_path[i - 1]; |
1007 | |
1008 | priv->search_path[0] = g_strdup (path)g_strdup_inline (path); |
1009 | |
1010 | do_theme_change (icon_theme); |
1011 | } |
1012 | |
1013 | /** |
1014 | * ctk_icon_theme_add_resource_path: |
1015 | * @icon_theme: a #CtkIconTheme |
1016 | * @path: a resource path |
1017 | * |
1018 | * Adds a resource path that will be looked at when looking |
1019 | * for icons, similar to search paths. |
1020 | * |
1021 | * This function should be used to make application-specific icons |
1022 | * available as part of the icon theme. |
1023 | * |
1024 | * The resources are considered as part of the hicolor icon theme |
1025 | * and must be located in subdirectories that are defined in the |
1026 | * hicolor icon theme, such as `@path/16x16/actions/run.png`. |
1027 | * Icons that are directly placed in the resource path instead |
1028 | * of a subdirectory are also considered as ultimate fallback. |
1029 | * |
1030 | * Since: 3.14 |
1031 | */ |
1032 | void |
1033 | ctk_icon_theme_add_resource_path (CtkIconTheme *icon_theme, |
1034 | const gchar *path) |
1035 | { |
1036 | CtkIconThemePrivate *priv = NULL((void*)0); |
1037 | |
1038 | g_return_if_fail (CTK_IS_ICON_THEME (icon_theme))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return; } } while (0); |
1039 | g_return_if_fail (path != NULL)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "path != NULL"); return; } } while (0); |
1040 | |
1041 | priv = icon_theme->priv; |
1042 | priv->resource_paths = g_list_append (priv->resource_paths, g_strdup (path)g_strdup_inline (path)); |
1043 | |
1044 | do_theme_change (icon_theme); |
1045 | } |
1046 | |
1047 | /** |
1048 | * ctk_icon_theme_set_custom_theme: |
1049 | * @icon_theme: a #CtkIconTheme |
1050 | * @theme_name: (allow-none): name of icon theme to use instead of |
1051 | * configured theme, or %NULL to unset a previously set custom theme |
1052 | * |
1053 | * Sets the name of the icon theme that the #CtkIconTheme object uses |
1054 | * overriding system configuration. This function cannot be called |
1055 | * on the icon theme objects returned from ctk_icon_theme_get_default() |
1056 | * and ctk_icon_theme_get_for_screen(). |
1057 | * |
1058 | * Since: 2.4 |
1059 | */ |
1060 | void |
1061 | ctk_icon_theme_set_custom_theme (CtkIconTheme *icon_theme, |
1062 | const gchar *theme_name) |
1063 | { |
1064 | CtkIconThemePrivate *priv; |
1065 | |
1066 | g_return_if_fail (CTK_IS_ICON_THEME (icon_theme))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return; } } while (0); |
1067 | |
1068 | priv = icon_theme->priv; |
1069 | |
1070 | g_return_if_fail (!priv->is_screen_singleton)do { if ((!priv->is_screen_singleton)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "!priv->is_screen_singleton" ); return; } } while (0); |
1071 | |
1072 | if (theme_name != NULL((void*)0)) |
1073 | { |
1074 | priv->custom_theme = TRUE(!(0)); |
1075 | if (!priv->current_theme || strcmp (theme_name, priv->current_theme) != 0) |
1076 | { |
1077 | g_free (priv->current_theme); |
1078 | priv->current_theme = g_strdup (theme_name)g_strdup_inline (theme_name); |
1079 | |
1080 | do_theme_change (icon_theme); |
1081 | } |
1082 | } |
1083 | else |
1084 | { |
1085 | if (priv->custom_theme) |
1086 | { |
1087 | priv->custom_theme = FALSE(0); |
1088 | update_current_theme (icon_theme); |
1089 | } |
1090 | } |
1091 | } |
1092 | |
1093 | static const gchar builtin_hicolor_index[] = |
1094 | "[Icon Theme]\n" |
1095 | "Name=Hicolor\n" |
1096 | "Hidden=True\n" |
1097 | "Directories=16x16/actions,16x16/status,22x22/actions,24x24/actions,24x24/status,32x32/actions,32x32/status,48x48/status,64x64/actions\n" |
1098 | "[16x16/actions]\n" |
1099 | "Size=16\n" |
1100 | "Type=Threshold\n" |
1101 | "[16x16/status]\n" |
1102 | "Size=16\n" |
1103 | "Type=Threshold\n" |
1104 | "[22x22/actions]\n" |
1105 | "Size=22\n" |
1106 | "Type=Threshold\n" |
1107 | "[24x24/actions]\n" |
1108 | "Size=24\n" |
1109 | "Type=Threshold\n" |
1110 | "[24x24/status]\n" |
1111 | "Size=24\n" |
1112 | "Type=Threshold\n" |
1113 | "[32x32/actions]\n" |
1114 | "Size=32\n" |
1115 | "Type=Threshold\n" |
1116 | "[32x32/status]\n" |
1117 | "Size=32\n" |
1118 | "Type=Threshold\n" |
1119 | "[48x48/status]\n" |
1120 | "Size=48\n" |
1121 | "Type=Threshold\n" |
1122 | "[64x64/actions]\n" |
1123 | "Size=64\n" |
1124 | "Type=Threshold\n"; |
1125 | |
1126 | static void |
1127 | insert_theme (CtkIconTheme *icon_theme, |
1128 | const gchar *theme_name) |
1129 | { |
1130 | gint i; |
1131 | GList *l; |
1132 | gchar **dirs; |
1133 | gchar **scaled_dirs; |
1134 | gchar **themes; |
1135 | CtkIconThemePrivate *priv; |
1136 | IconTheme *theme = NULL((void*)0); |
1137 | gchar *path; |
1138 | GKeyFile *theme_file; |
1139 | GError *error = NULL((void*)0); |
1140 | IconThemeDirMtime *dir_mtime; |
1141 | GStatBuf stat_buf; |
1142 | |
1143 | priv = icon_theme->priv; |
1144 | |
1145 | for (l = priv->themes; l != NULL((void*)0); l = l->next) |
1146 | { |
1147 | theme = l->data; |
1148 | if (strcmp (theme->name, theme_name) == 0) |
1149 | return; |
1150 | } |
1151 | |
1152 | for (i = 0; i < priv->search_path_len; i++) |
1153 | { |
1154 | path = g_build_filename (priv->search_path[i], |
1155 | theme_name, |
1156 | NULL((void*)0)); |
1157 | dir_mtime = g_slice_new (IconThemeDirMtime)((IconThemeDirMtime*) g_slice_alloc (sizeof (IconThemeDirMtime ))); |
1158 | dir_mtime->cache = NULL((void*)0); |
1159 | dir_mtime->dir = path; |
1160 | if (g_statstat (path, &stat_buf) == 0 && S_ISDIR (stat_buf.st_mode)((((stat_buf.st_mode)) & 0170000) == (0040000))) { |
1161 | dir_mtime->mtime = stat_buf.st_mtimest_mtim.tv_sec; |
1162 | dir_mtime->exists = TRUE(!(0)); |
1163 | } else { |
1164 | dir_mtime->mtime = 0; |
1165 | dir_mtime->exists = FALSE(0); |
1166 | } |
1167 | |
1168 | priv->dir_mtimes = g_list_prepend (priv->dir_mtimes, dir_mtime); |
1169 | } |
1170 | |
1171 | theme_file = NULL((void*)0); |
1172 | for (i = 0; i < priv->search_path_len && !theme_file; i++) |
1173 | { |
1174 | path = g_build_filename (priv->search_path[i], |
1175 | theme_name, |
1176 | "index.theme", |
1177 | NULL((void*)0)); |
1178 | if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) |
1179 | { |
1180 | theme_file = g_key_file_new (); |
1181 | g_key_file_set_list_separator (theme_file, ','); |
1182 | if (!g_key_file_load_from_file (theme_file, path, 0, &error)) |
1183 | { |
1184 | g_key_file_free (theme_file); |
1185 | theme_file = NULL((void*)0); |
1186 | g_error_free (error); |
1187 | error = NULL((void*)0); |
1188 | } |
1189 | } |
1190 | g_free (path); |
1191 | } |
1192 | |
1193 | if (theme_file || strcmp (theme_name, FALLBACK_ICON_THEME"hicolor") == 0) |
1194 | { |
1195 | theme = g_new0 (IconTheme, 1)((IconTheme *) g_malloc0_n ((1), sizeof (IconTheme))); |
1196 | theme->name = g_strdup (theme_name)g_strdup_inline (theme_name); |
1197 | priv->themes = g_list_prepend (priv->themes, theme); |
1198 | if (!theme_file) |
1199 | { |
1200 | theme_file = g_key_file_new (); |
1201 | g_key_file_set_list_separator (theme_file, ','); |
1202 | g_key_file_load_from_data (theme_file, builtin_hicolor_index, -1, 0, NULL((void*)0)); |
1203 | } |
1204 | } |
1205 | |
1206 | if (theme_file == NULL((void*)0)) |
1207 | return; |
1208 | |
1209 | theme->display_name = |
1210 | g_key_file_get_locale_string (theme_file, "Icon Theme", "Name", NULL((void*)0), NULL((void*)0)); |
1211 | if (!theme->display_name) |
1212 | g_warning ("Theme file for %s has no name", theme_name); |
1213 | |
1214 | dirs = g_key_file_get_string_list (theme_file, "Icon Theme", "Directories", NULL((void*)0), NULL((void*)0)); |
1215 | if (!dirs) |
1216 | { |
1217 | g_warning ("Theme file for %s has no directories", theme_name); |
1218 | priv->themes = g_list_remove (priv->themes, theme); |
1219 | g_free (theme->name); |
1220 | g_free (theme->display_name); |
1221 | g_free (theme); |
1222 | g_key_file_free (theme_file); |
1223 | return; |
1224 | } |
1225 | |
1226 | scaled_dirs = g_key_file_get_string_list (theme_file, "Icon Theme", "ScaledDirectories", NULL((void*)0), NULL((void*)0)); |
1227 | |
1228 | theme->comment = |
1229 | g_key_file_get_locale_string (theme_file, |
1230 | "Icon Theme", "Comment", |
1231 | NULL((void*)0), NULL((void*)0)); |
1232 | theme->example = |
1233 | g_key_file_get_string (theme_file, |
1234 | "Icon Theme", "Example", |
1235 | NULL((void*)0)); |
1236 | |
1237 | theme->dirs = NULL((void*)0); |
1238 | for (i = 0; dirs[i] != NULL((void*)0); i++) |
1239 | theme_subdir_load (icon_theme, theme, theme_file, dirs[i]); |
1240 | |
1241 | if (scaled_dirs) |
1242 | { |
1243 | for (i = 0; scaled_dirs[i] != NULL((void*)0); i++) |
1244 | theme_subdir_load (icon_theme, theme, theme_file, scaled_dirs[i]); |
1245 | } |
1246 | g_strfreev (dirs); |
1247 | g_strfreev (scaled_dirs); |
1248 | |
1249 | theme->dirs = g_list_reverse (theme->dirs); |
1250 | |
1251 | themes = g_key_file_get_string_list (theme_file, |
1252 | "Icon Theme", |
1253 | "Inherits", |
1254 | NULL((void*)0), |
1255 | NULL((void*)0)); |
1256 | if (themes) |
1257 | { |
1258 | for (i = 0; themes[i] != NULL((void*)0); i++) |
1259 | insert_theme (icon_theme, themes[i]); |
1260 | |
1261 | g_strfreev (themes); |
1262 | } |
1263 | |
1264 | g_key_file_free (theme_file); |
1265 | } |
1266 | |
1267 | static void |
1268 | free_unthemed_icon (UnthemedIcon *unthemed_icon) |
1269 | { |
1270 | g_free (unthemed_icon->svg_filename); |
1271 | g_free (unthemed_icon->no_svg_filename); |
1272 | g_slice_free (UnthemedIcon, unthemed_icon)do { if (1) g_slice_free1 (sizeof (UnthemedIcon), (unthemed_icon )); else (void) ((UnthemedIcon*) 0 == (unthemed_icon)); } while (0); |
1273 | } |
1274 | |
1275 | static gchar * |
1276 | strip_suffix (const gchar *filename) |
1277 | { |
1278 | const gchar *dot; |
1279 | |
1280 | if (g_str_has_suffix (filename, ".symbolic.png")(__builtin_constant_p (".symbolic.png")? __extension__ ({ const char * const __str = (filename); const char * const __suffix = (".symbolic.png"); gboolean __result = (0); if (__str == ( (void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix ) (__str, __suffix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __suffix_len = strlen ((( __suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (filename, ".symbolic.png") )) |
1281 | return g_strndup (filename, strlen(filename)-13); |
1282 | |
1283 | dot = strrchr (filename, '.'); |
1284 | |
1285 | if (dot == NULL((void*)0)) |
1286 | return g_strdup (filename)g_strdup_inline (filename); |
1287 | |
1288 | return g_strndup (filename, dot - filename); |
1289 | } |
1290 | |
1291 | static void |
1292 | add_unthemed_icon (CtkIconTheme *icon_theme, |
1293 | const gchar *dir, |
1294 | const gchar *file, |
1295 | gboolean is_resource) |
1296 | { |
1297 | CtkIconThemePrivate *priv = icon_theme->priv; |
1298 | IconSuffix new_suffix, old_suffix; |
1299 | gchar *abs_file; |
1300 | gchar *base_name; |
1301 | UnthemedIcon *unthemed_icon; |
1302 | |
1303 | new_suffix = suffix_from_name (file); |
1304 | |
1305 | if (new_suffix == ICON_SUFFIX_NONE) |
1306 | return; |
1307 | |
1308 | abs_file = g_build_filename (dir, file, NULL((void*)0)); |
1309 | base_name = strip_suffix (file); |
1310 | |
1311 | unthemed_icon = g_hash_table_lookup (priv->unthemed_icons, base_name); |
1312 | |
1313 | if (unthemed_icon) |
1314 | { |
1315 | if (new_suffix == ICON_SUFFIX_SVG) |
1316 | { |
1317 | if (unthemed_icon->svg_filename) |
1318 | g_free (abs_file); |
1319 | else |
1320 | unthemed_icon->svg_filename = abs_file; |
1321 | } |
1322 | else |
1323 | { |
1324 | if (unthemed_icon->no_svg_filename) |
1325 | { |
1326 | old_suffix = suffix_from_name (unthemed_icon->no_svg_filename); |
1327 | if (new_suffix > old_suffix) |
1328 | { |
1329 | g_free (unthemed_icon->no_svg_filename); |
1330 | unthemed_icon->no_svg_filename = abs_file; |
1331 | } |
1332 | else |
1333 | g_free (abs_file); |
1334 | } |
1335 | else |
1336 | unthemed_icon->no_svg_filename = abs_file; |
1337 | } |
1338 | |
1339 | g_free (base_name); |
1340 | } |
1341 | else |
1342 | { |
1343 | unthemed_icon = g_slice_new0 (UnthemedIcon)((UnthemedIcon*) g_slice_alloc0 (sizeof (UnthemedIcon))); |
1344 | |
1345 | unthemed_icon->is_resource = is_resource; |
1346 | |
1347 | if (new_suffix == ICON_SUFFIX_SVG) |
1348 | unthemed_icon->svg_filename = abs_file; |
1349 | else |
1350 | unthemed_icon->no_svg_filename = abs_file; |
1351 | |
1352 | /* takes ownership of base_name */ |
1353 | g_hash_table_replace (priv->unthemed_icons, base_name, unthemed_icon); |
1354 | } |
1355 | } |
1356 | |
1357 | static void |
1358 | load_themes (CtkIconTheme *icon_theme) |
1359 | { |
1360 | CtkIconThemePrivate *priv; |
1361 | GDir *gdir; |
1362 | gint base; |
1363 | gchar *dir; |
1364 | const gchar *file; |
1365 | IconThemeDirMtime *dir_mtime; |
1366 | GStatBuf stat_buf; |
1367 | GList *d; |
1368 | |
1369 | priv = icon_theme->priv; |
1370 | |
1371 | if (priv->current_theme) |
1372 | insert_theme (icon_theme, priv->current_theme); |
1373 | |
1374 | /* Always look in the Advaita, gnome and hicolor icon themes. |
1375 | * Looking in hicolor is mandated by the spec, looking in Advaita |
1376 | * and gnome is a pragmatic solution to prevent missing icons in |
1377 | * CTK+ applications when run under, e.g. KDE. |
1378 | */ |
1379 | insert_theme (icon_theme, DEFAULT_ICON_THEME"Advaita"); |
1380 | insert_theme (icon_theme, "gnome"); |
1381 | insert_theme (icon_theme, FALLBACK_ICON_THEME"hicolor"); |
1382 | priv->themes = g_list_reverse (priv->themes); |
1383 | |
1384 | |
1385 | priv->unthemed_icons = g_hash_table_new_full (g_str_hash, g_str_equal, |
1386 | g_free, (GDestroyNotify)free_unthemed_icon); |
1387 | |
1388 | for (base = 0; base < icon_theme->priv->search_path_len; base++) |
1389 | { |
1390 | dir = icon_theme->priv->search_path[base]; |
1391 | |
1392 | dir_mtime = g_slice_new (IconThemeDirMtime)((IconThemeDirMtime*) g_slice_alloc (sizeof (IconThemeDirMtime ))); |
1393 | priv->dir_mtimes = g_list_prepend (priv->dir_mtimes, dir_mtime); |
1394 | |
1395 | dir_mtime->dir = g_strdup (dir)g_strdup_inline (dir); |
1396 | dir_mtime->mtime = 0; |
1397 | dir_mtime->exists = FALSE(0); |
1398 | dir_mtime->cache = NULL((void*)0); |
1399 | |
1400 | if (g_statstat (dir, &stat_buf) != 0 || !S_ISDIR (stat_buf.st_mode)((((stat_buf.st_mode)) & 0170000) == (0040000))) |
1401 | continue; |
1402 | dir_mtime->mtime = stat_buf.st_mtimest_mtim.tv_sec; |
1403 | dir_mtime->exists = TRUE(!(0)); |
1404 | |
1405 | dir_mtime->cache = _ctk_icon_cache_new_for_path (dir); |
1406 | if (dir_mtime->cache != NULL((void*)0)) |
1407 | continue; |
1408 | |
1409 | gdir = g_dir_open (dir, 0, NULL((void*)0)); |
1410 | if (gdir == NULL((void*)0)) |
1411 | continue; |
1412 | |
1413 | while ((file = g_dir_read_name (gdir))) |
1414 | add_unthemed_icon (icon_theme, dir, file, FALSE(0)); |
1415 | |
1416 | g_dir_close (gdir); |
1417 | } |
1418 | priv->dir_mtimes = g_list_reverse (priv->dir_mtimes); |
1419 | |
1420 | for (d = priv->resource_paths; d; d = d->next) |
1421 | { |
1422 | gchar **children; |
1423 | gint i; |
1424 | |
1425 | dir = d->data; |
1426 | children = g_resources_enumerate_children (dir, 0, NULL((void*)0)); |
1427 | if (!children) |
1428 | continue; |
1429 | |
1430 | for (i = 0; children[i]; i++) |
1431 | add_unthemed_icon (icon_theme, dir, children[i], TRUE(!(0))); |
1432 | |
1433 | g_strfreev (children); |
1434 | } |
1435 | |
1436 | priv->themes_valid = TRUE(!(0)); |
1437 | |
1438 | priv->last_stat_time = g_get_monotonic_time (); |
1439 | |
1440 | CTK_NOTE (ICONTHEME, {do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1441 | GList *l;do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1442 | GString *s;do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1443 | s = g_string_new ("Current icon themes ");do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1444 | for (l = icon_theme->priv->themes; l; l = l->next)do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1445 | {do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1446 | IconTheme *theme = l->data;do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1447 | g_string_append (s, theme->name);do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1448 | g_string_append_c (s, ' ');do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1449 | }do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1450 | g_message ("%s", s->str);do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1451 | g_string_free (s, TRUE);do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0) |
1452 | })do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { { GList *l; GString *s; s = g_string_new ("Current icon themes " ); for (l = icon_theme->priv->themes; l; l = l->next ) { IconTheme *theme = l->data; (__builtin_constant_p (theme ->name) ? __extension__ ({ const char * const __val = (theme ->name); g_string_append_len_inline (s, __val, (__val != ( (void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (s, theme->name, (gssize ) -1)); g_string_append_c_inline (s, ' '); } g_message ("%s", s->str); (__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free ) ((s), ((!(0)))) : g_string_free_and_steal (s)) : (g_string_free ) ((s), ((!(0))))); }; }; } while (0); |
1453 | } |
1454 | |
1455 | static void |
1456 | ensure_valid_themes (CtkIconTheme *icon_theme) |
1457 | { |
1458 | CtkIconThemePrivate *priv = icon_theme->priv; |
1459 | gboolean was_valid = priv->themes_valid; |
1460 | |
1461 | if (priv->loading_themes) |
1462 | return; |
1463 | priv->loading_themes = TRUE(!(0)); |
1464 | |
1465 | if (priv->themes_valid) |
1466 | { |
1467 | gint64 now = g_get_monotonic_time (); |
1468 | |
1469 | if ((now - priv->last_stat_time) / G_USEC_PER_SEC1000000 > 5 && |
1470 | rescan_themes (icon_theme)) |
1471 | { |
1472 | g_hash_table_remove_all (priv->info_cache); |
1473 | blow_themes (icon_theme); |
1474 | } |
1475 | } |
1476 | |
1477 | if (!priv->themes_valid) |
1478 | { |
1479 | load_themes (icon_theme); |
1480 | |
1481 | if (was_valid) |
1482 | queue_theme_changed (icon_theme); |
1483 | } |
1484 | |
1485 | priv->loading_themes = FALSE(0); |
1486 | } |
1487 | |
1488 | /* The LRU cache is a short list of IconInfos that are kept |
1489 | * alive even though their IconInfo would otherwise have |
1490 | * been freed, so that we can avoid reloading these |
1491 | * constantly. |
1492 | * We put infos on the lru list when nothing otherwise |
1493 | * references the info. So, when we get a cache hit |
1494 | * we remove it from the list, and when the proxy |
1495 | * pixmap is released we put it on the list. |
1496 | */ |
1497 | static void |
1498 | ensure_lru_cache_space (CtkIconTheme *icon_theme) |
1499 | { |
1500 | CtkIconThemePrivate *priv = icon_theme->priv; |
1501 | GList *l; |
1502 | |
1503 | /* Remove last item if LRU full */ |
1504 | l = g_list_nth (priv->info_cache_lru, INFO_CACHE_LRU_SIZE32 - 1); |
1505 | if (l) |
1506 | { |
1507 | CtkIconInfo *icon_info = l->data; |
1508 | |
1509 | DEBUG_CACHE (("removing (due to out of space) %p (%s %d 0x%x) from LRU cache (cache size %d)\n", |
1510 | icon_info, |
1511 | g_strjoinv (",", icon_info->key.icon_names), |
1512 | icon_info->key.size, icon_info->key.flags, |
1513 | g_list_length (priv->info_cache_lru))); |
1514 | |
1515 | priv->info_cache_lru = g_list_delete_link (priv->info_cache_lru, l); |
1516 | g_object_unref (icon_info); |
1517 | } |
1518 | } |
1519 | |
1520 | static void |
1521 | add_to_lru_cache (CtkIconTheme *icon_theme, |
1522 | CtkIconInfo *icon_info) |
1523 | { |
1524 | CtkIconThemePrivate *priv = icon_theme->priv; |
1525 | |
1526 | DEBUG_CACHE (("adding %p (%s %d 0x%x) to LRU cache (cache size %d)\n", |
1527 | icon_info, |
1528 | g_strjoinv (",", icon_info->key.icon_names), |
1529 | icon_info->key.size, icon_info->key.flags, |
1530 | g_list_length (priv->info_cache_lru))); |
1531 | |
1532 | g_assert (g_list_find (priv->info_cache_lru, icon_info) == NULL)do { if (g_list_find (priv->info_cache_lru, icon_info) == ( (void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkicontheme.c" , 1532, ((const char*) (__func__)), "g_list_find (priv->info_cache_lru, icon_info) == NULL" ); } while (0); |
1533 | |
1534 | ensure_lru_cache_space (icon_theme); |
1535 | /* prepend new info to LRU */ |
1536 | priv->info_cache_lru = g_list_prepend (priv->info_cache_lru, |
1537 | g_object_ref (icon_info)((__typeof__ (icon_info)) (g_object_ref) (icon_info))); |
1538 | } |
1539 | |
1540 | static void |
1541 | ensure_in_lru_cache (CtkIconTheme *icon_theme, |
1542 | CtkIconInfo *icon_info) |
1543 | { |
1544 | CtkIconThemePrivate *priv = icon_theme->priv; |
1545 | GList *l; |
1546 | |
1547 | l = g_list_find (priv->info_cache_lru, icon_info); |
1548 | if (l) |
1549 | { |
1550 | /* Move to front of LRU if already in it */ |
1551 | priv->info_cache_lru = g_list_remove_link (priv->info_cache_lru, l); |
1552 | priv->info_cache_lru = g_list_concat (l, priv->info_cache_lru); |
1553 | } |
1554 | else |
1555 | add_to_lru_cache (icon_theme, icon_info); |
1556 | } |
1557 | |
1558 | static void |
1559 | remove_from_lru_cache (CtkIconTheme *icon_theme, |
1560 | CtkIconInfo *icon_info) |
1561 | { |
1562 | CtkIconThemePrivate *priv = icon_theme->priv; |
1563 | if (g_list_find (priv->info_cache_lru, icon_info)) |
1564 | { |
1565 | DEBUG_CACHE (("removing %p (%s %d 0x%x) from LRU cache (cache size %d)\n", |
1566 | icon_info, |
1567 | g_strjoinv (",", icon_info->key.icon_names), |
1568 | icon_info->key.size, icon_info->key.flags, |
1569 | g_list_length (priv->info_cache_lru))); |
1570 | |
1571 | priv->info_cache_lru = g_list_remove (priv->info_cache_lru, icon_info); |
1572 | g_object_unref (icon_info); |
1573 | } |
1574 | } |
1575 | |
1576 | static SymbolicPixbufCache * |
1577 | symbolic_pixbuf_cache_new (GdkPixbuf *pixbuf, |
1578 | const CdkRGBA *fg, |
1579 | const CdkRGBA *success_color, |
1580 | const CdkRGBA *warning_color, |
1581 | const CdkRGBA *error_color, |
1582 | SymbolicPixbufCache *next) |
1583 | { |
1584 | SymbolicPixbufCache *cache; |
1585 | |
1586 | cache = g_new0 (SymbolicPixbufCache, 1)((SymbolicPixbufCache *) g_malloc0_n ((1), sizeof (SymbolicPixbufCache ))); |
1587 | cache->pixbuf = g_object_ref (pixbuf)((__typeof__ (pixbuf)) (g_object_ref) (pixbuf)); |
1588 | if (fg) |
1589 | cache->fg = *fg; |
1590 | if (success_color) |
1591 | cache->success_color = *success_color; |
1592 | if (warning_color) |
1593 | cache->warning_color = *warning_color; |
1594 | if (error_color) |
1595 | cache->error_color = *error_color; |
1596 | cache->next = next; |
1597 | return cache; |
1598 | } |
1599 | |
1600 | static gboolean |
1601 | rgba_matches (const CdkRGBA *a, |
1602 | const CdkRGBA *b) |
1603 | { |
1604 | CdkRGBA transparent = { 0 }; |
1605 | |
1606 | /* For matching we treat unset colors as transparent rather |
1607 | than default, which works as well, because transparent |
1608 | will never be used for real symbolic icon colors */ |
1609 | if (a == NULL((void*)0)) |
1610 | a = &transparent; |
1611 | |
1612 | return |
1613 | fabs(a->red - b->red) < 0.0001 && |
1614 | fabs(a->green - b->green) < 0.0001 && |
1615 | fabs(a->blue - b->blue) < 0.0001 && |
1616 | fabs(a->alpha - b->alpha) < 0.0001; |
1617 | } |
1618 | |
1619 | static SymbolicPixbufCache * |
1620 | symbolic_pixbuf_cache_matches (SymbolicPixbufCache *cache, |
1621 | const CdkRGBA *fg, |
1622 | const CdkRGBA *success_color, |
1623 | const CdkRGBA *warning_color, |
1624 | const CdkRGBA *error_color) |
1625 | { |
1626 | while (cache != NULL((void*)0)) |
1627 | { |
1628 | if (rgba_matches (fg, &cache->fg) && |
1629 | rgba_matches (success_color, &cache->success_color) && |
1630 | rgba_matches (warning_color, &cache->warning_color) && |
1631 | rgba_matches (error_color, &cache->error_color)) |
1632 | return cache; |
1633 | |
1634 | cache = cache->next; |
1635 | } |
1636 | |
1637 | return NULL((void*)0); |
1638 | } |
1639 | |
1640 | static void |
1641 | symbolic_pixbuf_cache_free (SymbolicPixbufCache *cache) |
1642 | { |
1643 | SymbolicPixbufCache *next; |
1644 | |
1645 | while (cache != NULL((void*)0)) |
1646 | { |
1647 | next = cache->next; |
1648 | g_object_unref (cache->pixbuf); |
1649 | g_free (cache); |
1650 | |
1651 | cache = next; |
1652 | } |
1653 | } |
1654 | |
1655 | static gboolean |
1656 | icon_name_is_symbolic (const gchar *icon_name) |
1657 | { |
1658 | return g_str_has_suffix (icon_name, "-symbolic")(__builtin_constant_p ("-symbolic")? __extension__ ({ const char * const __str = (icon_name); const char * const __suffix = ( "-symbolic"); gboolean __result = (0); if (__str == ((void*)0 ) || __suffix == ((void*)0)) __result = (g_str_has_suffix) (__str , __suffix); else { const size_t __str_len = strlen (((__str) + !(__str))); const size_t __suffix_len = strlen (((__suffix ) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (icon_name, "-symbolic") ) |
1659 | || g_str_has_suffix (icon_name, "-symbolic-ltr")(__builtin_constant_p ("-symbolic-ltr")? __extension__ ({ const char * const __str = (icon_name); const char * const __suffix = ("-symbolic-ltr"); gboolean __result = (0); if (__str == ( (void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix ) (__str, __suffix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __suffix_len = strlen ((( __suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (icon_name, "-symbolic-ltr") ) |
1660 | || g_str_has_suffix (icon_name, "-symbolic-rtl")(__builtin_constant_p ("-symbolic-rtl")? __extension__ ({ const char * const __str = (icon_name); const char * const __suffix = ("-symbolic-rtl"); gboolean __result = (0); if (__str == ( (void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix ) (__str, __suffix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __suffix_len = strlen ((( __suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (icon_name, "-symbolic-rtl") ); |
1661 | } |
1662 | |
1663 | static gboolean |
1664 | icon_uri_is_symbolic (const gchar *icon_name) |
1665 | { |
1666 | return g_str_has_suffix (icon_name, "-symbolic.svg")(__builtin_constant_p ("-symbolic.svg")? __extension__ ({ const char * const __str = (icon_name); const char * const __suffix = ("-symbolic.svg"); gboolean __result = (0); if (__str == ( (void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix ) (__str, __suffix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __suffix_len = strlen ((( __suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (icon_name, "-symbolic.svg") ) |
1667 | || g_str_has_suffix (icon_name, "-symbolic-ltr.svg")(__builtin_constant_p ("-symbolic-ltr.svg")? __extension__ ({ const char * const __str = (icon_name); const char * const __suffix = ("-symbolic-ltr.svg"); gboolean __result = (0); if (__str == ((void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix ) (__str, __suffix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __suffix_len = strlen ((( __suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (icon_name, "-symbolic-ltr.svg") ) |
1668 | || g_str_has_suffix (icon_name, "-symbolic-rtl.svg")(__builtin_constant_p ("-symbolic-rtl.svg")? __extension__ ({ const char * const __str = (icon_name); const char * const __suffix = ("-symbolic-rtl.svg"); gboolean __result = (0); if (__str == ((void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix ) (__str, __suffix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __suffix_len = strlen ((( __suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (icon_name, "-symbolic-rtl.svg") ) |
1669 | || g_str_has_suffix (icon_name, ".symbolic.png")(__builtin_constant_p (".symbolic.png")? __extension__ ({ const char * const __str = (icon_name); const char * const __suffix = (".symbolic.png"); gboolean __result = (0); if (__str == ( (void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix ) (__str, __suffix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __suffix_len = strlen ((( __suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (icon_name, ".symbolic.png") ); |
1670 | } |
1671 | |
1672 | static CtkIconInfo * |
1673 | real_choose_icon (CtkIconTheme *icon_theme, |
1674 | const gchar *icon_names[], |
1675 | gint size, |
1676 | gint scale, |
1677 | CtkIconLookupFlags flags) |
1678 | { |
1679 | CtkIconThemePrivate *priv; |
1680 | GList *l; |
1681 | CtkIconInfo *icon_info = NULL((void*)0); |
1682 | CtkIconInfo *unscaled_icon_info; |
1683 | UnthemedIcon *unthemed_icon = NULL((void*)0); |
1684 | const gchar *icon_name = NULL((void*)0); |
1685 | gboolean allow_svg; |
1686 | gboolean use_builtin; |
1687 | IconTheme *theme = NULL((void*)0); |
1688 | gint i; |
1689 | IconInfoKey key; |
1690 | |
1691 | priv = icon_theme->priv; |
1692 | |
1693 | ensure_valid_themes (icon_theme); |
1694 | |
1695 | key.icon_names = (gchar **)icon_names; |
1696 | key.size = size; |
1697 | key.scale = scale; |
1698 | key.flags = flags; |
1699 | |
1700 | icon_info = g_hash_table_lookup (priv->info_cache, &key); |
1701 | if (icon_info != NULL((void*)0)) |
1702 | { |
1703 | DEBUG_CACHE (("cache hit %p (%s %d 0x%x) (cache size %d)\n", |
1704 | icon_info, |
1705 | g_strjoinv (",", icon_info->key.icon_names), |
1706 | icon_info->key.size, icon_info->key.flags, |
1707 | g_hash_table_size (priv->info_cache))); |
1708 | |
1709 | icon_info = g_object_ref (icon_info)((__typeof__ (icon_info)) (g_object_ref) (icon_info)); |
1710 | remove_from_lru_cache (icon_theme, icon_info); |
1711 | |
1712 | return icon_info; |
1713 | } |
1714 | |
1715 | if (flags & CTK_ICON_LOOKUP_NO_SVG) |
1716 | allow_svg = FALSE(0); |
1717 | else if (flags & CTK_ICON_LOOKUP_FORCE_SVG) |
1718 | allow_svg = TRUE(!(0)); |
1719 | else |
1720 | allow_svg = priv->pixbuf_supports_svg; |
1721 | |
1722 | use_builtin = flags & CTK_ICON_LOOKUP_USE_BUILTIN; |
1723 | |
1724 | /* This is used in the icontheme unit test */ |
1725 | CTK_NOTE (ICONTHEME,do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { for (i = 0; icon_names[i]; i++) g_message ("\tlookup name: %s" , icon_names[i]); }; } while (0) |
1726 | for (i = 0; icon_names[i]; i++)do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { for (i = 0; icon_names[i]; i++) g_message ("\tlookup name: %s" , icon_names[i]); }; } while (0) |
1727 | g_message ("\tlookup name: %s", icon_names[i]))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { for (i = 0; icon_names[i]; i++) g_message ("\tlookup name: %s" , icon_names[i]); }; } while (0); |
1728 | |
1729 | /* For symbolic icons, do a search in all registered themes first; |
1730 | * a theme that inherits them from a parent theme might provide |
1731 | * an alternative full-color version, but still expect the symbolic icon |
1732 | * to show up instead. |
1733 | * |
1734 | * In other words: We prefer symbolic icons in inherited themes over |
1735 | * generic icons in the theme. |
1736 | */ |
1737 | for (l = priv->themes; l; l = l->next) |
1738 | { |
1739 | theme = l->data; |
1740 | for (i = 0; icon_names[i] && icon_name_is_symbolic (icon_names[i]); i++) |
1741 | { |
1742 | icon_name = icon_names[i]; |
1743 | icon_info = theme_lookup_icon (theme, icon_name, size, scale, allow_svg, use_builtin); |
1744 | if (icon_info) |
1745 | goto out; |
1746 | } |
1747 | } |
1748 | |
1749 | for (l = priv->themes; l; l = l->next) |
1750 | { |
1751 | theme = l->data; |
1752 | |
1753 | for (i = 0; icon_names[i]; i++) |
1754 | { |
1755 | icon_name = icon_names[i]; |
1756 | icon_info = theme_lookup_icon (theme, icon_name, size, scale, allow_svg, use_builtin); |
1757 | if (icon_info) |
1758 | goto out; |
1759 | } |
1760 | } |
1761 | |
1762 | theme = NULL((void*)0); |
1763 | |
1764 | for (i = 0; icon_names[i]; i++) |
1765 | { |
1766 | unthemed_icon = g_hash_table_lookup (priv->unthemed_icons, icon_names[i]); |
1767 | if (unthemed_icon) |
1768 | break; |
1769 | } |
1770 | #ifdef G_OS_WIN32 |
1771 | /* Still not found an icon, check if reference to a Win32 resource */ |
1772 | if (!unthemed_icon) |
1773 | { |
1774 | gchar **resources; |
1775 | HICON hIcon = NULL((void*)0); |
1776 | |
1777 | resources = g_strsplit (icon_names[0], ",", 0); |
1778 | if (resources[0]) |
1779 | { |
1780 | wchar_t *wfile = g_utf8_to_utf16 (resources[0], -1, NULL((void*)0), NULL((void*)0), NULL((void*)0)); |
1781 | ExtractIconExW (wfile, resources[1] ? atoi (resources[1]) : 0, &hIcon, NULL((void*)0), 1); |
1782 | g_free (wfile); |
1783 | } |
1784 | |
1785 | if (hIcon) |
1786 | { |
1787 | icon_info = icon_info_new (ICON_THEME_DIR_UNTHEMED, size, 1); |
1788 | icon_info->cache_pixbuf = cdk_win32_icon_to_pixbuf_libctk_only (hIcon, NULL((void*)0), NULL((void*)0)); |
1789 | DestroyIcon (hIcon); |
1790 | } |
1791 | g_strfreev (resources); |
1792 | } |
1793 | #endif |
1794 | |
1795 | if (unthemed_icon) |
1796 | { |
1797 | icon_info = icon_info_new (ICON_THEME_DIR_UNTHEMED, size, 1); |
1798 | |
1799 | /* A SVG icon, when allowed, beats out a XPM icon, but not a PNG icon */ |
1800 | if (allow_svg && |
1801 | unthemed_icon->svg_filename && |
1802 | (!unthemed_icon->no_svg_filename || |
1803 | suffix_from_name (unthemed_icon->no_svg_filename) < ICON_SUFFIX_PNG)) |
1804 | icon_info->filename = g_strdup (unthemed_icon->svg_filename)g_strdup_inline (unthemed_icon->svg_filename); |
1805 | else if (unthemed_icon->no_svg_filename) |
1806 | icon_info->filename = g_strdup (unthemed_icon->no_svg_filename)g_strdup_inline (unthemed_icon->no_svg_filename); |
1807 | else |
1808 | { |
1809 | static gboolean warned_once = FALSE(0); |
1810 | |
1811 | if (!warned_once) |
1812 | { |
1813 | g_warning ("Found an icon but could not load it. " |
1814 | "Most likely gdk-pixbuf does not provide SVG support."); |
1815 | warned_once = TRUE(!(0)); |
1816 | } |
1817 | |
1818 | g_clear_object (&icon_info)do { _Static_assert (sizeof *((&icon_info)) == sizeof (gpointer ), "Expression evaluates to false"); __typeof__ (((&icon_info ))) _pp = ((&icon_info)); __typeof__ (*((&icon_info)) ) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) ( _ptr); } while (0); |
1819 | goto out; |
1820 | } |
1821 | |
1822 | if (unthemed_icon->is_resource) |
1823 | { |
1824 | gchar *uri; |
1825 | uri = g_strconcat ("resource://", icon_info->filename, NULL((void*)0)); |
1826 | icon_info->icon_file = g_file_new_for_uri (uri); |
1827 | g_free (uri); |
1828 | } |
1829 | else |
1830 | icon_info->icon_file = g_file_new_for_path (icon_info->filename); |
1831 | |
1832 | icon_info->is_svg = suffix_from_name (icon_info->filename) == ICON_SUFFIX_SVG; |
1833 | icon_info->is_resource = unthemed_icon->is_resource; |
1834 | } |
1835 | |
1836 | out: |
1837 | if (icon_info) |
1838 | { |
1839 | icon_info->desired_size = size; |
1840 | icon_info->desired_scale = scale; |
1841 | icon_info->forced_size = (flags & CTK_ICON_LOOKUP_FORCE_SIZE) != 0; |
1842 | |
1843 | /* In case we're not scaling the icon we want to reuse the exact same |
1844 | * size as a scale==1 lookup would be, rather than not scaling at all |
1845 | * and causing a different layout |
1846 | */ |
1847 | icon_info->unscaled_scale = 1.0; |
1848 | if (scale != 1 && !icon_info->forced_size && theme != NULL((void*)0)) |
1849 | { |
1850 | unscaled_icon_info = theme_lookup_icon (theme, icon_name, size, 1, allow_svg, use_builtin); |
1851 | if (unscaled_icon_info) |
1852 | { |
1853 | icon_info->unscaled_scale = |
1854 | (gdouble) unscaled_icon_info->dir_size * scale / (icon_info->dir_size * icon_info->dir_scale); |
1855 | g_object_unref (unscaled_icon_info); |
1856 | } |
1857 | } |
1858 | |
1859 | icon_info->key.icon_names = g_strdupv ((char **)icon_names); |
1860 | icon_info->key.size = size; |
1861 | icon_info->key.scale = scale; |
1862 | icon_info->key.flags = flags; |
1863 | icon_info->in_cache = icon_theme; |
1864 | DEBUG_CACHE (("adding %p (%s %d 0x%x) to cache (cache size %d)\n", |
1865 | icon_info, |
1866 | g_strjoinv (",", icon_info->key.icon_names), |
1867 | icon_info->key.size, icon_info->key.flags, |
1868 | g_hash_table_size (priv->info_cache))); |
1869 | g_hash_table_insert (priv->info_cache, &icon_info->key, icon_info); |
1870 | } |
1871 | else |
1872 | { |
1873 | static gboolean check_for_default_theme = TRUE(!(0)); |
1874 | gchar *default_theme_path; |
1875 | gboolean found = FALSE(0); |
1876 | |
1877 | if (check_for_default_theme) |
1878 | { |
1879 | check_for_default_theme = FALSE(0); |
1880 | |
1881 | for (i = 0; !found && i < priv->search_path_len; i++) |
1882 | { |
1883 | default_theme_path = g_build_filename (priv->search_path[i], |
1884 | FALLBACK_ICON_THEME"hicolor", |
1885 | "index.theme", |
1886 | NULL((void*)0)); |
1887 | found = g_file_test (default_theme_path, G_FILE_TEST_IS_REGULAR); |
1888 | g_free (default_theme_path); |
1889 | } |
1890 | |
1891 | if (!found) |
1892 | { |
1893 | g_warning ("Could not find the icon '%s'. The '%s' theme\n" |
1894 | "was not found either, perhaps you need to install it.\n" |
1895 | "You can get a copy from:\n" |
1896 | "\t%s", |
1897 | icon_names[0], FALLBACK_ICON_THEME"hicolor", "http://icon-theme.freedesktop.org/releases"); |
1898 | } |
1899 | } |
1900 | } |
1901 | |
1902 | return icon_info; |
1903 | } |
1904 | |
1905 | static void |
1906 | icon_name_list_add_icon (GPtrArray *icons, |
1907 | const gchar *dir_suffix, |
1908 | gchar *icon_name) |
1909 | { |
1910 | if (dir_suffix) |
1911 | g_ptr_array_add (icons, g_strconcat (icon_name, dir_suffix, NULL((void*)0))); |
1912 | g_ptr_array_add (icons, icon_name); |
1913 | } |
1914 | |
1915 | static CtkIconInfo * |
1916 | choose_icon (CtkIconTheme *icon_theme, |
1917 | const gchar *icon_names[], |
1918 | gint size, |
1919 | gint scale, |
1920 | CtkIconLookupFlags flags) |
1921 | { |
1922 | gboolean has_regular = FALSE(0), has_symbolic = FALSE(0); |
1923 | CtkIconInfo *icon_info; |
1924 | GPtrArray *new_names; |
1925 | const gchar *dir_suffix; |
1926 | guint i; |
1927 | |
1928 | if (flags & CTK_ICON_LOOKUP_DIR_LTR) |
1929 | dir_suffix = "-ltr"; |
1930 | else if (flags & CTK_ICON_LOOKUP_DIR_RTL) |
1931 | dir_suffix = "-rtl"; |
1932 | else |
1933 | dir_suffix = NULL((void*)0); |
1934 | |
1935 | for (i = 0; icon_names[i]; i++) |
1936 | { |
1937 | if (icon_name_is_symbolic (icon_names[i])) |
1938 | has_symbolic = TRUE(!(0)); |
1939 | else |
1940 | has_regular = TRUE(!(0)); |
1941 | } |
1942 | |
1943 | if ((flags & CTK_ICON_LOOKUP_FORCE_REGULAR) && has_symbolic) |
1944 | { |
1945 | new_names = g_ptr_array_new_with_free_func (g_free); |
1946 | for (i = 0; icon_names[i]; i++) |
1947 | { |
1948 | if (icon_name_is_symbolic (icon_names[i])) |
1949 | icon_name_list_add_icon (new_names, dir_suffix, g_strndup (icon_names[i], strlen (icon_names[i]) - strlen ("-symbolic"))); |
1950 | else |
1951 | icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i])g_strdup_inline (icon_names[i])); |
1952 | } |
1953 | for (i = 0; icon_names[i]; i++) |
1954 | { |
1955 | if (icon_name_is_symbolic (icon_names[i])) |
1956 | icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i])g_strdup_inline (icon_names[i])); |
1957 | } |
1958 | g_ptr_array_add (new_names, NULL((void*)0)); |
1959 | |
1960 | icon_info = real_choose_icon (icon_theme, |
1961 | (const gchar **) new_names->pdata, |
1962 | size, |
1963 | scale, |
1964 | flags & ~(CTK_ICON_LOOKUP_FORCE_REGULAR | CTK_ICON_LOOKUP_FORCE_SYMBOLIC)); |
1965 | |
1966 | g_ptr_array_free (new_names, TRUE(!(0))); |
1967 | } |
1968 | else if ((flags & CTK_ICON_LOOKUP_FORCE_SYMBOLIC) && has_regular) |
1969 | { |
1970 | new_names = g_ptr_array_new_with_free_func (g_free); |
1971 | for (i = 0; icon_names[i]; i++) |
1972 | { |
1973 | if (!icon_name_is_symbolic (icon_names[i])) |
1974 | icon_name_list_add_icon (new_names, dir_suffix, g_strconcat (icon_names[i], "-symbolic", NULL((void*)0))); |
1975 | else |
1976 | icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i])g_strdup_inline (icon_names[i])); |
1977 | } |
1978 | for (i = 0; icon_names[i]; i++) |
1979 | { |
1980 | if (!icon_name_is_symbolic (icon_names[i])) |
1981 | icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i])g_strdup_inline (icon_names[i])); |
1982 | } |
1983 | g_ptr_array_add (new_names, NULL((void*)0)); |
1984 | |
1985 | icon_info = real_choose_icon (icon_theme, |
1986 | (const gchar **) new_names->pdata, |
1987 | size, |
1988 | scale, |
1989 | flags & ~(CTK_ICON_LOOKUP_FORCE_REGULAR | CTK_ICON_LOOKUP_FORCE_SYMBOLIC)); |
1990 | |
1991 | g_ptr_array_free (new_names, TRUE(!(0))); |
1992 | } |
1993 | else if (dir_suffix) |
1994 | { |
1995 | new_names = g_ptr_array_new_with_free_func (g_free); |
1996 | for (i = 0; icon_names[i]; i++) |
1997 | { |
1998 | icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i])g_strdup_inline (icon_names[i])); |
1999 | } |
2000 | g_ptr_array_add (new_names, NULL((void*)0)); |
2001 | |
2002 | icon_info = real_choose_icon (icon_theme, |
2003 | (const gchar **) new_names->pdata, |
2004 | size, |
2005 | scale, |
2006 | flags & ~(CTK_ICON_LOOKUP_FORCE_REGULAR | CTK_ICON_LOOKUP_FORCE_SYMBOLIC)); |
2007 | |
2008 | g_ptr_array_free (new_names, TRUE(!(0))); |
2009 | } |
2010 | else |
2011 | { |
2012 | icon_info = real_choose_icon (icon_theme, |
2013 | icon_names, |
2014 | size, |
2015 | scale, |
2016 | flags & ~(CTK_ICON_LOOKUP_FORCE_REGULAR | CTK_ICON_LOOKUP_FORCE_SYMBOLIC)); |
2017 | } |
2018 | |
2019 | return icon_info; |
2020 | } |
2021 | |
2022 | /** |
2023 | * ctk_icon_theme_lookup_icon: |
2024 | * @icon_theme: a #CtkIconTheme |
2025 | * @icon_name: the name of the icon to lookup |
2026 | * @size: desired icon size |
2027 | * @flags: flags modifying the behavior of the icon lookup |
2028 | * |
2029 | * Looks up a named icon and returns a #CtkIconInfo containing |
2030 | * information such as the filename of the icon. The icon |
2031 | * can then be rendered into a pixbuf using |
2032 | * ctk_icon_info_load_icon(). (ctk_icon_theme_load_icon() |
2033 | * combines these two steps if all you need is the pixbuf.) |
2034 | * |
2035 | * When rendering on displays with high pixel densities you should not |
2036 | * use a @size multiplied by the scaling factor returned by functions |
2037 | * like cdk_window_get_scale_factor(). Instead, you should use |
2038 | * ctk_icon_theme_lookup_icon_for_scale(), as the assets loaded |
2039 | * for a given scaling factor may be different. |
2040 | * |
2041 | * Returns: (nullable) (transfer full): a #CtkIconInfo object |
2042 | * containing information about the icon, or %NULL if the |
2043 | * icon wasn’t found. |
2044 | * |
2045 | * Since: 2.4 |
2046 | */ |
2047 | CtkIconInfo * |
2048 | ctk_icon_theme_lookup_icon (CtkIconTheme *icon_theme, |
2049 | const gchar *icon_name, |
2050 | gint size, |
2051 | CtkIconLookupFlags flags) |
2052 | { |
2053 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((( void*)0)); } } while (0); |
2054 | g_return_val_if_fail (icon_name != NULL, NULL)do { if ((icon_name != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_name != NULL"); return (((void*)0)); } } while (0); |
2055 | g_return_val_if_fail ((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 ||do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0) |
2056 | (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL)do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0); |
2057 | |
2058 | CTK_NOTE (ICONTHEME, g_message ("looking up icon %s", icon_name))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { g_message ("looking up icon %s", icon_name); }; } while (0); |
2059 | |
2060 | return ctk_icon_theme_lookup_icon_for_scale (icon_theme, icon_name, |
2061 | size, 1, flags); |
2062 | } |
2063 | |
2064 | /** |
2065 | * ctk_icon_theme_lookup_icon_for_scale: |
2066 | * @icon_theme: a #CtkIconTheme |
2067 | * @icon_name: the name of the icon to lookup |
2068 | * @size: desired icon size |
2069 | * @scale: the desired scale |
2070 | * @flags: flags modifying the behavior of the icon lookup |
2071 | * |
2072 | * Looks up a named icon for a particular window scale and returns a |
2073 | * #CtkIconInfo containing information such as the filename of the |
2074 | * icon. The icon can then be rendered into a pixbuf using |
2075 | * ctk_icon_info_load_icon(). (ctk_icon_theme_load_icon() combines |
2076 | * these two steps if all you need is the pixbuf.) |
2077 | * |
2078 | * Returns: (nullable) (transfer full): a #CtkIconInfo object |
2079 | * containing information about the icon, or %NULL if the |
2080 | * icon wasn’t found. |
2081 | * |
2082 | * Since: 3.10 |
2083 | */ |
2084 | CtkIconInfo * |
2085 | ctk_icon_theme_lookup_icon_for_scale (CtkIconTheme *icon_theme, |
2086 | const gchar *icon_name, |
2087 | gint size, |
2088 | gint scale, |
2089 | CtkIconLookupFlags flags) |
2090 | { |
2091 | CtkIconInfo *info; |
2092 | |
2093 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((( void*)0)); } } while (0); |
2094 | g_return_val_if_fail (icon_name != NULL, NULL)do { if ((icon_name != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_name != NULL"); return (((void*)0)); } } while (0); |
2095 | g_return_val_if_fail ((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 ||do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0) |
2096 | (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL)do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0); |
2097 | g_return_val_if_fail (scale >= 1, NULL)do { if ((scale >= 1)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "scale >= 1"); return (((void*)0)); } } while (0); |
2098 | |
2099 | CTK_NOTE (ICONTHEME, g_message ("looking up icon %s for scale %d", icon_name, scale))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { g_message ("looking up icon %s for scale %d", icon_name, scale ); }; } while (0); |
2100 | |
2101 | if (flags & CTK_ICON_LOOKUP_GENERIC_FALLBACK) |
2102 | { |
2103 | gchar **names, **nonsymbolic_names; |
2104 | gint dashes, i; |
2105 | gchar *p, *nonsymbolic_icon_name; |
2106 | gboolean is_symbolic; |
2107 | |
2108 | is_symbolic = icon_name_is_symbolic (icon_name); |
2109 | if (is_symbolic) |
2110 | nonsymbolic_icon_name = g_strndup (icon_name, strlen (icon_name) - strlen ("-symbolic")); |
2111 | else |
2112 | nonsymbolic_icon_name = g_strdup (icon_name)g_strdup_inline (icon_name); |
2113 | |
2114 | dashes = 0; |
2115 | for (p = (gchar *) nonsymbolic_icon_name; *p; p++) |
2116 | if (*p == '-') |
2117 | dashes++; |
2118 | |
2119 | nonsymbolic_names = g_new (gchar *, dashes + 2)((gchar * *) g_malloc_n ((dashes + 2), sizeof (gchar *))); |
2120 | nonsymbolic_names[0] = nonsymbolic_icon_name; |
2121 | |
2122 | for (i = 1; i <= dashes; i++) |
2123 | { |
2124 | nonsymbolic_names[i] = g_strdup (nonsymbolic_names[i - 1])g_strdup_inline (nonsymbolic_names[i - 1]); |
2125 | p = strrchr (nonsymbolic_names[i], '-'); |
2126 | *p = '\0'; |
2127 | } |
2128 | nonsymbolic_names[dashes + 1] = NULL((void*)0); |
2129 | |
2130 | if (is_symbolic) |
2131 | { |
2132 | names = g_new (gchar *, 2 * dashes + 3)((gchar * *) g_malloc_n ((2 * dashes + 3), sizeof (gchar *))); |
2133 | for (i = 0; nonsymbolic_names[i] != NULL((void*)0); i++) |
2134 | { |
2135 | names[i] = g_strconcat (nonsymbolic_names[i], "-symbolic", NULL((void*)0)); |
2136 | names[dashes + 1 + i] = nonsymbolic_names[i]; |
2137 | } |
2138 | |
2139 | names[dashes + 1 + i] = NULL((void*)0); |
2140 | g_free (nonsymbolic_names); |
2141 | } |
2142 | else |
2143 | { |
2144 | names = nonsymbolic_names; |
2145 | } |
2146 | |
2147 | info = choose_icon (icon_theme, (const gchar **) names, size, scale, flags); |
2148 | |
2149 | g_strfreev (names); |
2150 | } |
2151 | else |
2152 | { |
2153 | const gchar *names[2]; |
2154 | |
2155 | names[0] = icon_name; |
2156 | names[1] = NULL((void*)0); |
2157 | |
2158 | info = choose_icon (icon_theme, names, size, scale, flags); |
2159 | } |
2160 | |
2161 | return info; |
2162 | } |
2163 | |
2164 | /** |
2165 | * ctk_icon_theme_choose_icon: |
2166 | * @icon_theme: a #CtkIconTheme |
2167 | * @icon_names: (array zero-terminated=1): %NULL-terminated array of |
2168 | * icon names to lookup |
2169 | * @size: desired icon size |
2170 | * @flags: flags modifying the behavior of the icon lookup |
2171 | * |
2172 | * Looks up a named icon and returns a #CtkIconInfo containing |
2173 | * information such as the filename of the icon. The icon |
2174 | * can then be rendered into a pixbuf using |
2175 | * ctk_icon_info_load_icon(). (ctk_icon_theme_load_icon() |
2176 | * combines these two steps if all you need is the pixbuf.) |
2177 | * |
2178 | * If @icon_names contains more than one name, this function |
2179 | * tries them all in the given order before falling back to |
2180 | * inherited icon themes. |
2181 | * |
2182 | * Returns: (nullable) (transfer full): a #CtkIconInfo object |
2183 | * containing information about the icon, or %NULL if the icon wasn’t |
2184 | * found. |
2185 | * |
2186 | * Since: 2.12 |
2187 | */ |
2188 | CtkIconInfo * |
2189 | ctk_icon_theme_choose_icon (CtkIconTheme *icon_theme, |
2190 | const gchar *icon_names[], |
2191 | gint size, |
2192 | CtkIconLookupFlags flags) |
2193 | { |
2194 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((( void*)0)); } } while (0); |
2195 | g_return_val_if_fail (icon_names != NULL, NULL)do { if ((icon_names != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_names != NULL"); return (((void*)0)); } } while (0); |
2196 | g_return_val_if_fail ((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 ||do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0) |
2197 | (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL)do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0); |
2198 | g_warn_if_fail ((flags & CTK_ICON_LOOKUP_GENERIC_FALLBACK) == 0)do { if ((flags & CTK_ICON_LOOKUP_GENERIC_FALLBACK) == 0) ; else g_warn_message ("Ctk", "ctkicontheme.c", 2198, ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_GENERIC_FALLBACK) == 0" ); } while (0); |
2199 | |
2200 | return choose_icon (icon_theme, icon_names, size, 1, flags); |
2201 | } |
2202 | |
2203 | /** |
2204 | * ctk_icon_theme_choose_icon_for_scale: |
2205 | * @icon_theme: a #CtkIconTheme |
2206 | * @icon_names: (array zero-terminated=1): %NULL-terminated |
2207 | * array of icon names to lookup |
2208 | * @size: desired icon size |
2209 | * @scale: desired scale |
2210 | * @flags: flags modifying the behavior of the icon lookup |
2211 | * |
2212 | * Looks up a named icon for a particular window scale and returns |
2213 | * a #CtkIconInfo containing information such as the filename of the |
2214 | * icon. The icon can then be rendered into a pixbuf using |
2215 | * ctk_icon_info_load_icon(). (ctk_icon_theme_load_icon() |
2216 | * combines these two steps if all you need is the pixbuf.) |
2217 | * |
2218 | * If @icon_names contains more than one name, this function |
2219 | * tries them all in the given order before falling back to |
2220 | * inherited icon themes. |
2221 | * |
2222 | * Returns: (nullable) (transfer full): a #CtkIconInfo object |
2223 | * containing information about the icon, or %NULL if the |
2224 | * icon wasn’t found. |
2225 | * |
2226 | * Since: 3.10 |
2227 | */ |
2228 | CtkIconInfo * |
2229 | ctk_icon_theme_choose_icon_for_scale (CtkIconTheme *icon_theme, |
2230 | const gchar *icon_names[], |
2231 | gint size, |
2232 | gint scale, |
2233 | CtkIconLookupFlags flags) |
2234 | { |
2235 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((( void*)0)); } } while (0); |
2236 | g_return_val_if_fail (icon_names != NULL, NULL)do { if ((icon_names != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_names != NULL"); return (((void*)0)); } } while (0); |
2237 | g_return_val_if_fail ((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 ||do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0) |
2238 | (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL)do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0); |
2239 | g_return_val_if_fail (scale >= 1, NULL)do { if ((scale >= 1)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "scale >= 1"); return (((void*)0)); } } while (0); |
2240 | g_warn_if_fail ((flags & CTK_ICON_LOOKUP_GENERIC_FALLBACK) == 0)do { if ((flags & CTK_ICON_LOOKUP_GENERIC_FALLBACK) == 0) ; else g_warn_message ("Ctk", "ctkicontheme.c", 2240, ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_GENERIC_FALLBACK) == 0" ); } while (0); |
2241 | |
2242 | return choose_icon (icon_theme, icon_names, size, scale, flags); |
2243 | } |
2244 | |
2245 | |
2246 | /* Error quark */ |
2247 | GQuark |
2248 | ctk_icon_theme_error_quark (void) |
2249 | { |
2250 | return g_quark_from_static_string ("ctk-icon-theme-error-quark"); |
2251 | } |
2252 | |
2253 | /** |
2254 | * ctk_icon_theme_load_icon: |
2255 | * @icon_theme: a #CtkIconTheme |
2256 | * @icon_name: the name of the icon to lookup |
2257 | * @size: the desired icon size. The resulting icon may not be |
2258 | * exactly this size; see ctk_icon_info_load_icon(). |
2259 | * @flags: flags modifying the behavior of the icon lookup |
2260 | * @error: (allow-none): Location to store error information on failure, |
2261 | * or %NULL. |
2262 | * |
2263 | * Looks up an icon in an icon theme, scales it to the given size |
2264 | * and renders it into a pixbuf. This is a convenience function; |
2265 | * if more details about the icon are needed, use |
2266 | * ctk_icon_theme_lookup_icon() followed by ctk_icon_info_load_icon(). |
2267 | * |
2268 | * Note that you probably want to listen for icon theme changes and |
2269 | * update the icon. This is usually done by connecting to the |
2270 | * CtkWidget::style-set signal. If for some reason you do not want to |
2271 | * update the icon when the icon theme changes, you should consider |
2272 | * using gdk_pixbuf_copy() to make a private copy of the pixbuf |
2273 | * returned by this function. Otherwise CTK+ may need to keep the old |
2274 | * icon theme loaded, which would be a waste of memory. |
2275 | * |
2276 | * Returns: (nullable) (transfer full): the rendered icon; this may be |
2277 | * a newly created icon or a new reference to an internal icon, so |
2278 | * you must not modify the icon. Use g_object_unref() to release |
2279 | * your reference to the icon. %NULL if the icon isn’t found. |
2280 | * |
2281 | * Since: 2.4 |
2282 | */ |
2283 | GdkPixbuf * |
2284 | ctk_icon_theme_load_icon (CtkIconTheme *icon_theme, |
2285 | const gchar *icon_name, |
2286 | gint size, |
2287 | CtkIconLookupFlags flags, |
2288 | GError **error) |
2289 | { |
2290 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((( void*)0)); } } while (0); |
2291 | g_return_val_if_fail (icon_name != NULL, NULL)do { if ((icon_name != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_name != NULL"); return (((void*)0)); } } while (0); |
2292 | g_return_val_if_fail ((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 ||do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0) |
2293 | (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL)do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0); |
2294 | g_return_val_if_fail (error == NULL || *error == NULL, NULL)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return (((void*)0)); } } while (0); |
2295 | |
2296 | return ctk_icon_theme_load_icon_for_scale (icon_theme, icon_name, |
2297 | size, 1, flags, error); |
2298 | } |
2299 | |
2300 | /** |
2301 | * ctk_icon_theme_load_icon_for_scale: |
2302 | * @icon_theme: a #CtkIconTheme |
2303 | * @icon_name: the name of the icon to lookup |
2304 | * @size: the desired icon size. The resulting icon may not be |
2305 | * exactly this size; see ctk_icon_info_load_icon(). |
2306 | * @scale: desired scale |
2307 | * @flags: flags modifying the behavior of the icon lookup |
2308 | * @error: (allow-none): Location to store error information on failure, |
2309 | * or %NULL. |
2310 | * |
2311 | * Looks up an icon in an icon theme for a particular window scale, |
2312 | * scales it to the given size and renders it into a pixbuf. This is a |
2313 | * convenience function; if more details about the icon are needed, |
2314 | * use ctk_icon_theme_lookup_icon() followed by |
2315 | * ctk_icon_info_load_icon(). |
2316 | * |
2317 | * Note that you probably want to listen for icon theme changes and |
2318 | * update the icon. This is usually done by connecting to the |
2319 | * CtkWidget::style-set signal. If for some reason you do not want to |
2320 | * update the icon when the icon theme changes, you should consider |
2321 | * using gdk_pixbuf_copy() to make a private copy of the pixbuf |
2322 | * returned by this function. Otherwise CTK+ may need to keep the old |
2323 | * icon theme loaded, which would be a waste of memory. |
2324 | * |
2325 | * Returns: (nullable) (transfer full): the rendered icon; this may be |
2326 | * a newly created icon or a new reference to an internal icon, so |
2327 | * you must not modify the icon. Use g_object_unref() to release |
2328 | * your reference to the icon. %NULL if the icon isn’t found. |
2329 | * |
2330 | * Since: 3.10 |
2331 | */ |
2332 | GdkPixbuf * |
2333 | ctk_icon_theme_load_icon_for_scale (CtkIconTheme *icon_theme, |
2334 | const gchar *icon_name, |
2335 | gint size, |
2336 | gint scale, |
2337 | CtkIconLookupFlags flags, |
2338 | GError **error) |
2339 | { |
2340 | CtkIconInfo *icon_info; |
2341 | GdkPixbuf *pixbuf = NULL((void*)0); |
2342 | |
2343 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((( void*)0)); } } while (0); |
2344 | g_return_val_if_fail (icon_name != NULL, NULL)do { if ((icon_name != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_name != NULL"); return (((void*)0)); } } while (0); |
2345 | g_return_val_if_fail ((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 ||do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0) |
2346 | (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL)do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0); |
2347 | g_return_val_if_fail (error == NULL || *error == NULL, NULL)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return (((void*)0)); } } while (0); |
2348 | g_return_val_if_fail (scale >= 1, NULL)do { if ((scale >= 1)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "scale >= 1"); return (((void*)0)); } } while (0); |
2349 | |
2350 | icon_info = ctk_icon_theme_lookup_icon_for_scale (icon_theme, icon_name, size, scale, |
2351 | flags | CTK_ICON_LOOKUP_USE_BUILTIN); |
2352 | if (!icon_info) |
2353 | { |
2354 | g_set_error (error, CTK_ICON_THEME_ERRORctk_icon_theme_error_quark (), CTK_ICON_THEME_NOT_FOUND, |
2355 | _("Icon '%s' not present in theme %s")((char *) g_dgettext ("ctk30", "Icon '%s' not present in theme %s" )), icon_name, icon_theme->priv->current_theme); |
2356 | return NULL((void*)0); |
2357 | } |
2358 | |
2359 | pixbuf = ctk_icon_info_load_icon (icon_info, error); |
2360 | g_prefix_error (error, "Failed to load %s: ", icon_info->filename); |
2361 | g_object_unref (icon_info); |
2362 | |
2363 | return pixbuf; |
2364 | } |
2365 | |
2366 | /** |
2367 | * ctk_icon_theme_load_surface: |
2368 | * @icon_theme: a #CtkIconTheme |
2369 | * @icon_name: the name of the icon to lookup |
2370 | * @size: the desired icon size. The resulting icon may not be |
2371 | * exactly this size; see ctk_icon_info_load_icon(). |
2372 | * @scale: desired scale |
2373 | * @for_window: (allow-none): #CdkWindow to optimize drawing for, or %NULL |
2374 | * @flags: flags modifying the behavior of the icon lookup |
2375 | * @error: (allow-none): Location to store error information on failure, |
2376 | * or %NULL. |
2377 | * |
2378 | * Looks up an icon in an icon theme for a particular window scale, |
2379 | * scales it to the given size and renders it into a cairo surface. This is a |
2380 | * convenience function; if more details about the icon are needed, |
2381 | * use ctk_icon_theme_lookup_icon() followed by |
2382 | * ctk_icon_info_load_surface(). |
2383 | * |
2384 | * Note that you probably want to listen for icon theme changes and |
2385 | * update the icon. This is usually done by connecting to the |
2386 | * CtkWidget::style-set signal. |
2387 | * |
2388 | * Returns: (nullable) (transfer full): the rendered icon; this may be |
2389 | * a newly created icon or a new reference to an internal icon, so |
2390 | * you must not modify the icon. Use cairo_surface_destroy() to |
2391 | * release your reference to the icon. %NULL if the icon isn’t |
2392 | * found. |
2393 | * |
2394 | * Since: 3.10 |
2395 | */ |
2396 | cairo_surface_t * |
2397 | ctk_icon_theme_load_surface (CtkIconTheme *icon_theme, |
2398 | const gchar *icon_name, |
2399 | gint size, |
2400 | gint scale, |
2401 | CdkWindow *for_window, |
2402 | CtkIconLookupFlags flags, |
2403 | GError **error) |
2404 | { |
2405 | CtkIconInfo *icon_info; |
2406 | cairo_surface_t *surface = NULL((void*)0); |
2407 | |
2408 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((( void*)0)); } } while (0); |
2409 | g_return_val_if_fail (icon_name != NULL, NULL)do { if ((icon_name != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_name != NULL"); return (((void*)0)); } } while (0); |
2410 | g_return_val_if_fail ((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 ||do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0) |
2411 | (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL)do { if (((flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_NO_SVG) == 0 || (flags & CTK_ICON_LOOKUP_FORCE_SVG) == 0" ); return (((void*)0)); } } while (0); |
2412 | g_return_val_if_fail (error == NULL || *error == NULL, NULL)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return (((void*)0)); } } while (0); |
2413 | g_return_val_if_fail (scale >= 1, NULL)do { if ((scale >= 1)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "scale >= 1"); return (((void*)0)); } } while (0); |
2414 | |
2415 | icon_info = ctk_icon_theme_lookup_icon_for_scale (icon_theme, icon_name, size, scale, |
2416 | flags | CTK_ICON_LOOKUP_USE_BUILTIN); |
2417 | if (!icon_info) |
2418 | { |
2419 | g_set_error (error, CTK_ICON_THEME_ERRORctk_icon_theme_error_quark (), CTK_ICON_THEME_NOT_FOUND, |
2420 | _("Icon '%s' not present in theme %s")((char *) g_dgettext ("ctk30", "Icon '%s' not present in theme %s" )), icon_name, icon_theme->priv->current_theme); |
2421 | return NULL((void*)0); |
2422 | } |
2423 | |
2424 | surface = ctk_icon_info_load_surface (icon_info, for_window, error); |
2425 | g_object_unref (icon_info); |
2426 | |
2427 | return surface; |
2428 | } |
2429 | |
2430 | /** |
2431 | * ctk_icon_theme_has_icon: |
2432 | * @icon_theme: a #CtkIconTheme |
2433 | * @icon_name: the name of an icon |
2434 | * |
2435 | * Checks whether an icon theme includes an icon |
2436 | * for a particular name. |
2437 | * |
2438 | * Returns: %TRUE if @icon_theme includes an |
2439 | * icon for @icon_name. |
2440 | * |
2441 | * Since: 2.4 |
2442 | */ |
2443 | gboolean |
2444 | ctk_icon_theme_has_icon (CtkIconTheme *icon_theme, |
2445 | const gchar *icon_name) |
2446 | { |
2447 | CtkIconThemePrivate *priv; |
2448 | GList *l; |
2449 | |
2450 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((0 )); } } while (0); |
2451 | g_return_val_if_fail (icon_name != NULL, FALSE)do { if ((icon_name != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_name != NULL"); return ((0)); } } while (0); |
2452 | |
2453 | priv = icon_theme->priv; |
2454 | |
2455 | ensure_valid_themes (icon_theme); |
2456 | |
2457 | for (l = priv->dir_mtimes; l; l = l->next) |
2458 | { |
2459 | IconThemeDirMtime *dir_mtime = l->data; |
2460 | CtkIconCache *cache = dir_mtime->cache; |
2461 | |
2462 | if (cache && _ctk_icon_cache_has_icon (cache, icon_name)) |
2463 | return TRUE(!(0)); |
2464 | } |
2465 | |
2466 | for (l = priv->themes; l; l = l->next) |
2467 | { |
2468 | if (theme_has_icon (l->data, icon_name)) |
2469 | return TRUE(!(0)); |
2470 | } |
2471 | |
2472 | if (icon_theme_builtin_icons && |
2473 | g_hash_table_lookup_extended (icon_theme_builtin_icons, |
2474 | icon_name, NULL((void*)0), NULL((void*)0))) |
2475 | return TRUE(!(0)); |
2476 | |
2477 | return FALSE(0); |
2478 | } |
2479 | |
2480 | static void |
2481 | add_size (gpointer key, |
2482 | gpointer value G_GNUC_UNUSED__attribute__ ((__unused__)), |
2483 | gpointer user_data) |
2484 | { |
2485 | gint **res_p = user_data; |
2486 | |
2487 | **res_p = GPOINTER_TO_INT (key)((gint) (glong) (key)); |
2488 | |
2489 | (*res_p)++; |
2490 | } |
2491 | |
2492 | /** |
2493 | * ctk_icon_theme_get_icon_sizes: |
2494 | * @icon_theme: a #CtkIconTheme |
2495 | * @icon_name: the name of an icon |
2496 | * |
2497 | * Returns an array of integers describing the sizes at which |
2498 | * the icon is available without scaling. A size of -1 means |
2499 | * that the icon is available in a scalable format. The array |
2500 | * is zero-terminated. |
2501 | * |
2502 | * Returns: (array zero-terminated=1) (transfer full): An newly |
2503 | * allocated array describing the sizes at which the icon is |
2504 | * available. The array should be freed with g_free() when it is no |
2505 | * longer needed. |
2506 | * |
2507 | * Since: 2.6 |
2508 | */ |
2509 | gint * |
2510 | ctk_icon_theme_get_icon_sizes (CtkIconTheme *icon_theme, |
2511 | const gchar *icon_name) |
2512 | { |
2513 | GList *l, *d, *icons; |
2514 | GHashTable *sizes; |
2515 | gint *result, *r; |
2516 | guint suffix; |
2517 | CtkIconThemePrivate *priv; |
2518 | |
2519 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((( void*)0)); } } while (0); |
2520 | |
2521 | priv = icon_theme->priv; |
2522 | |
2523 | ensure_valid_themes (icon_theme); |
2524 | |
2525 | sizes = g_hash_table_new (g_direct_hash, g_direct_equal); |
2526 | |
2527 | for (l = priv->themes; l; l = l->next) |
2528 | { |
2529 | IconTheme *theme = l->data; |
2530 | for (d = theme->dirs; d; d = d->next) |
2531 | { |
2532 | IconThemeDir *dir = d->data; |
2533 | |
2534 | if (dir->type != ICON_THEME_DIR_SCALABLE && g_hash_table_lookup_extended (sizes, GINT_TO_POINTER (dir->size)((gpointer) (glong) (dir->size)), NULL((void*)0), NULL((void*)0))) |
2535 | continue; |
2536 | |
2537 | suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL((void*)0)); |
2538 | if (suffix != ICON_SUFFIX_NONE) |
2539 | { |
2540 | if (suffix == ICON_SUFFIX_SVG) |
2541 | g_hash_table_insert (sizes, GINT_TO_POINTER (-1)((gpointer) (glong) (-1)), NULL((void*)0)); |
2542 | else |
2543 | g_hash_table_insert (sizes, GINT_TO_POINTER (dir->size)((gpointer) (glong) (dir->size)), NULL((void*)0)); |
2544 | } |
2545 | } |
2546 | } |
2547 | |
2548 | if (icon_theme_builtin_icons) |
2549 | { |
2550 | icons = g_hash_table_lookup (icon_theme_builtin_icons, icon_name); |
2551 | |
2552 | while (icons) |
2553 | { |
2554 | BuiltinIcon *icon = icons->data; |
2555 | |
2556 | g_hash_table_insert (sizes, GINT_TO_POINTER (icon->size)((gpointer) (glong) (icon->size)), NULL((void*)0)); |
2557 | icons = icons->next; |
2558 | } |
2559 | } |
2560 | |
2561 | r = result = g_new0 (gint, g_hash_table_size (sizes) + 1)((gint *) g_malloc0_n ((g_hash_table_size (sizes) + 1), sizeof (gint))); |
2562 | |
2563 | g_hash_table_foreach (sizes, add_size, &r); |
2564 | g_hash_table_destroy (sizes); |
2565 | |
2566 | return result; |
2567 | } |
2568 | |
2569 | static void |
2570 | add_key_to_hash (gpointer key, |
2571 | gpointer value G_GNUC_UNUSED__attribute__ ((__unused__)), |
2572 | gpointer user_data) |
2573 | { |
2574 | GHashTable *hash = user_data; |
2575 | |
2576 | g_hash_table_insert (hash, key, NULL((void*)0)); |
2577 | } |
2578 | |
2579 | static void |
2580 | add_key_to_list (gpointer key, |
2581 | gpointer value G_GNUC_UNUSED__attribute__ ((__unused__)), |
2582 | gpointer user_data) |
2583 | { |
2584 | GList **list = user_data; |
2585 | |
2586 | *list = g_list_prepend (*list, g_strdup (key)g_strdup_inline (key)); |
2587 | } |
2588 | |
2589 | /** |
2590 | * ctk_icon_theme_list_icons: |
2591 | * @icon_theme: a #CtkIconTheme |
2592 | * @context: (allow-none): a string identifying a particular type of |
2593 | * icon, or %NULL to list all icons. |
2594 | * |
2595 | * Lists the icons in the current icon theme. Only a subset |
2596 | * of the icons can be listed by providing a context string. |
2597 | * The set of values for the context string is system dependent, |
2598 | * but will typically include such values as “Applications” and |
2599 | * “MimeTypes”. Contexts are explained in the |
2600 | * [Icon Theme Specification](http://www.freedesktop.org/wiki/Specifications/icon-theme-spec). |
2601 | * The standard contexts are listed in the |
2602 | * [Icon Naming Specification](http://www.freedesktop.org/wiki/Specifications/icon-naming-spec). |
2603 | * Also see ctk_icon_theme_list_contexts(). |
2604 | * |
2605 | * Returns: (element-type utf8) (transfer full): a #GList list |
2606 | * holding the names of all the icons in the theme. You must |
2607 | * first free each element in the list with g_free(), then |
2608 | * free the list itself with g_list_free(). |
2609 | * |
2610 | * Since: 2.4 |
2611 | */ |
2612 | GList * |
2613 | ctk_icon_theme_list_icons (CtkIconTheme *icon_theme, |
2614 | const gchar *context) |
2615 | { |
2616 | CtkIconThemePrivate *priv; |
2617 | GHashTable *icons; |
2618 | GList *list, *l; |
2619 | GQuark context_quark; |
2620 | |
2621 | priv = icon_theme->priv; |
2622 | |
2623 | ensure_valid_themes (icon_theme); |
2624 | |
2625 | if (context) |
2626 | { |
2627 | context_quark = g_quark_try_string (context); |
2628 | |
2629 | if (!context_quark) |
2630 | return NULL((void*)0); |
2631 | } |
2632 | else |
2633 | context_quark = 0; |
2634 | |
2635 | icons = g_hash_table_new (g_str_hash, g_str_equal); |
2636 | |
2637 | l = priv->themes; |
2638 | while (l != NULL((void*)0)) |
2639 | { |
2640 | theme_list_icons (l->data, icons, context_quark); |
2641 | l = l->next; |
2642 | } |
2643 | |
2644 | if (context_quark == 0) |
2645 | g_hash_table_foreach (priv->unthemed_icons, |
2646 | add_key_to_hash, |
2647 | icons); |
2648 | |
2649 | list = NULL((void*)0); |
2650 | |
2651 | g_hash_table_foreach (icons, |
2652 | add_key_to_list, |
2653 | &list); |
2654 | |
2655 | g_hash_table_destroy (icons); |
2656 | |
2657 | return list; |
2658 | } |
2659 | |
2660 | /** |
2661 | * ctk_icon_theme_list_contexts: |
2662 | * @icon_theme: a #CtkIconTheme |
2663 | * |
2664 | * Gets the list of contexts available within the current |
2665 | * hierarchy of icon themes. |
2666 | * See ctk_icon_theme_list_icons() for details about contexts. |
2667 | * |
2668 | * Returns: (element-type utf8) (transfer full): a #GList list |
2669 | * holding the names of all the contexts in the theme. You must first |
2670 | * free each element in the list with g_free(), then free the list |
2671 | * itself with g_list_free(). |
2672 | * |
2673 | * Since: 2.12 |
2674 | */ |
2675 | GList * |
2676 | ctk_icon_theme_list_contexts (CtkIconTheme *icon_theme) |
2677 | { |
2678 | CtkIconThemePrivate *priv; |
2679 | GHashTable *contexts; |
2680 | GList *list, *l; |
2681 | |
2682 | priv = icon_theme->priv; |
2683 | |
2684 | ensure_valid_themes (icon_theme); |
2685 | |
2686 | contexts = g_hash_table_new (g_str_hash, g_str_equal); |
2687 | |
2688 | l = priv->themes; |
2689 | while (l != NULL((void*)0)) |
2690 | { |
2691 | theme_list_contexts (l->data, contexts); |
2692 | l = l->next; |
2693 | } |
2694 | |
2695 | list = NULL((void*)0); |
2696 | |
2697 | g_hash_table_foreach (contexts, |
2698 | add_key_to_list, |
2699 | &list); |
2700 | |
2701 | g_hash_table_destroy (contexts); |
2702 | |
2703 | return list; |
2704 | } |
2705 | |
2706 | /** |
2707 | * ctk_icon_theme_get_example_icon_name: |
2708 | * @icon_theme: a #CtkIconTheme |
2709 | * |
2710 | * Gets the name of an icon that is representative of the |
2711 | * current theme (for instance, to use when presenting |
2712 | * a list of themes to the user.) |
2713 | * |
2714 | * Returns: (nullable): the name of an example icon or %NULL. |
2715 | * Free with g_free(). |
2716 | * |
2717 | * Since: 2.4 |
2718 | */ |
2719 | gchar * |
2720 | ctk_icon_theme_get_example_icon_name (CtkIconTheme *icon_theme) |
2721 | { |
2722 | CtkIconThemePrivate *priv; |
2723 | GList *l; |
2724 | IconTheme *theme; |
2725 | |
2726 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((( void*)0)); } } while (0); |
2727 | |
2728 | priv = icon_theme->priv; |
2729 | |
2730 | ensure_valid_themes (icon_theme); |
2731 | |
2732 | l = priv->themes; |
2733 | while (l != NULL((void*)0)) |
2734 | { |
2735 | theme = l->data; |
2736 | if (theme->example) |
2737 | return g_strdup (theme->example)g_strdup_inline (theme->example); |
2738 | |
2739 | l = l->next; |
2740 | } |
2741 | |
2742 | return NULL((void*)0); |
2743 | } |
2744 | |
2745 | |
2746 | static gboolean |
2747 | rescan_themes (CtkIconTheme *icon_theme) |
2748 | { |
2749 | CtkIconThemePrivate *priv; |
2750 | IconThemeDirMtime *dir_mtime; |
2751 | GList *d; |
2752 | gint stat_res; |
2753 | GStatBuf stat_buf; |
2754 | |
2755 | priv = icon_theme->priv; |
2756 | |
2757 | for (d = priv->dir_mtimes; d != NULL((void*)0); d = d->next) |
2758 | { |
2759 | dir_mtime = d->data; |
2760 | |
2761 | stat_res = g_statstat (dir_mtime->dir, &stat_buf); |
2762 | |
2763 | /* dir mtime didn't change */ |
2764 | if (stat_res == 0 && dir_mtime->exists && |
2765 | S_ISDIR (stat_buf.st_mode)((((stat_buf.st_mode)) & 0170000) == (0040000)) && |
2766 | dir_mtime->mtime == stat_buf.st_mtimest_mtim.tv_sec) |
2767 | continue; |
2768 | /* didn't exist before, and still doesn't */ |
2769 | if (!dir_mtime->exists && |
2770 | (stat_res != 0 || !S_ISDIR (stat_buf.st_mode)((((stat_buf.st_mode)) & 0170000) == (0040000)))) |
2771 | continue; |
2772 | |
2773 | return TRUE(!(0)); |
2774 | } |
2775 | |
2776 | priv->last_stat_time = g_get_monotonic_time (); |
2777 | |
2778 | return FALSE(0); |
2779 | } |
2780 | |
2781 | /** |
2782 | * ctk_icon_theme_rescan_if_needed: |
2783 | * @icon_theme: a #CtkIconTheme |
2784 | * |
2785 | * Checks to see if the icon theme has changed; if it has, any |
2786 | * currently cached information is discarded and will be reloaded |
2787 | * next time @icon_theme is accessed. |
2788 | * |
2789 | * Returns: %TRUE if the icon theme has changed and needed |
2790 | * to be reloaded. |
2791 | * |
2792 | * Since: 2.4 |
2793 | */ |
2794 | gboolean |
2795 | ctk_icon_theme_rescan_if_needed (CtkIconTheme *icon_theme) |
2796 | { |
2797 | gboolean retval; |
2798 | |
2799 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((0 )); } } while (0); |
2800 | |
2801 | retval = rescan_themes (icon_theme); |
2802 | if (retval) |
2803 | do_theme_change (icon_theme); |
2804 | |
2805 | return retval; |
2806 | } |
2807 | |
2808 | static void |
2809 | theme_destroy (IconTheme *theme) |
2810 | { |
2811 | g_free (theme->display_name); |
2812 | g_free (theme->comment); |
2813 | g_free (theme->name); |
2814 | g_free (theme->example); |
2815 | |
2816 | g_list_free_full (theme->dirs, (GDestroyNotify) theme_dir_destroy); |
2817 | |
2818 | g_free (theme); |
2819 | } |
2820 | |
2821 | static void |
2822 | theme_dir_destroy (IconThemeDir *dir) |
2823 | { |
2824 | if (dir->cache) |
2825 | _ctk_icon_cache_unref (dir->cache); |
2826 | if (dir->icons) |
2827 | g_hash_table_destroy (dir->icons); |
2828 | |
2829 | g_free (dir->dir); |
2830 | g_free (dir->subdir); |
2831 | g_free (dir); |
2832 | } |
2833 | |
2834 | static int |
2835 | theme_dir_size_difference (IconThemeDir *dir, |
2836 | gint size, |
2837 | gint scale) |
2838 | { |
2839 | gint scaled_size, scaled_dir_size; |
2840 | gint min, max; |
2841 | |
2842 | scaled_size = size * scale; |
2843 | scaled_dir_size = dir->size * dir->scale; |
2844 | |
2845 | switch (dir->type) |
2846 | { |
2847 | case ICON_THEME_DIR_FIXED: |
2848 | return abs (scaled_size - scaled_dir_size); |
2849 | break; |
This statement is never executed | |
2850 | case ICON_THEME_DIR_SCALABLE: |
2851 | if (scaled_size < (dir->min_size * dir->scale)) |
2852 | return (dir->min_size * dir->scale) - scaled_size; |
2853 | if (size > (dir->max_size * dir->scale)) |
2854 | return scaled_size - (dir->max_size * dir->scale); |
2855 | return 0; |
2856 | break; |
2857 | case ICON_THEME_DIR_THRESHOLD: |
2858 | min = (dir->size - dir->threshold) * dir->scale; |
2859 | max = (dir->size + dir->threshold) * dir->scale; |
2860 | if (scaled_size < min) |
2861 | return min - scaled_size; |
2862 | if (scaled_size > max) |
2863 | return scaled_size - max; |
2864 | return 0; |
2865 | break; |
2866 | case ICON_THEME_DIR_UNTHEMED: |
2867 | g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkicontheme.c", 2867, ((const char*) (__func__)), ((void*)0)); } while (0); |
2868 | break; |
2869 | } |
2870 | g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkicontheme.c", 2870, ((const char*) (__func__)), ((void*)0)); } while (0); |
2871 | return 1000; |
2872 | } |
2873 | |
2874 | static const gchar * |
2875 | string_from_suffix (IconSuffix suffix) |
2876 | { |
2877 | switch (suffix) |
2878 | { |
2879 | case ICON_SUFFIX_XPM: |
2880 | return ".xpm"; |
2881 | case ICON_SUFFIX_SVG: |
2882 | return ".svg"; |
2883 | case ICON_SUFFIX_PNG: |
2884 | return ".png"; |
2885 | case ICON_SUFFIX_SYMBOLIC_PNG: |
2886 | return ".symbolic.png"; |
2887 | default: |
2888 | g_assert_not_reached()do { g_assertion_message_expr ("Ctk", "ctkicontheme.c", 2888, ((const char*) (__func__)), ((void*)0)); } while (0); |
2889 | } |
2890 | return NULL((void*)0); |
2891 | } |
2892 | |
2893 | static IconSuffix |
2894 | suffix_from_name (const gchar *name) |
2895 | { |
2896 | IconSuffix retval = ICON_SUFFIX_NONE; |
2897 | |
2898 | if (name != NULL((void*)0)) |
2899 | { |
2900 | if (g_str_has_suffix (name, ".symbolic.png")(__builtin_constant_p (".symbolic.png")? __extension__ ({ const char * const __str = (name); const char * const __suffix = ( ".symbolic.png"); gboolean __result = (0); if (__str == ((void *)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix) (__str, __suffix); else { const size_t __str_len = strlen (( (__str) + !(__str))); const size_t __suffix_len = strlen (((__suffix ) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (name, ".symbolic.png") )) |
2901 | retval = ICON_SUFFIX_SYMBOLIC_PNG; |
2902 | else if (g_str_has_suffix (name, ".png")(__builtin_constant_p (".png")? __extension__ ({ const char * const __str = (name); const char * const __suffix = (".png") ; gboolean __result = (0); if (__str == ((void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix) (__str, __suffix ); else { const size_t __str_len = strlen (((__str) + !(__str ))); const size_t __suffix_len = strlen (((__suffix) + !(__suffix ))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(__suffix)), __suffix_len ) == 0; } __result; }) : (g_str_has_suffix) (name, ".png") )) |
2903 | retval = ICON_SUFFIX_PNG; |
2904 | else if (g_str_has_suffix (name, ".svg")(__builtin_constant_p (".svg")? __extension__ ({ const char * const __str = (name); const char * const __suffix = (".svg") ; gboolean __result = (0); if (__str == ((void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix) (__str, __suffix ); else { const size_t __str_len = strlen (((__str) + !(__str ))); const size_t __suffix_len = strlen (((__suffix) + !(__suffix ))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(__suffix)), __suffix_len ) == 0; } __result; }) : (g_str_has_suffix) (name, ".svg") )) |
2905 | retval = ICON_SUFFIX_SVG; |
2906 | else if (g_str_has_suffix (name, ".xpm")(__builtin_constant_p (".xpm")? __extension__ ({ const char * const __str = (name); const char * const __suffix = (".xpm") ; gboolean __result = (0); if (__str == ((void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix) (__str, __suffix ); else { const size_t __str_len = strlen (((__str) + !(__str ))); const size_t __suffix_len = strlen (((__suffix) + !(__suffix ))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(__suffix)), __suffix_len ) == 0; } __result; }) : (g_str_has_suffix) (name, ".xpm") )) |
2907 | retval = ICON_SUFFIX_XPM; |
2908 | } |
2909 | |
2910 | return retval; |
2911 | } |
2912 | |
2913 | static IconSuffix |
2914 | best_suffix (IconSuffix suffix, |
2915 | gboolean allow_svg) |
2916 | { |
2917 | if ((suffix & ICON_SUFFIX_SYMBOLIC_PNG) != 0) |
2918 | return ICON_SUFFIX_SYMBOLIC_PNG; |
2919 | else if ((suffix & ICON_SUFFIX_PNG) != 0) |
2920 | return ICON_SUFFIX_PNG; |
2921 | else if (allow_svg && ((suffix & ICON_SUFFIX_SVG) != 0)) |
2922 | return ICON_SUFFIX_SVG; |
2923 | else if ((suffix & ICON_SUFFIX_XPM) != 0) |
2924 | return ICON_SUFFIX_XPM; |
2925 | else |
2926 | return ICON_SUFFIX_NONE; |
2927 | } |
2928 | |
2929 | static IconSuffix |
2930 | theme_dir_get_icon_suffix (IconThemeDir *dir, |
2931 | const gchar *icon_name, |
2932 | gboolean *has_icon_file) |
2933 | { |
2934 | IconSuffix suffix, symbolic_suffix; |
2935 | |
2936 | if (dir->cache) |
2937 | { |
2938 | suffix = (IconSuffix)_ctk_icon_cache_get_icon_flags (dir->cache, |
2939 | icon_name, |
2940 | dir->subdir_index); |
2941 | |
2942 | if (icon_name_is_symbolic (icon_name)) |
2943 | { |
2944 | /* Look for foo-symbolic.symbolic.png, as the cache only stores the ".png" suffix */ |
2945 | char *icon_name_with_prefix = g_strconcat (icon_name, ".symbolic", NULL((void*)0)); |
2946 | symbolic_suffix = (IconSuffix)_ctk_icon_cache_get_icon_flags (dir->cache, |
2947 | icon_name_with_prefix, |
2948 | dir->subdir_index); |
2949 | g_free (icon_name_with_prefix); |
2950 | |
2951 | if (symbolic_suffix & ICON_SUFFIX_PNG) |
2952 | suffix = ICON_SUFFIX_SYMBOLIC_PNG; |
2953 | } |
2954 | |
2955 | if (has_icon_file) |
2956 | *has_icon_file = suffix & HAS_ICON_FILE; |
2957 | |
2958 | suffix = suffix & ~HAS_ICON_FILE; |
2959 | } |
2960 | else |
2961 | suffix = GPOINTER_TO_UINT (g_hash_table_lookup (dir->icons, icon_name))((guint) (gulong) (g_hash_table_lookup (dir->icons, icon_name ))); |
2962 | |
2963 | CTK_NOTE (ICONTHEME, g_message ("get icon suffix%s: %u", dir->cache ? " (cached)" : "", suffix))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { g_message ("get icon suffix%s: %u", dir->cache ? " (cached)" : "", suffix); }; } while (0); |
2964 | |
2965 | return suffix; |
2966 | } |
2967 | |
2968 | /* returns TRUE if dir_a is a better match */ |
2969 | static gboolean |
2970 | compare_dir_matches (IconThemeDir *dir_a, gint difference_a, |
2971 | IconThemeDir *dir_b, gint difference_b, |
2972 | gint requested_size, |
2973 | gint requested_scale) |
2974 | { |
2975 | gint diff_a; |
2976 | gint diff_b; |
2977 | |
2978 | if (difference_a == 0) |
2979 | { |
2980 | if (difference_b != 0) |
2981 | return TRUE(!(0)); |
2982 | |
2983 | /* a and b both exact matches */ |
2984 | } |
2985 | else |
2986 | { |
2987 | /* If scaling, *always* prefer downscaling */ |
2988 | if (dir_a->size >= requested_size && |
2989 | dir_b->size < requested_size) |
2990 | return TRUE(!(0)); |
2991 | |
2992 | if (dir_a->size < requested_size && |
2993 | dir_b->size >= requested_size) |
2994 | return FALSE(0); |
2995 | |
2996 | /* Otherwise prefer the closest match */ |
2997 | |
2998 | if (difference_a < difference_b) |
2999 | return TRUE(!(0)); |
3000 | |
3001 | if (difference_a > difference_b) |
3002 | return FALSE(0); |
3003 | |
3004 | /* same pixel difference */ |
3005 | } |
3006 | |
3007 | if (dir_a->scale == requested_scale && |
3008 | dir_b->scale != requested_scale) |
3009 | return TRUE(!(0)); |
3010 | |
3011 | if (dir_a->scale != requested_scale && |
3012 | dir_b->scale == requested_scale) |
3013 | return FALSE(0); |
3014 | |
3015 | /* a and b both match the scale */ |
3016 | |
3017 | if (dir_a->type != ICON_THEME_DIR_SCALABLE && |
3018 | dir_b->type == ICON_THEME_DIR_SCALABLE) |
3019 | return TRUE(!(0)); |
3020 | |
3021 | if (dir_a->type == ICON_THEME_DIR_SCALABLE && |
3022 | dir_b->type != ICON_THEME_DIR_SCALABLE) |
3023 | return FALSE(0); |
3024 | |
3025 | /* a and b both are scalable */ |
3026 | |
3027 | diff_a = abs (requested_size * requested_scale - dir_a->size * dir_a->scale); |
3028 | diff_b = abs (requested_size * requested_scale - dir_b->size * dir_b->scale); |
3029 | |
3030 | return diff_a <= diff_b; |
3031 | } |
3032 | |
3033 | static CtkIconInfo * |
3034 | theme_lookup_icon (IconTheme *theme, |
3035 | const gchar *icon_name, |
3036 | gint size, |
3037 | gint scale, |
3038 | gboolean allow_svg, |
3039 | gboolean use_builtin) |
3040 | { |
3041 | GList *dirs, *l; |
3042 | IconThemeDir *dir, *min_dir; |
3043 | gchar *file; |
3044 | gint min_difference, difference; |
3045 | BuiltinIcon *closest_builtin = NULL((void*)0); |
3046 | IconSuffix suffix; |
3047 | |
3048 | min_difference = G_MAXINT2147483647; |
3049 | min_dir = NULL((void*)0); |
3050 | |
3051 | /* Builtin icons are logically part of the default theme and |
3052 | * are searched before other subdirectories of the default theme. |
3053 | */ |
3054 | if (use_builtin && strcmp (theme->name, FALLBACK_ICON_THEME"hicolor") == 0) |
3055 | { |
3056 | closest_builtin = find_builtin_icon (icon_name, |
3057 | size, scale, |
3058 | &min_difference); |
3059 | |
3060 | if (min_difference == 0) |
3061 | return icon_info_new_builtin (closest_builtin); |
3062 | } |
3063 | |
3064 | dirs = theme->dirs; |
3065 | |
3066 | l = dirs; |
3067 | while (l != NULL((void*)0)) |
3068 | { |
3069 | dir = l->data; |
3070 | |
3071 | CTK_NOTE (ICONTHEME, g_message ("look up icon dir %s", dir->dir))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { g_message ("look up icon dir %s", dir->dir); }; } while ( 0); |
3072 | suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL((void*)0)); |
3073 | if (best_suffix (suffix, allow_svg) != ICON_SUFFIX_NONE) |
3074 | { |
3075 | difference = theme_dir_size_difference (dir, size, scale); |
3076 | if (min_dir == NULL((void*)0) || |
3077 | compare_dir_matches (dir, difference, |
3078 | min_dir, min_difference, |
3079 | size, scale)) |
3080 | { |
3081 | min_dir = dir; |
3082 | min_difference = difference; |
3083 | } |
3084 | } |
3085 | |
3086 | l = l->next; |
3087 | } |
3088 | |
3089 | if (min_dir) |
3090 | { |
3091 | CtkIconInfo *icon_info; |
3092 | gboolean has_icon_file = FALSE(0); |
3093 | |
3094 | icon_info = icon_info_new (min_dir->type, min_dir->size, min_dir->scale); |
3095 | icon_info->min_size = min_dir->min_size; |
3096 | icon_info->max_size = min_dir->max_size; |
3097 | |
3098 | suffix = theme_dir_get_icon_suffix (min_dir, icon_name, &has_icon_file); |
3099 | suffix = best_suffix (suffix, allow_svg); |
3100 | g_assert (suffix != ICON_SUFFIX_NONE)do { if (suffix != ICON_SUFFIX_NONE) ; else g_assertion_message_expr ("Ctk", "ctkicontheme.c", 3100, ((const char*) (__func__)), "suffix != ICON_SUFFIX_NONE" ); } while (0); |
3101 | |
3102 | if (min_dir->dir) |
3103 | { |
3104 | file = g_strconcat (icon_name, string_from_suffix (suffix), NULL((void*)0)); |
3105 | icon_info->filename = g_build_filename (min_dir->dir, file, NULL((void*)0)); |
3106 | |
3107 | if (min_dir->is_resource) |
3108 | { |
3109 | gchar *uri; |
3110 | uri = g_strconcat ("resource://", icon_info->filename, NULL((void*)0)); |
3111 | icon_info->icon_file = g_file_new_for_uri (uri); |
3112 | g_free (uri); |
3113 | } |
3114 | else |
3115 | icon_info->icon_file = g_file_new_for_path (icon_info->filename); |
3116 | |
3117 | icon_info->is_svg = suffix == ICON_SUFFIX_SVG; |
3118 | icon_info->is_resource = min_dir->is_resource; |
3119 | g_free (file); |
3120 | } |
3121 | else |
3122 | { |
3123 | icon_info->filename = NULL((void*)0); |
3124 | icon_info->icon_file = NULL((void*)0); |
3125 | } |
3126 | |
3127 | if (min_dir->cache) |
3128 | { |
3129 | icon_info->cache_pixbuf = _ctk_icon_cache_get_icon (min_dir->cache, icon_name, |
3130 | min_dir->subdir_index); |
3131 | } |
3132 | |
3133 | return icon_info; |
3134 | } |
3135 | |
3136 | if (closest_builtin) |
3137 | return icon_info_new_builtin (closest_builtin); |
3138 | |
3139 | return NULL((void*)0); |
3140 | } |
3141 | |
3142 | static void |
3143 | theme_list_icons (IconTheme *theme, |
3144 | GHashTable *icons, |
3145 | GQuark context) |
3146 | { |
3147 | GList *l = theme->dirs; |
3148 | IconThemeDir *dir; |
3149 | |
3150 | while (l != NULL((void*)0)) |
3151 | { |
3152 | dir = l->data; |
3153 | |
3154 | if (context == dir->context || |
3155 | context == 0) |
3156 | { |
3157 | if (dir->cache) |
3158 | _ctk_icon_cache_add_icons (dir->cache, dir->subdir, icons); |
3159 | else |
3160 | g_hash_table_foreach (dir->icons, add_key_to_hash, icons); |
3161 | } |
3162 | l = l->next; |
3163 | } |
3164 | } |
3165 | |
3166 | static gboolean |
3167 | theme_has_icon (IconTheme *theme, |
3168 | const gchar *icon_name) |
3169 | { |
3170 | GList *l; |
3171 | |
3172 | for (l = theme->dirs; l; l = l->next) |
3173 | { |
3174 | IconThemeDir *dir = l->data; |
3175 | |
3176 | if (dir->cache) |
3177 | { |
3178 | if (_ctk_icon_cache_has_icon (dir->cache, icon_name)) |
3179 | return TRUE(!(0)); |
3180 | } |
3181 | else |
3182 | { |
3183 | if (g_hash_table_lookup (dir->icons, icon_name) != NULL((void*)0)) |
3184 | return TRUE(!(0)); |
3185 | } |
3186 | } |
3187 | |
3188 | return FALSE(0); |
3189 | } |
3190 | |
3191 | static void |
3192 | theme_list_contexts (IconTheme *theme, |
3193 | GHashTable *contexts) |
3194 | { |
3195 | GList *l = theme->dirs; |
3196 | IconThemeDir *dir; |
3197 | const gchar *context; |
3198 | |
3199 | while (l != NULL((void*)0)) |
3200 | { |
3201 | dir = l->data; |
3202 | |
3203 | /* The "Context" key can be unset */ |
3204 | if (dir->context != 0) |
3205 | { |
3206 | context = g_quark_to_string (dir->context); |
3207 | g_hash_table_replace (contexts, (gpointer) context, NULL((void*)0)); |
3208 | } |
3209 | |
3210 | l = l->next; |
3211 | } |
3212 | } |
3213 | |
3214 | static gboolean |
3215 | scan_directory (CtkIconThemePrivate *icon_theme G_GNUC_UNUSED__attribute__ ((__unused__)), |
3216 | IconThemeDir *dir, |
3217 | gchar *full_dir) |
3218 | { |
3219 | GDir *gdir; |
3220 | const gchar *name; |
3221 | |
3222 | CTK_NOTE (ICONTHEME, g_message ("scanning directory %s", full_dir))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { g_message ("scanning directory %s", full_dir); }; } while (0 ); |
3223 | |
3224 | gdir = g_dir_open (full_dir, 0, NULL((void*)0)); |
3225 | |
3226 | if (gdir == NULL((void*)0)) |
3227 | return FALSE(0); |
3228 | |
3229 | dir->icons = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); |
3230 | |
3231 | while ((name = g_dir_read_name (gdir))) |
3232 | { |
3233 | gchar *base_name; |
3234 | IconSuffix suffix, hash_suffix; |
3235 | |
3236 | suffix = suffix_from_name (name); |
3237 | if (suffix == ICON_SUFFIX_NONE) |
3238 | continue; |
3239 | |
3240 | base_name = strip_suffix (name); |
3241 | |
3242 | hash_suffix = GPOINTER_TO_INT (g_hash_table_lookup (dir->icons, base_name))((gint) (glong) (g_hash_table_lookup (dir->icons, base_name ))); |
3243 | /* takes ownership of base_name */ |
3244 | g_hash_table_replace (dir->icons, base_name, GUINT_TO_POINTER (hash_suffix|suffix)((gpointer) (gulong) (hash_suffix|suffix))); |
3245 | } |
3246 | |
3247 | g_dir_close (gdir); |
3248 | |
3249 | return g_hash_table_size (dir->icons) > 0; |
3250 | } |
3251 | |
3252 | static gboolean |
3253 | scan_resources (CtkIconThemePrivate *icon_theme G_GNUC_UNUSED__attribute__ ((__unused__)), |
3254 | IconThemeDir *dir, |
3255 | gchar *full_dir) |
3256 | { |
3257 | gint i; |
3258 | gchar **children; |
3259 | |
3260 | CTK_NOTE (ICONTHEME, g_message ("scanning resources %s", full_dir))do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { g_message ("scanning resources %s", full_dir); }; } while (0 ); |
3261 | |
3262 | children = g_resources_enumerate_children (full_dir, 0, NULL((void*)0)); |
3263 | if (!children) |
3264 | return FALSE(0); |
3265 | |
3266 | dir->icons = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); |
3267 | |
3268 | for (i = 0; children[i]; i++) |
3269 | { |
3270 | gchar *base_name; |
3271 | IconSuffix suffix, hash_suffix; |
3272 | |
3273 | suffix = suffix_from_name (children[i]); |
3274 | if (suffix == ICON_SUFFIX_NONE) |
3275 | continue; |
3276 | |
3277 | base_name = strip_suffix (children[i]); |
3278 | |
3279 | hash_suffix = GPOINTER_TO_INT (g_hash_table_lookup (dir->icons, base_name))((gint) (glong) (g_hash_table_lookup (dir->icons, base_name ))); |
3280 | /* takes ownership of base_name */ |
3281 | g_hash_table_replace (dir->icons, base_name, GUINT_TO_POINTER (hash_suffix|suffix)((gpointer) (gulong) (hash_suffix|suffix))); |
3282 | } |
3283 | g_strfreev (children); |
3284 | |
3285 | return g_hash_table_size (dir->icons) > 0; |
3286 | } |
3287 | |
3288 | static void |
3289 | theme_subdir_load (CtkIconTheme *icon_theme, |
3290 | IconTheme *theme, |
3291 | GKeyFile *theme_file, |
3292 | gchar *subdir) |
3293 | { |
3294 | GList *d; |
3295 | gchar *type_string; |
3296 | IconThemeDir *dir; |
3297 | IconThemeDirType type; |
3298 | gchar *context_string; |
3299 | GQuark context; |
3300 | gint size; |
3301 | gint min_size; |
3302 | gint max_size; |
3303 | gint threshold; |
3304 | gchar *full_dir; |
3305 | GError *error = NULL((void*)0); |
3306 | IconThemeDirMtime *dir_mtime; |
3307 | gint scale; |
3308 | gboolean has_icons; |
3309 | |
3310 | size = g_key_file_get_integer (theme_file, subdir, "Size", &error); |
3311 | if (error) |
3312 | { |
3313 | g_error_free (error); |
3314 | g_warning ("Theme directory %s of theme %s has no size field\n", |
3315 | subdir, theme->name); |
3316 | return; |
3317 | } |
3318 | |
3319 | type = ICON_THEME_DIR_THRESHOLD; |
3320 | type_string = g_key_file_get_string (theme_file, subdir, "Type", NULL((void*)0)); |
3321 | if (type_string) |
3322 | { |
3323 | if (strcmp (type_string, "Fixed") == 0) |
3324 | type = ICON_THEME_DIR_FIXED; |
3325 | else if (strcmp (type_string, "Scalable") == 0) |
3326 | type = ICON_THEME_DIR_SCALABLE; |
3327 | else if (strcmp (type_string, "Threshold") == 0) |
3328 | type = ICON_THEME_DIR_THRESHOLD; |
3329 | |
3330 | g_free (type_string); |
3331 | } |
3332 | |
3333 | context = 0; |
3334 | context_string = g_key_file_get_string (theme_file, subdir, "Context", NULL((void*)0)); |
3335 | if (context_string) |
3336 | { |
3337 | context = g_quark_from_string (context_string); |
3338 | g_free (context_string); |
3339 | } |
3340 | |
3341 | if (g_key_file_has_key (theme_file, subdir, "MaxSize", NULL((void*)0))) |
3342 | max_size = g_key_file_get_integer (theme_file, subdir, "MaxSize", NULL((void*)0)); |
3343 | else |
3344 | max_size = size; |
3345 | |
3346 | if (g_key_file_has_key (theme_file, subdir, "MinSize", NULL((void*)0))) |
3347 | min_size = g_key_file_get_integer (theme_file, subdir, "MinSize", NULL((void*)0)); |
3348 | else |
3349 | min_size = size; |
3350 | |
3351 | if (g_key_file_has_key (theme_file, subdir, "Threshold", NULL((void*)0))) |
3352 | threshold = g_key_file_get_integer (theme_file, subdir, "Threshold", NULL((void*)0)); |
3353 | else |
3354 | threshold = 2; |
3355 | |
3356 | if (g_key_file_has_key (theme_file, subdir, "Scale", NULL((void*)0))) |
3357 | scale = g_key_file_get_integer (theme_file, subdir, "Scale", NULL((void*)0)); |
3358 | else |
3359 | scale = 1; |
3360 | |
3361 | for (d = icon_theme->priv->dir_mtimes; d; d = d->next) |
3362 | { |
3363 | dir_mtime = (IconThemeDirMtime *)d->data; |
3364 | |
3365 | if (!dir_mtime->exists) |
3366 | continue; /* directory doesn't exist */ |
3367 | |
3368 | full_dir = g_build_filename (dir_mtime->dir, subdir, NULL((void*)0)); |
3369 | |
3370 | /* First, see if we have a cache for the directory */ |
3371 | if (dir_mtime->cache != NULL((void*)0) || g_file_test (full_dir, G_FILE_TEST_IS_DIR)) |
3372 | { |
3373 | if (dir_mtime->cache == NULL((void*)0)) |
3374 | { |
3375 | /* This will return NULL if the cache doesn't exist or is outdated */ |
3376 | dir_mtime->cache = _ctk_icon_cache_new_for_path (dir_mtime->dir); |
3377 | } |
3378 | |
3379 | dir = g_new0 (IconThemeDir, 1)((IconThemeDir *) g_malloc0_n ((1), sizeof (IconThemeDir))); |
3380 | dir->type = type; |
3381 | dir->is_resource = FALSE(0); |
3382 | dir->context = context; |
3383 | dir->size = size; |
3384 | dir->min_size = min_size; |
3385 | dir->max_size = max_size; |
3386 | dir->threshold = threshold; |
3387 | dir->dir = full_dir; |
3388 | dir->subdir = g_strdup (subdir)g_strdup_inline (subdir); |
3389 | dir->scale = scale; |
3390 | |
3391 | if (dir_mtime->cache != NULL((void*)0)) |
3392 | { |
3393 | dir->cache = _ctk_icon_cache_ref (dir_mtime->cache); |
3394 | dir->subdir_index = _ctk_icon_cache_get_directory_index (dir->cache, dir->subdir); |
3395 | has_icons = _ctk_icon_cache_has_icons (dir->cache, dir->subdir); |
3396 | } |
3397 | else |
3398 | { |
3399 | dir->cache = NULL((void*)0); |
3400 | dir->subdir_index = -1; |
3401 | has_icons = scan_directory (icon_theme->priv, dir, full_dir); |
3402 | } |
3403 | |
3404 | if (has_icons) |
3405 | theme->dirs = g_list_prepend (theme->dirs, dir); |
3406 | else |
3407 | theme_dir_destroy (dir); |
3408 | } |
3409 | else |
3410 | g_free (full_dir); |
3411 | } |
3412 | |
3413 | if (strcmp (theme->name, FALLBACK_ICON_THEME"hicolor") == 0) |
3414 | { |
3415 | for (d = icon_theme->priv->resource_paths; d; d = d->next) |
3416 | { |
3417 | /* Force a trailing / here, to avoid extra copies in GResource */ |
3418 | full_dir = g_build_filename ((const gchar *)d->data, subdir, " ", NULL((void*)0)); |
3419 | full_dir[strlen (full_dir) - 1] = '\0'; |
3420 | dir = g_new0 (IconThemeDir, 1)((IconThemeDir *) g_malloc0_n ((1), sizeof (IconThemeDir))); |
3421 | dir->type = type; |
3422 | dir->is_resource = TRUE(!(0)); |
3423 | dir->context = context; |
3424 | dir->size = size; |
3425 | dir->min_size = min_size; |
3426 | dir->max_size = max_size; |
3427 | dir->threshold = threshold; |
3428 | dir->dir = full_dir; |
3429 | dir->subdir = g_strdup (subdir)g_strdup_inline (subdir); |
3430 | dir->scale = scale; |
3431 | dir->cache = NULL((void*)0); |
3432 | dir->subdir_index = -1; |
3433 | |
3434 | if (scan_resources (icon_theme->priv, dir, full_dir)) |
3435 | theme->dirs = g_list_prepend (theme->dirs, dir); |
3436 | else |
3437 | theme_dir_destroy (dir); |
3438 | } |
3439 | } |
3440 | } |
3441 | |
3442 | /* |
3443 | * CtkIconInfo |
3444 | */ |
3445 | |
3446 | static void ctk_icon_info_class_init (CtkIconInfoClass *klass); |
3447 | |
3448 | G_DEFINE_TYPE (CtkIconInfo, ctk_icon_info, G_TYPE_OBJECT)static void ctk_icon_info_init (CtkIconInfo *self); static void ctk_icon_info_class_init (CtkIconInfoClass *klass); static GType ctk_icon_info_get_type_once (void); static gpointer ctk_icon_info_parent_class = ((void*)0); static gint CtkIconInfo_private_offset; static void ctk_icon_info_class_intern_init (gpointer klass) { ctk_icon_info_parent_class = g_type_class_peek_parent (klass); if (CtkIconInfo_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkIconInfo_private_offset ); ctk_icon_info_class_init ((CtkIconInfoClass*) klass); } __attribute__ ((__unused__)) static inline gpointer ctk_icon_info_get_instance_private (CtkIconInfo *self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkIconInfo_private_offset)))); } GType ctk_icon_info_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); (void) ( 0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0)) ; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = ctk_icon_info_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id ) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id )); })) ; } return static_g_define_type_id; } __attribute__ ( (__noinline__)) static GType ctk_icon_info_get_type_once (void ) { GType g_define_type_id = g_type_register_static_simple (( (GType) ((20) << (2))), g_intern_static_string ("CtkIconInfo" ), sizeof (CtkIconInfoClass), (GClassInitFunc)(void (*)(void) ) ctk_icon_info_class_intern_init, sizeof (CtkIconInfo), (GInstanceInitFunc )(void (*)(void)) ctk_icon_info_init, (GTypeFlags) 0); { {{}; } } return g_define_type_id; } |
3449 | |
3450 | static void |
3451 | ctk_icon_info_init (CtkIconInfo *icon_info) |
3452 | { |
3453 | icon_info->scale = -1.; |
3454 | } |
3455 | |
3456 | static CtkIconInfo * |
3457 | icon_info_new (IconThemeDirType type, |
3458 | gint dir_size, |
3459 | gint dir_scale) |
3460 | { |
3461 | CtkIconInfo *icon_info; |
3462 | |
3463 | icon_info = g_object_new (CTK_TYPE_ICON_INFO(ctk_icon_info_get_type ()), NULL((void*)0)); |
3464 | |
3465 | icon_info->dir_type = type; |
3466 | icon_info->dir_size = dir_size; |
3467 | icon_info->dir_scale = dir_scale; |
3468 | icon_info->unscaled_scale = 1.0; |
3469 | icon_info->is_svg = FALSE(0); |
3470 | icon_info->is_resource = FALSE(0); |
3471 | |
3472 | return icon_info; |
3473 | } |
3474 | |
3475 | /* This only copies whatever is needed to load the pixbuf, |
3476 | * so that we can do a load in a thread without affecting |
3477 | * the original IconInfo from the thread. |
3478 | */ |
3479 | static CtkIconInfo * |
3480 | icon_info_dup (CtkIconInfo *icon_info) |
3481 | { |
3482 | CtkIconInfo *dup; |
3483 | GSList *l; |
3484 | |
3485 | dup = icon_info_new (icon_info->dir_type, icon_info->dir_size, icon_info->dir_scale); |
3486 | |
3487 | dup->filename = g_strdup (icon_info->filename)g_strdup_inline (icon_info->filename); |
3488 | dup->is_svg = icon_info->is_svg; |
3489 | |
3490 | if (icon_info->icon_file) |
3491 | dup->icon_file = g_object_ref (icon_info->icon_file)((__typeof__ (icon_info->icon_file)) (g_object_ref) (icon_info ->icon_file)); |
3492 | if (icon_info->loadable) |
3493 | dup->loadable = g_object_ref (icon_info->loadable)((__typeof__ (icon_info->loadable)) (g_object_ref) (icon_info ->loadable)); |
3494 | if (icon_info->pixbuf) |
3495 | dup->pixbuf = g_object_ref (icon_info->pixbuf)((__typeof__ (icon_info->pixbuf)) (g_object_ref) (icon_info ->pixbuf)); |
3496 | |
3497 | for (l = icon_info->emblem_infos; l != NULL((void*)0); l = l->next) |
3498 | { |
3499 | dup->emblem_infos = |
3500 | g_slist_append (dup->emblem_infos, |
3501 | icon_info_dup (l->data)); |
3502 | } |
3503 | |
3504 | if (icon_info->cache_pixbuf) |
3505 | dup->cache_pixbuf = g_object_ref (icon_info->cache_pixbuf)((__typeof__ (icon_info->cache_pixbuf)) (g_object_ref) (icon_info ->cache_pixbuf)); |
3506 | |
3507 | dup->scale = icon_info->scale; |
3508 | dup->unscaled_scale = icon_info->unscaled_scale; |
3509 | dup->desired_size = icon_info->desired_size; |
3510 | dup->desired_scale = icon_info->desired_scale; |
3511 | dup->forced_size = icon_info->forced_size; |
3512 | dup->emblems_applied = icon_info->emblems_applied; |
3513 | dup->is_resource = icon_info->is_resource; |
3514 | dup->min_size = icon_info->min_size; |
3515 | dup->max_size = icon_info->max_size; |
3516 | dup->symbolic_width = icon_info->symbolic_width; |
3517 | dup->symbolic_height = icon_info->symbolic_height; |
3518 | |
3519 | return dup; |
3520 | } |
3521 | |
3522 | static CtkIconInfo * |
3523 | icon_info_new_builtin (BuiltinIcon *icon) |
3524 | { |
3525 | CtkIconInfo *icon_info = icon_info_new (ICON_THEME_DIR_THRESHOLD, icon->size, 1); |
3526 | |
3527 | icon_info->cache_pixbuf = g_object_ref (icon->pixbuf)((__typeof__ (icon->pixbuf)) (g_object_ref) (icon->pixbuf )); |
3528 | |
3529 | return icon_info; |
3530 | } |
3531 | |
3532 | /** |
3533 | * ctk_icon_info_copy: (skip) |
3534 | * @icon_info: a #CtkIconInfo |
3535 | * |
3536 | * Make a copy of a #CtkIconInfo. |
3537 | * |
3538 | * Returns: (transfer full): the new CtkIconInfo |
3539 | * |
3540 | * Since: 2.4 |
3541 | * |
3542 | * Deprecated: 3.8: Use g_object_ref() |
3543 | */ |
3544 | CtkIconInfo * |
3545 | ctk_icon_info_copy (CtkIconInfo *icon_info) |
3546 | { |
3547 | g_return_val_if_fail (icon_info != NULL, NULL)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return (((void*)0)); } } while (0); |
3548 | return g_object_ref (icon_info)((__typeof__ (icon_info)) (g_object_ref) (icon_info)); |
3549 | } |
3550 | |
3551 | /** |
3552 | * ctk_icon_info_free: (skip) |
3553 | * @icon_info: a #CtkIconInfo |
3554 | * |
3555 | * Free a #CtkIconInfo and associated information |
3556 | * |
3557 | * Since: 2.4 |
3558 | * |
3559 | * Deprecated: 3.8: Use g_object_unref() |
3560 | */ |
3561 | void |
3562 | ctk_icon_info_free (CtkIconInfo *icon_info) |
3563 | { |
3564 | g_return_if_fail (icon_info != NULL)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return ; } } while (0); |
3565 | g_object_unref (icon_info); |
3566 | } |
3567 | |
3568 | static void |
3569 | ctk_icon_info_finalize (GObject *object) |
3570 | { |
3571 | CtkIconInfo *icon_info = (CtkIconInfo *) object; |
3572 | |
3573 | if (icon_info->in_cache) |
3574 | g_hash_table_remove (icon_info->in_cache->priv->info_cache, &icon_info->key); |
3575 | |
3576 | g_strfreev (icon_info->key.icon_names); |
3577 | |
3578 | g_free (icon_info->filename); |
3579 | g_clear_object (&icon_info->icon_file)do { _Static_assert (sizeof *((&icon_info->icon_file)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&icon_info->icon_file))) _pp = ((&icon_info-> icon_file)); __typeof__ (*((&icon_info->icon_file))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr) ; } while (0); |
3580 | |
3581 | g_clear_object (&icon_info->loadable)do { _Static_assert (sizeof *((&icon_info->loadable)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&icon_info->loadable))) _pp = ((&icon_info-> loadable)); __typeof__ (*((&icon_info->loadable))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr) ; } while (0); |
3582 | g_slist_free_full (icon_info->emblem_infos, (GDestroyNotify) g_object_unref); |
3583 | g_clear_object (&icon_info->pixbuf)do { _Static_assert (sizeof *((&icon_info->pixbuf)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&icon_info->pixbuf))) _pp = ((&icon_info->pixbuf )); __typeof__ (*((&icon_info->pixbuf))) _ptr = *_pp; * _pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while ( 0); |
3584 | g_clear_object (&icon_info->proxy_pixbuf)do { _Static_assert (sizeof *((&icon_info->proxy_pixbuf )) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&icon_info->proxy_pixbuf))) _pp = ((&icon_info ->proxy_pixbuf)); __typeof__ (*((&icon_info->proxy_pixbuf ))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref ) (_ptr); } while (0); |
3585 | g_clear_object (&icon_info->cache_pixbuf)do { _Static_assert (sizeof *((&icon_info->cache_pixbuf )) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&icon_info->cache_pixbuf))) _pp = ((&icon_info ->cache_pixbuf)); __typeof__ (*((&icon_info->cache_pixbuf ))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref ) (_ptr); } while (0); |
3586 | g_clear_error (&icon_info->load_error); |
3587 | |
3588 | symbolic_pixbuf_cache_free (icon_info->symbolic_pixbuf_cache); |
3589 | |
3590 | G_OBJECT_CLASS (ctk_icon_info_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_icon_info_parent_class)), (((GType) ((20) << ( 2))))))))->finalize (object); |
3591 | } |
3592 | |
3593 | static void |
3594 | ctk_icon_info_class_init (CtkIconInfoClass *klass) |
3595 | { |
3596 | GObjectClass *gobject_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); |
3597 | |
3598 | gobject_class->finalize = ctk_icon_info_finalize; |
3599 | } |
3600 | |
3601 | /** |
3602 | * ctk_icon_info_get_base_size: |
3603 | * @icon_info: a #CtkIconInfo |
3604 | * |
3605 | * Gets the base size for the icon. The base size |
3606 | * is a size for the icon that was specified by |
3607 | * the icon theme creator. This may be different |
3608 | * than the actual size of image; an example of |
3609 | * this is small emblem icons that can be attached |
3610 | * to a larger icon. These icons will be given |
3611 | * the same base size as the larger icons to which |
3612 | * they are attached. |
3613 | * |
3614 | * Note that for scaled icons the base size does |
3615 | * not include the base scale. |
3616 | * |
3617 | * Returns: the base size, or 0, if no base |
3618 | * size is known for the icon. |
3619 | * |
3620 | * Since: 2.4 |
3621 | */ |
3622 | gint |
3623 | ctk_icon_info_get_base_size (CtkIconInfo *icon_info) |
3624 | { |
3625 | g_return_val_if_fail (icon_info != NULL, 0)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return (0); } } while (0); |
3626 | |
3627 | return icon_info->dir_size; |
3628 | } |
3629 | |
3630 | /** |
3631 | * ctk_icon_info_get_base_scale: |
3632 | * @icon_info: a #CtkIconInfo |
3633 | * |
3634 | * Gets the base scale for the icon. The base scale is a scale |
3635 | * for the icon that was specified by the icon theme creator. |
3636 | * For instance an icon drawn for a high-dpi screen with window |
3637 | * scale 2 for a base size of 32 will be 64 pixels tall and have |
3638 | * a base scale of 2. |
3639 | * |
3640 | * Returns: the base scale |
3641 | * |
3642 | * Since: 3.10 |
3643 | */ |
3644 | gint |
3645 | ctk_icon_info_get_base_scale (CtkIconInfo *icon_info) |
3646 | { |
3647 | g_return_val_if_fail (icon_info != NULL, 0)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return (0); } } while (0); |
3648 | |
3649 | return icon_info->dir_scale; |
3650 | } |
3651 | |
3652 | /** |
3653 | * ctk_icon_info_get_filename: |
3654 | * @icon_info: a #CtkIconInfo |
3655 | * |
3656 | * Gets the filename for the icon. If the %CTK_ICON_LOOKUP_USE_BUILTIN |
3657 | * flag was passed to ctk_icon_theme_lookup_icon(), there may be no |
3658 | * filename if a builtin icon is returned; in this case, you should |
3659 | * use ctk_icon_info_get_builtin_pixbuf(). |
3660 | * |
3661 | * Returns: (nullable) (type filename): the filename for the icon, or %NULL |
3662 | * if ctk_icon_info_get_builtin_pixbuf() should be used instead. |
3663 | * The return value is owned by CTK+ and should not be modified |
3664 | * or freed. |
3665 | * |
3666 | * Since: 2.4 |
3667 | */ |
3668 | const gchar * |
3669 | ctk_icon_info_get_filename (CtkIconInfo *icon_info) |
3670 | { |
3671 | g_return_val_if_fail (icon_info != NULL, NULL)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return (((void*)0)); } } while (0); |
3672 | |
3673 | return icon_info->filename; |
3674 | } |
3675 | |
3676 | /** |
3677 | * ctk_icon_info_get_builtin_pixbuf: |
3678 | * @icon_info: a #CtkIconInfo |
3679 | * |
3680 | * Gets the built-in image for this icon, if any. To allow CTK+ to use |
3681 | * built in icon images, you must pass the %CTK_ICON_LOOKUP_USE_BUILTIN |
3682 | * to ctk_icon_theme_lookup_icon(). |
3683 | * |
3684 | * Returns: (nullable) (transfer none): the built-in image pixbuf, or %NULL. |
3685 | * No extra reference is added to the returned pixbuf, so if |
3686 | * you want to keep it around, you must use g_object_ref(). |
3687 | * The returned image must not be modified. |
3688 | * |
3689 | * Since: 2.4 |
3690 | * |
3691 | * Deprecated: 3.14: This function is deprecated, use |
3692 | * ctk_icon_theme_add_resource_path() instead of builtin icons. |
3693 | */ |
3694 | GdkPixbuf * |
3695 | ctk_icon_info_get_builtin_pixbuf (CtkIconInfo *icon_info) |
3696 | { |
3697 | g_return_val_if_fail (icon_info != NULL, NULL)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return (((void*)0)); } } while (0); |
3698 | |
3699 | if (icon_info->filename) |
3700 | return NULL((void*)0); |
3701 | |
3702 | return icon_info->cache_pixbuf; |
3703 | } |
3704 | |
3705 | /** |
3706 | * ctk_icon_info_is_symbolic: |
3707 | * @icon_info: a #CtkIconInfo |
3708 | * |
3709 | * Checks if the icon is symbolic or not. This currently uses only |
3710 | * the file name and not the file contents for determining this. |
3711 | * This behaviour may change in the future. |
3712 | * |
3713 | * Returns: %TRUE if the icon is symbolic, %FALSE otherwise |
3714 | * |
3715 | * Since: 3.12 |
3716 | */ |
3717 | gboolean |
3718 | ctk_icon_info_is_symbolic (CtkIconInfo *icon_info) |
3719 | { |
3720 | gchar *icon_uri; |
3721 | gboolean is_symbolic; |
3722 | |
3723 | g_return_val_if_fail (CTK_IS_ICON_INFO (icon_info), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_info)); GType __t = ((ctk_icon_info_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "CTK_IS_ICON_INFO (icon_info)"); return ((0)); } } while ( 0); |
3724 | |
3725 | icon_uri = NULL((void*)0); |
3726 | if (icon_info->icon_file) |
3727 | icon_uri = g_file_get_uri (icon_info->icon_file); |
3728 | |
3729 | is_symbolic = (icon_uri != NULL((void*)0)) && (icon_uri_is_symbolic (icon_uri)); |
3730 | g_free (icon_uri); |
3731 | |
3732 | return is_symbolic; |
3733 | } |
3734 | |
3735 | static GdkPixbuf * |
3736 | apply_emblems_to_pixbuf (GdkPixbuf *pixbuf, |
3737 | CtkIconInfo *info) |
3738 | { |
3739 | GdkPixbuf *icon = NULL((void*)0); |
3740 | gint w, h, pos; |
3741 | GSList *l; |
3742 | |
3743 | if (info->emblem_infos == NULL((void*)0)) |
3744 | return NULL((void*)0); |
3745 | |
3746 | w = gdk_pixbuf_get_width (pixbuf); |
3747 | h = gdk_pixbuf_get_height (pixbuf); |
3748 | |
3749 | for (l = info->emblem_infos, pos = 0; l; l = l->next, pos++) |
3750 | { |
3751 | CtkIconInfo *emblem_info = l->data; |
3752 | |
3753 | if (icon_info_ensure_scale_and_pixbuf (emblem_info)) |
3754 | { |
3755 | GdkPixbuf *emblem = emblem_info->pixbuf; |
3756 | gint ew, eh; |
3757 | gint x = 0, y = 0; /* silence compiler */ |
3758 | gdouble scale; |
3759 | |
3760 | ew = gdk_pixbuf_get_width (emblem); |
3761 | eh = gdk_pixbuf_get_height (emblem); |
3762 | if (ew >= w) |
3763 | { |
3764 | scale = 0.75; |
3765 | ew = ew * 0.75; |
3766 | eh = eh * 0.75; |
3767 | } |
3768 | else |
3769 | scale = 1.0; |
3770 | |
3771 | switch (pos % 4) |
3772 | { |
3773 | case 0: |
3774 | x = w - ew; |
3775 | y = h - eh; |
3776 | break; |
3777 | case 1: |
3778 | x = w - ew; |
3779 | y = 0; |
3780 | break; |
3781 | case 2: |
3782 | x = 0; |
3783 | y = h - eh; |
3784 | break; |
3785 | case 3: |
3786 | x = 0; |
3787 | y = 0; |
3788 | break; |
3789 | } |
3790 | |
3791 | if (icon == NULL((void*)0)) |
3792 | { |
3793 | icon = gdk_pixbuf_copy (pixbuf); |
3794 | if (icon == NULL((void*)0)) |
3795 | break; |
3796 | } |
3797 | |
3798 | gdk_pixbuf_composite (emblem, icon, x, y, ew, eh, x, y, |
3799 | scale, scale, GDK_INTERP_BILINEAR, 255); |
3800 | } |
3801 | } |
3802 | |
3803 | return icon; |
3804 | } |
3805 | |
3806 | /* Combine the icon with all emblems, the first emblem is placed |
3807 | * in the southeast corner. Scale emblems to be at most 3/4 of the |
3808 | * size of the icon itself. |
3809 | */ |
3810 | static void |
3811 | apply_emblems (CtkIconInfo *info) |
3812 | { |
3813 | GdkPixbuf *icon; |
3814 | |
3815 | if (info->emblems_applied) |
3816 | return; |
3817 | |
3818 | icon = apply_emblems_to_pixbuf (info->pixbuf, info); |
3819 | |
3820 | if (icon) |
3821 | { |
3822 | g_object_unref (info->pixbuf); |
3823 | info->pixbuf = icon; |
3824 | info->emblems_applied = TRUE(!(0)); |
3825 | } |
3826 | } |
3827 | |
3828 | /* If this returns TRUE, its safe to call icon_info_ensure_scale_and_pixbuf |
3829 | * without blocking |
3830 | */ |
3831 | static gboolean |
3832 | icon_info_get_pixbuf_ready (CtkIconInfo *icon_info) |
3833 | { |
3834 | if (icon_info->pixbuf && |
3835 | (icon_info->emblem_infos == NULL((void*)0) || icon_info->emblems_applied)) |
3836 | return TRUE(!(0)); |
3837 | |
3838 | if (icon_info->load_error) |
3839 | return TRUE(!(0)); |
3840 | |
3841 | return FALSE(0); |
3842 | } |
3843 | |
3844 | /* This function contains the complicated logic for deciding |
3845 | * on the size at which to load the icon and loading it at |
3846 | * that size. |
3847 | */ |
3848 | static gboolean |
3849 | icon_info_ensure_scale_and_pixbuf (CtkIconInfo *icon_info) |
3850 | { |
3851 | gint image_width, image_height, image_size; |
3852 | gint scaled_desired_size; |
3853 | GdkPixbuf *source_pixbuf; |
3854 | gdouble dir_scale; |
3855 | |
3856 | if (icon_info->pixbuf) |
3857 | { |
3858 | apply_emblems (icon_info); |
3859 | return TRUE(!(0)); |
3860 | } |
3861 | |
3862 | if (icon_info->load_error) |
3863 | return FALSE(0); |
3864 | |
3865 | if (icon_info->icon_file && !icon_info->loadable) |
3866 | icon_info->loadable = G_LOADABLE_ICON (g_file_icon_new (icon_info->icon_file))((((GLoadableIcon*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((g_file_icon_new (icon_info->icon_file))), ((g_loadable_icon_get_type ())))))); |
3867 | |
3868 | scaled_desired_size = icon_info->desired_size * icon_info->desired_scale; |
3869 | |
3870 | dir_scale = icon_info->dir_scale; |
3871 | |
3872 | /* In many cases, the scale can be determined without actual access |
3873 | * to the icon file. This is generally true when we have a size |
3874 | * for the directory where the icon is; the image size doesn't |
3875 | * matter in that case. |
3876 | */ |
3877 | if (icon_info->forced_size || |
3878 | icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) |
3879 | icon_info->scale = -1; |
3880 | else if (icon_info->dir_type == ICON_THEME_DIR_FIXED || |
3881 | icon_info->dir_type == ICON_THEME_DIR_THRESHOLD) |
3882 | icon_info->scale = icon_info->unscaled_scale; |
3883 | else if (icon_info->dir_type == ICON_THEME_DIR_SCALABLE) |
3884 | { |
3885 | /* For svg icons, treat scalable directories as if they had |
3886 | * a Scale=<desired_scale> entry. In particular, this means |
3887 | * spinners that are restriced to size 32 will loaded at size |
3888 | * up to 64 with Scale=2. |
3889 | */ |
3890 | if (icon_info->is_svg) |
3891 | dir_scale = icon_info->desired_scale; |
3892 | |
3893 | if (scaled_desired_size < icon_info->min_size * dir_scale) |
3894 | icon_info->scale = (gdouble) icon_info->min_size / (gdouble) icon_info->dir_size; |
3895 | else if (scaled_desired_size > icon_info->max_size * dir_scale) |
3896 | icon_info->scale = (gdouble) icon_info->max_size / (gdouble) icon_info->dir_size; |
3897 | else |
3898 | icon_info->scale = (gdouble) scaled_desired_size / (icon_info->dir_size * dir_scale); |
3899 | } |
3900 | |
3901 | /* At this point, we need to actually get the icon; either from the |
3902 | * builtin image or by loading the file |
3903 | */ |
3904 | source_pixbuf = NULL((void*)0); |
3905 | if (icon_info->cache_pixbuf) |
3906 | source_pixbuf = g_object_ref (icon_info->cache_pixbuf)((__typeof__ (icon_info->cache_pixbuf)) (g_object_ref) (icon_info ->cache_pixbuf)); |
3907 | else if (icon_info->is_resource) |
3908 | { |
3909 | if (icon_info->is_svg) |
3910 | { |
3911 | gint size; |
3912 | |
3913 | if (icon_info->forced_size || icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) |
3914 | size = scaled_desired_size; |
3915 | else |
3916 | size = icon_info->dir_size * dir_scale * icon_info->scale; |
3917 | |
3918 | if (size == 0) |
3919 | source_pixbuf = _gdk_pixbuf_new_from_resource_scaled (icon_info->filename, |
3920 | icon_info->desired_scale, |
3921 | &icon_info->load_error); |
3922 | else |
3923 | source_pixbuf = gdk_pixbuf_new_from_resource_at_scale (icon_info->filename, |
3924 | size, size, TRUE(!(0)), |
3925 | &icon_info->load_error); |
3926 | } |
3927 | else |
3928 | source_pixbuf = gdk_pixbuf_new_from_resource (icon_info->filename, |
3929 | &icon_info->load_error); |
3930 | } |
3931 | else |
3932 | { |
3933 | GInputStream *stream; |
3934 | |
3935 | /* TODO: We should have a load_at_scale */ |
3936 | stream = g_loadable_icon_load (icon_info->loadable, |
3937 | scaled_desired_size, |
3938 | NULL((void*)0), NULL((void*)0), |
3939 | &icon_info->load_error); |
3940 | if (stream) |
3941 | { |
3942 | /* SVG icons are a special case - we just immediately scale them |
3943 | * to the desired size |
3944 | */ |
3945 | if (icon_info->is_svg) |
3946 | { |
3947 | gint size; |
3948 | |
3949 | if (icon_info->forced_size || icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) |
3950 | size = scaled_desired_size; |
3951 | else |
3952 | size = icon_info->dir_size * dir_scale * icon_info->scale; |
3953 | if (size == 0) |
3954 | source_pixbuf = _gdk_pixbuf_new_from_stream_scaled (stream, |
3955 | icon_info->desired_scale, |
3956 | NULL((void*)0), |
3957 | &icon_info->load_error); |
3958 | else |
3959 | source_pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream, |
3960 | size, size, |
3961 | TRUE(!(0)), NULL((void*)0), |
3962 | &icon_info->load_error); |
3963 | } |
3964 | else |
3965 | source_pixbuf = gdk_pixbuf_new_from_stream (stream, |
3966 | NULL((void*)0), |
3967 | &icon_info->load_error); |
3968 | g_object_unref (stream); |
3969 | } |
3970 | } |
3971 | |
3972 | if (!source_pixbuf) |
3973 | { |
3974 | static gboolean warn_about_load_failure = TRUE(!(0)); |
3975 | |
3976 | if (warn_about_load_failure) |
3977 | { |
3978 | gchar *path; |
3979 | |
3980 | if (icon_info->is_resource) |
3981 | path = g_strdup (icon_info->filename)g_strdup_inline (icon_info->filename); |
3982 | else if (G_IS_FILE (icon_info->loadable)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (icon_info->loadable)); GType __t = ((g_file_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } ))))) |
3983 | path = g_file_get_path (G_FILE (icon_info->loadable)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((icon_info->loadable)), ((g_file_get_type ()))))))); |
3984 | else |
3985 | path = g_strdup ("icon theme")g_strdup_inline ("icon theme"); |
3986 | |
3987 | g_warning ("Could not load a pixbuf from %s.\n" |
3988 | "This may indicate that pixbuf loaders or the mime database could not be found.", |
3989 | path); |
3990 | g_free (path); |
3991 | |
3992 | warn_about_load_failure = FALSE(0); |
3993 | } |
3994 | |
3995 | return FALSE(0); |
3996 | } |
3997 | |
3998 | /* Do scale calculations that depend on the image size |
3999 | */ |
4000 | image_width = gdk_pixbuf_get_width (source_pixbuf); |
4001 | image_height = gdk_pixbuf_get_height (source_pixbuf); |
4002 | image_size = MAX (image_width, image_height)(((image_width) > (image_height)) ? (image_width) : (image_height )); |
4003 | |
4004 | if (icon_info->is_svg) |
4005 | icon_info->scale = image_size / 1000.; |
4006 | else if (icon_info->scale < 0.0) |
4007 | { |
4008 | if (image_size > 0 && scaled_desired_size > 0) |
4009 | icon_info->scale = (gdouble)scaled_desired_size / (gdouble)image_size; |
4010 | else |
4011 | icon_info->scale = 1.0; |
4012 | |
4013 | if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED && |
4014 | !icon_info->forced_size) |
4015 | icon_info->scale = MIN (icon_info->scale, 1.0)(((icon_info->scale) < (1.0)) ? (icon_info->scale) : (1.0)); |
4016 | } |
4017 | |
4018 | if (icon_info->is_svg) |
4019 | icon_info->pixbuf = source_pixbuf; |
4020 | else if (icon_info->scale == 1.0) |
4021 | icon_info->pixbuf = source_pixbuf; |
4022 | else |
4023 | { |
4024 | icon_info->pixbuf = gdk_pixbuf_scale_simple (source_pixbuf, |
4025 | MAX (1, 0.5 + image_width * icon_info->scale)(((1) > (0.5 + image_width * icon_info->scale)) ? (1) : (0.5 + image_width * icon_info->scale)), |
4026 | MAX (1, 0.5 + image_height * icon_info->scale)(((1) > (0.5 + image_height * icon_info->scale)) ? (1) : (0.5 + image_height * icon_info->scale)), |
4027 | GDK_INTERP_BILINEAR); |
4028 | g_object_unref (source_pixbuf); |
4029 | } |
4030 | |
4031 | apply_emblems (icon_info); |
4032 | |
4033 | return TRUE(!(0)); |
4034 | } |
4035 | |
4036 | static void |
4037 | proxy_pixbuf_destroy (guchar *pixels G_GNUC_UNUSED__attribute__ ((__unused__)), |
4038 | gpointer data) |
4039 | { |
4040 | CtkIconInfo *icon_info = data; |
4041 | CtkIconTheme *icon_theme = icon_info->in_cache; |
4042 | |
4043 | g_assert (icon_info->proxy_pixbuf != NULL)do { if (icon_info->proxy_pixbuf != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkicontheme.c", 4043, ((const char*) (__func__)), "icon_info->proxy_pixbuf != NULL" ); } while (0); |
4044 | icon_info->proxy_pixbuf = NULL((void*)0); |
4045 | |
4046 | /* Keep it alive a bit longer */ |
4047 | if (icon_theme != NULL((void*)0)) |
4048 | ensure_in_lru_cache (icon_theme, icon_info); |
4049 | |
4050 | g_object_unref (icon_info); |
4051 | } |
4052 | |
4053 | /** |
4054 | * ctk_icon_info_load_icon: |
4055 | * @icon_info: a #CtkIconInfo from ctk_icon_theme_lookup_icon() |
4056 | * @error: (allow-none): location to store error information on failure, |
4057 | * or %NULL. |
4058 | * |
4059 | * Renders an icon previously looked up in an icon theme using |
4060 | * ctk_icon_theme_lookup_icon(); the size will be based on the size |
4061 | * passed to ctk_icon_theme_lookup_icon(). Note that the resulting |
4062 | * pixbuf may not be exactly this size; an icon theme may have icons |
4063 | * that differ slightly from their nominal sizes, and in addition CTK+ |
4064 | * will avoid scaling icons that it considers sufficiently close to the |
4065 | * requested size or for which the source image would have to be scaled |
4066 | * up too far. (This maintains sharpness.). This behaviour can be changed |
4067 | * by passing the %CTK_ICON_LOOKUP_FORCE_SIZE flag when obtaining |
4068 | * the #CtkIconInfo. If this flag has been specified, the pixbuf |
4069 | * returned by this function will be scaled to the exact size. |
4070 | * |
4071 | * Returns: (transfer full): the rendered icon; this may be a newly |
4072 | * created icon or a new reference to an internal icon, so you must |
4073 | * not modify the icon. Use g_object_unref() to release your reference |
4074 | * to the icon. |
4075 | * |
4076 | * Since: 2.4 |
4077 | */ |
4078 | GdkPixbuf * |
4079 | ctk_icon_info_load_icon (CtkIconInfo *icon_info, |
4080 | GError **error) |
4081 | { |
4082 | g_return_val_if_fail (icon_info != NULL, NULL)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return (((void*)0)); } } while (0); |
4083 | g_return_val_if_fail (error == NULL || *error == NULL, NULL)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return (((void*)0)); } } while (0); |
4084 | |
4085 | if (!icon_info_ensure_scale_and_pixbuf (icon_info)) |
4086 | { |
4087 | if (icon_info->load_error) |
4088 | { |
4089 | if (error) |
4090 | *error = g_error_copy (icon_info->load_error); |
4091 | } |
4092 | else |
4093 | { |
4094 | g_set_error_literal (error, |
4095 | CTK_ICON_THEME_ERRORctk_icon_theme_error_quark (), |
4096 | CTK_ICON_THEME_NOT_FOUND, |
4097 | _("Failed to load icon")((char *) g_dgettext ("ctk30", "Failed to load icon"))); |
4098 | } |
4099 | |
4100 | return NULL((void*)0); |
4101 | } |
4102 | |
4103 | /* Instead of returning the pixbuf directly we return a proxy |
4104 | * to it that we don't own (but that shares the data with the |
4105 | * one we own). This way we can know when it is freed and ensure |
4106 | * the IconInfo is alive (and thus cached) while the pixbuf is |
4107 | * still alive. |
4108 | */ |
4109 | if (icon_info->proxy_pixbuf != NULL((void*)0)) |
4110 | return g_object_ref (icon_info->proxy_pixbuf)((__typeof__ (icon_info->proxy_pixbuf)) (g_object_ref) (icon_info ->proxy_pixbuf)); |
4111 | |
4112 | icon_info->proxy_pixbuf = |
4113 | gdk_pixbuf_new_from_data (gdk_pixbuf_get_pixels (icon_info->pixbuf), |
4114 | gdk_pixbuf_get_colorspace (icon_info->pixbuf), |
4115 | gdk_pixbuf_get_has_alpha (icon_info->pixbuf), |
4116 | gdk_pixbuf_get_bits_per_sample (icon_info->pixbuf), |
4117 | gdk_pixbuf_get_width (icon_info->pixbuf), |
4118 | gdk_pixbuf_get_height (icon_info->pixbuf), |
4119 | gdk_pixbuf_get_rowstride (icon_info->pixbuf), |
4120 | proxy_pixbuf_destroy, |
4121 | g_object_ref (icon_info)((__typeof__ (icon_info)) (g_object_ref) (icon_info))); |
4122 | |
4123 | return icon_info->proxy_pixbuf; |
4124 | } |
4125 | |
4126 | /** |
4127 | * ctk_icon_info_load_surface: |
4128 | * @icon_info: a #CtkIconInfo from ctk_icon_theme_lookup_icon() |
4129 | * @for_window: (allow-none): #CdkWindow to optimize drawing for, or %NULL |
4130 | * @error: (allow-none): location for error information on failure, or %NULL |
4131 | * |
4132 | * Renders an icon previously looked up in an icon theme using |
4133 | * ctk_icon_theme_lookup_icon(); the size will be based on the size |
4134 | * passed to ctk_icon_theme_lookup_icon(). Note that the resulting |
4135 | * surface may not be exactly this size; an icon theme may have icons |
4136 | * that differ slightly from their nominal sizes, and in addition CTK+ |
4137 | * will avoid scaling icons that it considers sufficiently close to the |
4138 | * requested size or for which the source image would have to be scaled |
4139 | * up too far. (This maintains sharpness.). This behaviour can be changed |
4140 | * by passing the %CTK_ICON_LOOKUP_FORCE_SIZE flag when obtaining |
4141 | * the #CtkIconInfo. If this flag has been specified, the pixbuf |
4142 | * returned by this function will be scaled to the exact size. |
4143 | * |
4144 | * Returns: (transfer full): the rendered icon; this may be a newly |
4145 | * created icon or a new reference to an internal icon, so you must |
4146 | * not modify the icon. Use cairo_surface_destroy() to release your |
4147 | * reference to the icon. |
4148 | * |
4149 | * Since: 3.10 |
4150 | */ |
4151 | cairo_surface_t * |
4152 | ctk_icon_info_load_surface (CtkIconInfo *icon_info, |
4153 | CdkWindow *for_window, |
4154 | GError **error) |
4155 | { |
4156 | GdkPixbuf *pixbuf; |
4157 | cairo_surface_t *surface; |
4158 | |
4159 | g_return_val_if_fail (icon_info != NULL, NULL)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return (((void*)0)); } } while (0); |
4160 | g_return_val_if_fail (error == NULL || *error == NULL, NULL)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__) ), "error == NULL || *error == NULL"); return (((void*)0)); } } while (0); |
4161 | |
4162 | pixbuf = ctk_icon_info_load_icon (icon_info, error); |
4163 | |
4164 | if (pixbuf == NULL((void*)0)) |
4165 | return NULL((void*)0); |
4166 | |
4167 | surface = cdk_cairo_surface_create_from_pixbuf (pixbuf, icon_info->desired_scale, for_window); |
4168 | g_object_unref (pixbuf); |
4169 | |
4170 | return surface; |
4171 | } |
4172 | |
4173 | static void |
4174 | load_icon_thread (GTask *task, |
4175 | gpointer source_object G_GNUC_UNUSED__attribute__ ((__unused__)), |
4176 | gpointer task_data, |
4177 | GCancellable *cancellable G_GNUC_UNUSED__attribute__ ((__unused__))) |
4178 | { |
4179 | CtkIconInfo *dup = task_data; |
4180 | |
4181 | (void)icon_info_ensure_scale_and_pixbuf (dup); |
4182 | g_task_return_pointer (task, NULL((void*)0), NULL((void*)0)); |
4183 | } |
4184 | |
4185 | /** |
4186 | * ctk_icon_info_load_icon_async: |
4187 | * @icon_info: a #CtkIconInfo from ctk_icon_theme_lookup_icon() |
4188 | * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore |
4189 | * @callback: (scope async): a #GAsyncReadyCallback to call when the |
4190 | * request is satisfied |
4191 | * @user_data: (closure): the data to pass to callback function |
4192 | * |
4193 | * Asynchronously load, render and scale an icon previously looked up |
4194 | * from the icon theme using ctk_icon_theme_lookup_icon(). |
4195 | * |
4196 | * For more details, see ctk_icon_info_load_icon() which is the synchronous |
4197 | * version of this call. |
4198 | * |
4199 | * Since: 3.8 |
4200 | */ |
4201 | void |
4202 | ctk_icon_info_load_icon_async (CtkIconInfo *icon_info, |
4203 | GCancellable *cancellable, |
4204 | GAsyncReadyCallback callback, |
4205 | gpointer user_data) |
4206 | { |
4207 | GTask *task; |
4208 | GdkPixbuf *pixbuf; |
4209 | CtkIconInfo *dup; |
4210 | GError *error = NULL((void*)0); |
4211 | |
4212 | task = g_task_new (icon_info, cancellable, callback, user_data); |
4213 | |
4214 | if (icon_info_get_pixbuf_ready (icon_info)) |
4215 | { |
4216 | pixbuf = ctk_icon_info_load_icon (icon_info, &error); |
4217 | if (pixbuf == NULL((void*)0)) |
4218 | g_task_return_error (task, error); |
4219 | else |
4220 | g_task_return_pointer (task, pixbuf, g_object_unref); |
4221 | g_object_unref (task); |
4222 | } |
4223 | else |
4224 | { |
4225 | dup = icon_info_dup (icon_info); |
4226 | g_task_set_task_data (task, dup, g_object_unref); |
4227 | g_task_run_in_thread (task, load_icon_thread); |
4228 | g_object_unref (task); |
4229 | } |
4230 | } |
4231 | |
4232 | /** |
4233 | * ctk_icon_info_load_icon_finish: |
4234 | * @icon_info: a #CtkIconInfo from ctk_icon_theme_lookup_icon() |
4235 | * @res: a #GAsyncResult |
4236 | * @error: (allow-none): location to store error information on failure, |
4237 | * or %NULL. |
4238 | * |
4239 | * Finishes an async icon load, see ctk_icon_info_load_icon_async(). |
4240 | * |
4241 | * Returns: (transfer full): the rendered icon; this may be a newly |
4242 | * created icon or a new reference to an internal icon, so you must |
4243 | * not modify the icon. Use g_object_unref() to release your reference |
4244 | * to the icon. |
4245 | * |
4246 | * Since: 3.8 |
4247 | */ |
4248 | GdkPixbuf * |
4249 | ctk_icon_info_load_icon_finish (CtkIconInfo *icon_info, |
4250 | GAsyncResult *result, |
4251 | GError **error) |
4252 | { |
4253 | GTask *task = G_TASK (result)((((GTask*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((result)), ((g_task_get_type ())))))); |
4254 | CtkIconInfo *dup; |
4255 | |
4256 | g_return_val_if_fail (g_task_is_valid (result, icon_info), NULL)do { if ((g_task_is_valid (result, icon_info))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "g_task_is_valid (result, icon_info)" ); return (((void*)0)); } } while (0); |
4257 | |
4258 | dup = g_task_get_task_data (task); |
4259 | if (dup == NULL((void*)0) || g_task_had_error (task)) |
4260 | return g_task_propagate_pointer (task, error); |
4261 | |
4262 | /* We ran the thread and it was not cancelled */ |
4263 | |
4264 | /* Check if someone else updated the icon_info in between */ |
4265 | if (!icon_info_get_pixbuf_ready (icon_info)) |
4266 | { |
4267 | /* If not, copy results from dup back to icon_info */ |
4268 | icon_info->emblems_applied = dup->emblems_applied; |
4269 | icon_info->scale = dup->scale; |
4270 | g_clear_object (&icon_info->pixbuf)do { _Static_assert (sizeof *((&icon_info->pixbuf)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (((&icon_info->pixbuf))) _pp = ((&icon_info->pixbuf )); __typeof__ (*((&icon_info->pixbuf))) _ptr = *_pp; * _pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while ( 0); |
4271 | if (dup->pixbuf) |
4272 | icon_info->pixbuf = g_object_ref (dup->pixbuf)((__typeof__ (dup->pixbuf)) (g_object_ref) (dup->pixbuf )); |
4273 | g_clear_error (&icon_info->load_error); |
4274 | if (dup->load_error) |
4275 | icon_info->load_error = g_error_copy (dup->load_error); |
4276 | } |
4277 | |
4278 | g_assert (icon_info_get_pixbuf_ready (icon_info))do { if (icon_info_get_pixbuf_ready (icon_info)) ; else g_assertion_message_expr ("Ctk", "ctkicontheme.c", 4278, ((const char*) (__func__)), "icon_info_get_pixbuf_ready (icon_info)" ); } while (0); |
4279 | |
4280 | /* This is now guaranteed to not block */ |
4281 | return ctk_icon_info_load_icon (icon_info, error); |
4282 | } |
4283 | |
4284 | static void |
4285 | proxy_symbolic_pixbuf_destroy (guchar *pixels, |
4286 | gpointer data) |
4287 | { |
4288 | CtkIconInfo *icon_info = data; |
4289 | CtkIconTheme *icon_theme = icon_info->in_cache; |
4290 | SymbolicPixbufCache *symbolic_cache; |
4291 | |
4292 | for (symbolic_cache = icon_info->symbolic_pixbuf_cache; |
4293 | symbolic_cache != NULL((void*)0); |
4294 | symbolic_cache = symbolic_cache->next) |
4295 | { |
4296 | if (symbolic_cache->proxy_pixbuf != NULL((void*)0) && |
4297 | gdk_pixbuf_get_pixels (symbolic_cache->proxy_pixbuf) == pixels) |
4298 | break; |
4299 | } |
4300 | |
4301 | g_assert (symbolic_cache != NULL)do { if (symbolic_cache != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkicontheme.c", 4301, ((const char*) (__func__)), "symbolic_cache != NULL" ); } while (0); |
4302 | g_assert (symbolic_cache->proxy_pixbuf != NULL)do { if (symbolic_cache->proxy_pixbuf != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkicontheme.c", 4302, ((const char*) (__func__)), "symbolic_cache->proxy_pixbuf != NULL" ); } while (0); |
4303 | |
4304 | symbolic_cache->proxy_pixbuf = NULL((void*)0); |
4305 | |
4306 | /* Keep it alive a bit longer */ |
4307 | if (icon_theme != NULL((void*)0)) |
4308 | ensure_in_lru_cache (icon_theme, icon_info); |
4309 | |
4310 | g_object_unref (icon_info); |
4311 | } |
4312 | |
4313 | static GdkPixbuf * |
4314 | symbolic_cache_get_proxy (SymbolicPixbufCache *symbolic_cache, |
4315 | CtkIconInfo *icon_info) |
4316 | { |
4317 | if (symbolic_cache->proxy_pixbuf) |
4318 | return g_object_ref (symbolic_cache->proxy_pixbuf)((__typeof__ (symbolic_cache->proxy_pixbuf)) (g_object_ref ) (symbolic_cache->proxy_pixbuf)); |
4319 | |
4320 | symbolic_cache->proxy_pixbuf = |
4321 | gdk_pixbuf_new_from_data (gdk_pixbuf_get_pixels (symbolic_cache->pixbuf), |
4322 | gdk_pixbuf_get_colorspace (symbolic_cache->pixbuf), |
4323 | gdk_pixbuf_get_has_alpha (symbolic_cache->pixbuf), |
4324 | gdk_pixbuf_get_bits_per_sample (symbolic_cache->pixbuf), |
4325 | gdk_pixbuf_get_width (symbolic_cache->pixbuf), |
4326 | gdk_pixbuf_get_height (symbolic_cache->pixbuf), |
4327 | gdk_pixbuf_get_rowstride (symbolic_cache->pixbuf), |
4328 | proxy_symbolic_pixbuf_destroy, |
4329 | g_object_ref (icon_info)((__typeof__ (icon_info)) (g_object_ref) (icon_info))); |
4330 | |
4331 | return symbolic_cache->proxy_pixbuf; |
4332 | } |
4333 | |
4334 | static gchar * |
4335 | rgba_to_string_noalpha (const CdkRGBA *rgba) |
4336 | { |
4337 | CdkRGBA color; |
4338 | |
4339 | color = *rgba; |
4340 | color.alpha = 1.0; |
4341 | |
4342 | return cdk_rgba_to_string (&color); |
4343 | } |
4344 | |
4345 | static void |
4346 | rgba_to_pixel(const CdkRGBA *rgba, |
4347 | guint8 pixel[4]) |
4348 | { |
4349 | pixel[0] = rgba->red * 255; |
4350 | pixel[1] = rgba->green * 255; |
4351 | pixel[2] = rgba->blue * 255; |
4352 | pixel[3] = 255; |
4353 | } |
4354 | |
4355 | GdkPixbuf * |
4356 | ctk_icon_theme_color_symbolic_pixbuf (GdkPixbuf *symbolic, |
4357 | const CdkRGBA *fg_color, |
4358 | const CdkRGBA *success_color, |
4359 | const CdkRGBA *warning_color, |
4360 | const CdkRGBA *error_color) |
4361 | { |
4362 | int width, height, x, y, src_stride, dst_stride; |
4363 | guchar *src_data, *dst_data; |
4364 | guchar *src_row, *dst_row; |
4365 | int alpha; |
4366 | GdkPixbuf *colored; |
4367 | guint8 fg_pixel[4], success_pixel[4], warning_pixel[4], error_pixel[4]; |
4368 | |
4369 | alpha = fg_color->alpha * 255; |
4370 | |
4371 | rgba_to_pixel (fg_color, fg_pixel); |
4372 | rgba_to_pixel (success_color, success_pixel); |
4373 | rgba_to_pixel (warning_color, warning_pixel); |
4374 | rgba_to_pixel (error_color, error_pixel); |
4375 | |
4376 | width = gdk_pixbuf_get_width (symbolic); |
4377 | height = gdk_pixbuf_get_height (symbolic); |
4378 | |
4379 | colored = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE(!(0)), 8, width, height); |
4380 | |
4381 | src_stride = gdk_pixbuf_get_rowstride (symbolic); |
4382 | src_data = gdk_pixbuf_get_pixels (symbolic); |
4383 | |
4384 | dst_data = gdk_pixbuf_get_pixels (colored); |
4385 | dst_stride = gdk_pixbuf_get_rowstride (colored); |
4386 | |
4387 | for (y = 0; y < height; y++) |
4388 | { |
4389 | src_row = src_data + src_stride * y; |
4390 | dst_row = dst_data + dst_stride * y; |
4391 | for (x = 0; x < width; x++) |
4392 | { |
4393 | guint r, g, b, a; |
4394 | int c1, c2, c3, c4; |
4395 | |
4396 | a = src_row[3]; |
4397 | dst_row[3] = a * alpha / 255; |
4398 | |
4399 | if (a == 0) |
4400 | { |
4401 | dst_row[0] = 0; |
4402 | dst_row[1] = 0; |
4403 | dst_row[2] = 0; |
4404 | } |
4405 | else |
4406 | { |
4407 | c2 = src_row[0]; |
4408 | c3 = src_row[1]; |
4409 | c4 = src_row[2]; |
4410 | |
4411 | if (c2 == 0 && c3 == 0 && c4 == 0) |
4412 | { |
4413 | dst_row[0] = fg_pixel[0]; |
4414 | dst_row[1] = fg_pixel[1]; |
4415 | dst_row[2] = fg_pixel[2]; |
4416 | } |
4417 | else |
4418 | { |
4419 | c1 = 255 - c2 - c3 - c4; |
4420 | |
4421 | r = fg_pixel[0] * c1 + success_pixel[0] * c2 + warning_pixel[0] * c3 + error_pixel[0] * c4; |
4422 | g = fg_pixel[1] * c1 + success_pixel[1] * c2 + warning_pixel[1] * c3 + error_pixel[1] * c4; |
4423 | b = fg_pixel[2] * c1 + success_pixel[2] * c2 + warning_pixel[2] * c3 + error_pixel[2] * c4; |
4424 | |
4425 | dst_row[0] = r / 255; |
4426 | dst_row[1] = g / 255; |
4427 | dst_row[2] = b / 255; |
4428 | } |
4429 | } |
4430 | |
4431 | src_row += 4; |
4432 | dst_row += 4; |
4433 | } |
4434 | } |
4435 | |
4436 | return colored; |
4437 | } |
4438 | |
4439 | static GdkPixbuf * |
4440 | ctk_icon_info_load_symbolic_png (CtkIconInfo *icon_info, |
4441 | const CdkRGBA *fg, |
4442 | const CdkRGBA *success_color, |
4443 | const CdkRGBA *warning_color, |
4444 | const CdkRGBA *error_color, |
4445 | GError **error) |
4446 | { |
4447 | CdkRGBA fg_default = { 0.7450980392156863, 0.7450980392156863, 0.7450980392156863, 1.0}; |
4448 | CdkRGBA success_default = { 0.3046921492332342,0.6015716792553597, 0.023437857633325704, 1.0}; |
4449 | CdkRGBA warning_default = {0.9570458533607996, 0.47266346227206835, 0.2421911955443656, 1.0 }; |
4450 | CdkRGBA error_default = { 0.796887159533074, 0 ,0, 1.0 }; |
4451 | |
4452 | if (!icon_info_ensure_scale_and_pixbuf (icon_info)) |
4453 | { |
4454 | if (icon_info->load_error) |
4455 | { |
4456 | if (error) |
4457 | *error = g_error_copy (icon_info->load_error); |
4458 | } |
4459 | else |
4460 | { |
4461 | g_set_error_literal (error, |
4462 | CTK_ICON_THEME_ERRORctk_icon_theme_error_quark (), |
4463 | CTK_ICON_THEME_NOT_FOUND, |
4464 | _("Failed to load icon")((char *) g_dgettext ("ctk30", "Failed to load icon"))); |
4465 | } |
4466 | |
4467 | return NULL((void*)0); |
4468 | } |
4469 | |
4470 | return ctk_icon_theme_color_symbolic_pixbuf (icon_info->pixbuf, |
4471 | fg ? fg : &fg_default, |
4472 | success_color ? success_color : &success_default, |
4473 | warning_color ? warning_color : &warning_default, |
4474 | error_color ? error_color : &error_default); |
4475 | } |
4476 | |
4477 | static GdkPixbuf * |
4478 | ctk_icon_info_load_symbolic_svg (CtkIconInfo *icon_info, |
4479 | const CdkRGBA *fg, |
4480 | const CdkRGBA *success_color, |
4481 | const CdkRGBA *warning_color, |
4482 | const CdkRGBA *error_color, |
4483 | GError **error) |
4484 | { |
4485 | GInputStream *stream; |
4486 | GdkPixbuf *pixbuf; |
4487 | gchar *css_fg; |
4488 | gchar *css_success; |
4489 | gchar *css_warning; |
4490 | gchar *css_error; |
4491 | gchar *data; |
4492 | gchar *width; |
4493 | gchar *height; |
4494 | gchar *file_data, *escaped_file_data; |
4495 | gsize file_len; |
4496 | gint symbolic_size; |
4497 | double alpha; |
4498 | gchar alphastr[G_ASCII_DTOSTR_BUF_SIZE(29 + 10)]; |
4499 | |
4500 | alpha = fg->alpha; |
4501 | |
4502 | css_fg = rgba_to_string_noalpha (fg); |
4503 | |
4504 | css_success = css_warning = css_error = NULL((void*)0); |
4505 | |
4506 | if (warning_color) |
4507 | css_warning = rgba_to_string_noalpha (warning_color); |
4508 | else |
4509 | css_warning = g_strdup ("rgb(245,121,62)")g_strdup_inline ("rgb(245,121,62)"); |
4510 | |
4511 | if (error_color) |
4512 | css_error = rgba_to_string_noalpha (error_color); |
4513 | else |
4514 | css_error = g_strdup ("rgb(204,0,0)")g_strdup_inline ("rgb(204,0,0)"); |
4515 | |
4516 | if (success_color) |
4517 | css_success = rgba_to_string_noalpha (success_color); |
4518 | else |
4519 | css_success = g_strdup ("rgb(78,154,6)")g_strdup_inline ("rgb(78,154,6)"); |
4520 | |
4521 | if (!g_file_load_contents (icon_info->icon_file, NULL((void*)0), &file_data, &file_len, NULL((void*)0), error)) |
4522 | return NULL((void*)0); |
4523 | |
4524 | if (!icon_info_ensure_scale_and_pixbuf (icon_info)) |
4525 | { |
4526 | g_propagate_error (error, icon_info->load_error); |
4527 | icon_info->load_error = NULL((void*)0); |
4528 | g_free (css_fg); |
4529 | g_free (css_warning); |
4530 | g_free (css_error); |
4531 | g_free (css_success); |
4532 | g_free (file_data); |
4533 | return NULL((void*)0); |
4534 | } |
4535 | |
4536 | if (icon_info->symbolic_width == 0 || |
4537 | icon_info->symbolic_height == 0) |
4538 | { |
4539 | /* Fetch size from the original icon */ |
4540 | stream = g_memory_input_stream_new_from_data (file_data, file_len, NULL((void*)0)); |
4541 | pixbuf = gdk_pixbuf_new_from_stream (stream, NULL((void*)0), error); |
4542 | g_object_unref (stream); |
4543 | |
4544 | if (!pixbuf) |
4545 | { |
4546 | g_free (css_fg); |
4547 | g_free (css_warning); |
4548 | g_free (css_error); |
4549 | g_free (css_success); |
4550 | g_free (file_data); |
4551 | return NULL((void*)0); |
4552 | } |
4553 | |
4554 | icon_info->symbolic_width = gdk_pixbuf_get_width (pixbuf); |
4555 | icon_info->symbolic_height = gdk_pixbuf_get_height (pixbuf); |
4556 | g_object_unref (pixbuf); |
4557 | } |
4558 | |
4559 | symbolic_size = MAX (icon_info->symbolic_width, icon_info->symbolic_height)(((icon_info->symbolic_width) > (icon_info->symbolic_height )) ? (icon_info->symbolic_width) : (icon_info->symbolic_height )); |
4560 | |
4561 | CTK_NOTE (ICONTHEME,do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) g_message ("Symbolic icon %s is not in an icon theme directory", icon_info ->key.icon_names ? icon_info->key.icon_names[0] : icon_info ->filename); else if (icon_info->dir_size * icon_info-> dir_scale != symbolic_size) g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d" , icon_info->key.icon_names ? icon_info->key.icon_names [0] : icon_info->filename, symbolic_size, icon_info->dir_size * icon_info->dir_scale); }; } while (0) |
4562 | if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED)do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) g_message ("Symbolic icon %s is not in an icon theme directory", icon_info ->key.icon_names ? icon_info->key.icon_names[0] : icon_info ->filename); else if (icon_info->dir_size * icon_info-> dir_scale != symbolic_size) g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d" , icon_info->key.icon_names ? icon_info->key.icon_names [0] : icon_info->filename, symbolic_size, icon_info->dir_size * icon_info->dir_scale); }; } while (0) |
4563 | g_message ("Symbolic icon %s is not in an icon theme directory",do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) g_message ("Symbolic icon %s is not in an icon theme directory", icon_info ->key.icon_names ? icon_info->key.icon_names[0] : icon_info ->filename); else if (icon_info->dir_size * icon_info-> dir_scale != symbolic_size) g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d" , icon_info->key.icon_names ? icon_info->key.icon_names [0] : icon_info->filename, symbolic_size, icon_info->dir_size * icon_info->dir_scale); }; } while (0) |
4564 | icon_info->key.icon_names ? icon_info->key.icon_names[0] : icon_info->filename);do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) g_message ("Symbolic icon %s is not in an icon theme directory", icon_info ->key.icon_names ? icon_info->key.icon_names[0] : icon_info ->filename); else if (icon_info->dir_size * icon_info-> dir_scale != symbolic_size) g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d" , icon_info->key.icon_names ? icon_info->key.icon_names [0] : icon_info->filename, symbolic_size, icon_info->dir_size * icon_info->dir_scale); }; } while (0) |
4565 | else if (icon_info->dir_size * icon_info->dir_scale != symbolic_size)do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) g_message ("Symbolic icon %s is not in an icon theme directory", icon_info ->key.icon_names ? icon_info->key.icon_names[0] : icon_info ->filename); else if (icon_info->dir_size * icon_info-> dir_scale != symbolic_size) g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d" , icon_info->key.icon_names ? icon_info->key.icon_names [0] : icon_info->filename, symbolic_size, icon_info->dir_size * icon_info->dir_scale); }; } while (0) |
4566 | g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d",do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) g_message ("Symbolic icon %s is not in an icon theme directory", icon_info ->key.icon_names ? icon_info->key.icon_names[0] : icon_info ->filename); else if (icon_info->dir_size * icon_info-> dir_scale != symbolic_size) g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d" , icon_info->key.icon_names ? icon_info->key.icon_names [0] : icon_info->filename, symbolic_size, icon_info->dir_size * icon_info->dir_scale); }; } while (0) |
4567 | icon_info->key.icon_names ? icon_info->key.icon_names[0] : icon_info->filename,do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) g_message ("Symbolic icon %s is not in an icon theme directory", icon_info ->key.icon_names ? icon_info->key.icon_names[0] : icon_info ->filename); else if (icon_info->dir_size * icon_info-> dir_scale != symbolic_size) g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d" , icon_info->key.icon_names ? icon_info->key.icon_names [0] : icon_info->filename, symbolic_size, icon_info->dir_size * icon_info->dir_scale); }; } while (0) |
4568 | symbolic_size,do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) g_message ("Symbolic icon %s is not in an icon theme directory", icon_info ->key.icon_names ? icon_info->key.icon_names[0] : icon_info ->filename); else if (icon_info->dir_size * icon_info-> dir_scale != symbolic_size) g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d" , icon_info->key.icon_names ? icon_info->key.icon_names [0] : icon_info->filename, symbolic_size, icon_info->dir_size * icon_info->dir_scale); }; } while (0) |
4569 | icon_info->dir_size * icon_info->dir_scale)do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) g_message ("Symbolic icon %s is not in an icon theme directory", icon_info ->key.icon_names ? icon_info->key.icon_names[0] : icon_info ->filename); else if (icon_info->dir_size * icon_info-> dir_scale != symbolic_size) g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d" , icon_info->key.icon_names ? icon_info->key.icon_names [0] : icon_info->filename, symbolic_size, icon_info->dir_size * icon_info->dir_scale); }; } while (0) |
4570 | )do { if ((ctk_get_debug_flags () & CTK_DEBUG_ICONTHEME)) { if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED) g_message ("Symbolic icon %s is not in an icon theme directory", icon_info ->key.icon_names ? icon_info->key.icon_names[0] : icon_info ->filename); else if (icon_info->dir_size * icon_info-> dir_scale != symbolic_size) g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d" , icon_info->key.icon_names ? icon_info->key.icon_names [0] : icon_info->filename, symbolic_size, icon_info->dir_size * icon_info->dir_scale); }; } while (0); |
4571 | |
4572 | width = g_strdup_printf ("%d", icon_info->symbolic_width); |
4573 | height = g_strdup_printf ("%d", icon_info->symbolic_height); |
4574 | |
4575 | escaped_file_data = g_base64_encode ((guchar *) file_data, file_len); |
4576 | g_free (file_data); |
4577 | |
4578 | g_ascii_dtostr (alphastr, G_ASCII_DTOSTR_BUF_SIZE(29 + 10), CLAMP (alpha, 0, 1)(((alpha) > (1)) ? (1) : (((alpha) < (0)) ? (0) : (alpha )))); |
4579 | |
4580 | data = g_strconcat ("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" |
4581 | "<svg version=\"1.1\"\n" |
4582 | " xmlns=\"http://www.w3.org/2000/svg\"\n" |
4583 | " xmlns:xi=\"http://www.w3.org/2001/XInclude\"\n" |
4584 | " width=\"", width, "\"\n" |
4585 | " height=\"", height, "\">\n" |
4586 | " <style type=\"text/css\">\n" |
4587 | " rect,path,ellipse,circle,polygon {\n" |
4588 | " fill: ", css_fg," !important;\n" |
4589 | " }\n" |
4590 | " .warning {\n" |
4591 | " fill: ", css_warning, " !important;\n" |
4592 | " }\n" |
4593 | " .error {\n" |
4594 | " fill: ", css_error ," !important;\n" |
4595 | " }\n" |
4596 | " .success {\n" |
4597 | " fill: ", css_success, " !important;\n" |
4598 | " }\n" |
4599 | " </style>\n" |
4600 | " <g opacity=\"", alphastr, "\" ><xi:include href=\"data:text/xml;base64,", escaped_file_data, "\"/></g>\n" |
4601 | "</svg>", |
4602 | NULL((void*)0)); |
4603 | g_free (escaped_file_data); |
4604 | g_free (css_fg); |
4605 | g_free (css_warning); |
4606 | g_free (css_error); |
4607 | g_free (css_success); |
4608 | g_free (width); |
4609 | g_free (height); |
4610 | |
4611 | stream = g_memory_input_stream_new_from_data (data, -1, g_free); |
4612 | pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream, |
4613 | gdk_pixbuf_get_width (icon_info->pixbuf), |
4614 | gdk_pixbuf_get_height (icon_info->pixbuf), |
4615 | TRUE(!(0)), |
4616 | NULL((void*)0), |
4617 | error); |
4618 | g_object_unref (stream); |
4619 | |
4620 | return pixbuf; |
4621 | } |
4622 | |
4623 | |
4624 | static GdkPixbuf * |
4625 | ctk_icon_info_load_symbolic_internal (CtkIconInfo *icon_info, |
4626 | const CdkRGBA *fg, |
4627 | const CdkRGBA *success_color, |
4628 | const CdkRGBA *warning_color, |
4629 | const CdkRGBA *error_color, |
4630 | gboolean use_cache, |
4631 | GError **error) |
4632 | { |
4633 | GdkPixbuf *pixbuf; |
4634 | SymbolicPixbufCache *symbolic_cache; |
4635 | char *icon_uri; |
4636 | |
4637 | if (use_cache) |
4638 | { |
4639 | symbolic_cache = symbolic_pixbuf_cache_matches (icon_info->symbolic_pixbuf_cache, |
4640 | fg, success_color, warning_color, error_color); |
4641 | if (symbolic_cache) |
4642 | return symbolic_cache_get_proxy (symbolic_cache, icon_info); |
4643 | } |
4644 | |
4645 | /* css_fg can't possibly have failed, otherwise |
4646 | * that would mean we have a broken style |
4647 | */ |
4648 | g_return_val_if_fail (fg != NULL, NULL)do { if ((fg != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "fg != NULL"); return (( (void*)0)); } } while (0); |
4649 | |
4650 | icon_uri = g_file_get_uri (icon_info->icon_file); |
4651 | if (g_str_has_suffix (icon_uri, ".symbolic.png")(__builtin_constant_p (".symbolic.png")? __extension__ ({ const char * const __str = (icon_uri); const char * const __suffix = (".symbolic.png"); gboolean __result = (0); if (__str == ( (void*)0) || __suffix == ((void*)0)) __result = (g_str_has_suffix ) (__str, __suffix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __suffix_len = strlen ((( __suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix) + !( __suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix ) (icon_uri, ".symbolic.png") )) |
4652 | pixbuf = ctk_icon_info_load_symbolic_png (icon_info, fg, success_color, warning_color, error_color, error); |
4653 | else |
4654 | pixbuf = ctk_icon_info_load_symbolic_svg (icon_info, fg, success_color, warning_color, error_color, error); |
4655 | |
4656 | g_free (icon_uri); |
4657 | |
4658 | if (pixbuf != NULL((void*)0)) |
4659 | { |
4660 | GdkPixbuf *icon; |
4661 | |
4662 | icon = apply_emblems_to_pixbuf (pixbuf, icon_info); |
4663 | if (icon != NULL((void*)0)) |
4664 | { |
4665 | g_object_unref (pixbuf); |
4666 | pixbuf = icon; |
4667 | } |
4668 | |
4669 | if (use_cache) |
4670 | { |
4671 | icon_info->symbolic_pixbuf_cache = |
4672 | symbolic_pixbuf_cache_new (pixbuf, fg, success_color, warning_color, error_color, |
4673 | icon_info->symbolic_pixbuf_cache); |
4674 | g_object_unref (pixbuf); |
4675 | return symbolic_cache_get_proxy (icon_info->symbolic_pixbuf_cache, icon_info); |
4676 | } |
4677 | else |
4678 | return pixbuf; |
4679 | } |
4680 | |
4681 | return NULL((void*)0); |
4682 | } |
4683 | |
4684 | /** |
4685 | * ctk_icon_info_load_symbolic: |
4686 | * @icon_info: a #CtkIconInfo |
4687 | * @fg: a #CdkRGBA representing the foreground color of the icon |
4688 | * @success_color: (allow-none): a #CdkRGBA representing the warning color |
4689 | * of the icon or %NULL to use the default color |
4690 | * @warning_color: (allow-none): a #CdkRGBA representing the warning color |
4691 | * of the icon or %NULL to use the default color |
4692 | * @error_color: (allow-none): a #CdkRGBA representing the error color |
4693 | * of the icon or %NULL to use the default color (allow-none) |
4694 | * @was_symbolic: (out) (allow-none): a #gboolean, returns whether the |
4695 | * loaded icon was a symbolic one and whether the @fg color was |
4696 | * applied to it. |
4697 | * @error: (allow-none): location to store error information on failure, |
4698 | * or %NULL. |
4699 | * |
4700 | * Loads an icon, modifying it to match the system colours for the foreground, |
4701 | * success, warning and error colors provided. If the icon is not a symbolic |
4702 | * one, the function will return the result from ctk_icon_info_load_icon(). |
4703 | * |
4704 | * This allows loading symbolic icons that will match the system theme. |
4705 | * |
4706 | * Unless you are implementing a widget, you will want to use |
4707 | * g_themed_icon_new_with_default_fallbacks() to load the icon. |
4708 | * |
4709 | * As implementation details, the icon loaded needs to be of SVG type, |
4710 | * contain the “symbolic” term as the last component of the icon name, |
4711 | * and use the “fg”, “success”, “warning” and “error” CSS styles in the |
4712 | * SVG file itself. |
4713 | * |
4714 | * See the [Symbolic Icons Specification](http://www.freedesktop.org/wiki/SymbolicIcons) |
4715 | * for more information about symbolic icons. |
4716 | * |
4717 | * Returns: (transfer full): a #GdkPixbuf representing the loaded icon |
4718 | * |
4719 | * Since: 3.0 |
4720 | */ |
4721 | GdkPixbuf * |
4722 | ctk_icon_info_load_symbolic (CtkIconInfo *icon_info, |
4723 | const CdkRGBA *fg, |
4724 | const CdkRGBA *success_color, |
4725 | const CdkRGBA *warning_color, |
4726 | const CdkRGBA *error_color, |
4727 | gboolean *was_symbolic, |
4728 | GError **error) |
4729 | { |
4730 | gboolean is_symbolic; |
4731 | |
4732 | g_return_val_if_fail (icon_info != NULL, NULL)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return (((void*)0)); } } while (0); |
4733 | g_return_val_if_fail (fg != NULL, NULL)do { if ((fg != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "fg != NULL"); return (( (void*)0)); } } while (0); |
4734 | |
4735 | is_symbolic = ctk_icon_info_is_symbolic (icon_info); |
4736 | |
4737 | if (was_symbolic) |
4738 | *was_symbolic = is_symbolic; |
4739 | |
4740 | if (!is_symbolic) |
4741 | return ctk_icon_info_load_icon (icon_info, error); |
4742 | |
4743 | return ctk_icon_info_load_symbolic_internal (icon_info, |
4744 | fg, success_color, |
4745 | warning_color, error_color, |
4746 | TRUE(!(0)), |
4747 | error); |
4748 | } |
4749 | |
4750 | void |
4751 | ctk_icon_theme_lookup_symbolic_colors (CtkCssStyle *style, |
4752 | CdkRGBA *color_out, |
4753 | CdkRGBA *success_out, |
4754 | CdkRGBA *warning_out, |
4755 | CdkRGBA *error_out) |
4756 | { |
4757 | CtkCssValue *palette, *color; |
4758 | const CdkRGBA *lookup; |
4759 | |
4760 | color = ctk_css_style_get_value (style, CTK_CSS_PROPERTY_COLOR); |
4761 | palette = ctk_css_style_get_value (style, CTK_CSS_PROPERTY_ICON_PALETTE); |
4762 | *color_out = *_ctk_css_rgba_value_get_rgba (color); |
4763 | |
4764 | lookup = ctk_css_palette_value_get_color (palette, "success"); |
4765 | if (lookup) |
4766 | *success_out = *lookup; |
4767 | else |
4768 | *success_out = *color_out; |
4769 | |
4770 | lookup = ctk_css_palette_value_get_color (palette, "warning"); |
4771 | if (lookup) |
4772 | *warning_out = *lookup; |
4773 | else |
4774 | *warning_out = *color_out; |
4775 | |
4776 | lookup = ctk_css_palette_value_get_color (palette, "error"); |
4777 | if (lookup) |
4778 | *error_out = *lookup; |
4779 | else |
4780 | *error_out = *color_out; |
4781 | } |
4782 | |
4783 | /** |
4784 | * ctk_icon_info_load_symbolic_for_context: |
4785 | * @icon_info: a #CtkIconInfo |
4786 | * @context: a #CtkStyleContext |
4787 | * @was_symbolic: (out) (allow-none): a #gboolean, returns whether the |
4788 | * loaded icon was a symbolic one and whether the @fg color was |
4789 | * applied to it. |
4790 | * @error: (allow-none): location to store error information on failure, |
4791 | * or %NULL. |
4792 | * |
4793 | * Loads an icon, modifying it to match the system colors for the foreground, |
4794 | * success, warning and error colors provided. If the icon is not a symbolic |
4795 | * one, the function will return the result from ctk_icon_info_load_icon(). |
4796 | * This function uses the regular foreground color and the symbolic colors |
4797 | * with the names “success_color”, “warning_color” and “error_color” from |
4798 | * the context. |
4799 | * |
4800 | * This allows loading symbolic icons that will match the system theme. |
4801 | * |
4802 | * See ctk_icon_info_load_symbolic() for more details. |
4803 | * |
4804 | * Returns: (transfer full): a #GdkPixbuf representing the loaded icon |
4805 | * |
4806 | * Since: 3.0 |
4807 | */ |
4808 | GdkPixbuf * |
4809 | ctk_icon_info_load_symbolic_for_context (CtkIconInfo *icon_info, |
4810 | CtkStyleContext *context, |
4811 | gboolean *was_symbolic, |
4812 | GError **error) |
4813 | { |
4814 | CdkRGBA fg; |
4815 | CdkRGBA success_color; |
4816 | CdkRGBA warning_color; |
4817 | CdkRGBA error_color; |
4818 | gboolean is_symbolic; |
4819 | |
4820 | g_return_val_if_fail (icon_info != NULL, NULL)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return (((void*)0)); } } while (0); |
4821 | g_return_val_if_fail (context != NULL, NULL)do { if ((context != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "context != NULL"); return (((void*)0)); } } while (0); |
4822 | |
4823 | is_symbolic = ctk_icon_info_is_symbolic (icon_info); |
4824 | |
4825 | if (was_symbolic) |
4826 | *was_symbolic = is_symbolic; |
4827 | |
4828 | if (!is_symbolic) |
4829 | return ctk_icon_info_load_icon (icon_info, error); |
4830 | |
4831 | ctk_icon_theme_lookup_symbolic_colors (ctk_style_context_lookup_style (context), |
4832 | &fg, &success_color, |
4833 | &warning_color, &error_color); |
4834 | |
4835 | return ctk_icon_info_load_symbolic_internal (icon_info, |
4836 | &fg, &success_color, |
4837 | &warning_color, &error_color, |
4838 | TRUE(!(0)), |
4839 | error); |
4840 | } |
4841 | |
4842 | typedef struct { |
4843 | gboolean is_symbolic; |
4844 | CtkIconInfo *dup; |
4845 | CdkRGBA fg; |
4846 | gboolean fg_set; |
4847 | CdkRGBA success_color; |
4848 | gboolean success_color_set; |
4849 | CdkRGBA warning_color; |
4850 | gboolean warning_color_set; |
4851 | CdkRGBA error_color; |
4852 | gboolean error_color_set; |
4853 | } AsyncSymbolicData; |
4854 | |
4855 | static void |
4856 | async_symbolic_data_free (AsyncSymbolicData *data) |
4857 | { |
4858 | if (data->dup) |
4859 | g_object_unref (data->dup); |
4860 | g_slice_free (AsyncSymbolicData, data)do { if (1) g_slice_free1 (sizeof (AsyncSymbolicData), (data) ); else (void) ((AsyncSymbolicData*) 0 == (data)); } while (0 ); |
4861 | } |
4862 | |
4863 | static void |
4864 | async_load_no_symbolic_cb (GObject *source_object, |
4865 | GAsyncResult *res, |
4866 | gpointer user_data) |
4867 | { |
4868 | CtkIconInfo *icon_info = CTK_ICON_INFO (source_object)((((CtkIconInfo*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((source_object)), ((ctk_icon_info_get_type ())))))); |
4869 | GTask *task = user_data; |
4870 | GError *error = NULL((void*)0); |
4871 | GdkPixbuf *pixbuf; |
4872 | |
4873 | pixbuf = ctk_icon_info_load_icon_finish (icon_info, res, &error); |
4874 | if (pixbuf == NULL((void*)0)) |
4875 | g_task_return_error (task, error); |
4876 | else |
4877 | g_task_return_pointer (task, pixbuf, g_object_unref); |
4878 | g_object_unref (task); |
4879 | } |
4880 | |
4881 | static void |
4882 | load_symbolic_icon_thread (GTask *task, |
4883 | gpointer source_object G_GNUC_UNUSED__attribute__ ((__unused__)), |
4884 | gpointer task_data, |
4885 | GCancellable *cancellable G_GNUC_UNUSED__attribute__ ((__unused__))) |
4886 | { |
4887 | AsyncSymbolicData *data = task_data; |
4888 | GError *error; |
4889 | GdkPixbuf *pixbuf; |
4890 | |
4891 | error = NULL((void*)0); |
4892 | pixbuf = ctk_icon_info_load_symbolic_internal (data->dup, |
4893 | data->fg_set ? &data->fg : NULL((void*)0), |
4894 | data->success_color_set ? &data->success_color : NULL((void*)0), |
4895 | data->warning_color_set ? &data->warning_color : NULL((void*)0), |
4896 | data->error_color_set ? &data->error_color : NULL((void*)0), |
4897 | FALSE(0), |
4898 | &error); |
4899 | if (pixbuf == NULL((void*)0)) |
4900 | g_task_return_error (task, error); |
4901 | else |
4902 | g_task_return_pointer (task, pixbuf, g_object_unref); |
4903 | } |
4904 | |
4905 | /** |
4906 | * ctk_icon_info_load_symbolic_async: |
4907 | * @icon_info: a #CtkIconInfo from ctk_icon_theme_lookup_icon() |
4908 | * @fg: a #CdkRGBA representing the foreground color of the icon |
4909 | * @success_color: (allow-none): a #CdkRGBA representing the warning color |
4910 | * of the icon or %NULL to use the default color |
4911 | * @warning_color: (allow-none): a #CdkRGBA representing the warning color |
4912 | * of the icon or %NULL to use the default color |
4913 | * @error_color: (allow-none): a #CdkRGBA representing the error color |
4914 | * of the icon or %NULL to use the default color (allow-none) |
4915 | * @cancellable: (allow-none): optional #GCancellable object, |
4916 | * %NULL to ignore |
4917 | * @callback: (scope async): a #GAsyncReadyCallback to call when the |
4918 | * request is satisfied |
4919 | * @user_data: (closure): the data to pass to callback function |
4920 | * |
4921 | * Asynchronously load, render and scale a symbolic icon previously looked up |
4922 | * from the icon theme using ctk_icon_theme_lookup_icon(). |
4923 | * |
4924 | * For more details, see ctk_icon_info_load_symbolic() which is the synchronous |
4925 | * version of this call. |
4926 | * |
4927 | * Since: 3.8 |
4928 | */ |
4929 | void |
4930 | ctk_icon_info_load_symbolic_async (CtkIconInfo *icon_info, |
4931 | const CdkRGBA *fg, |
4932 | const CdkRGBA *success_color, |
4933 | const CdkRGBA *warning_color, |
4934 | const CdkRGBA *error_color, |
4935 | GCancellable *cancellable, |
4936 | GAsyncReadyCallback callback, |
4937 | gpointer user_data) |
4938 | { |
4939 | GTask *task; |
4940 | AsyncSymbolicData *data; |
4941 | SymbolicPixbufCache *symbolic_cache; |
4942 | GdkPixbuf *pixbuf; |
4943 | |
4944 | g_return_if_fail (icon_info != NULL)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return ; } } while (0); |
4945 | g_return_if_fail (fg != NULL)do { if ((fg != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "fg != NULL"); return; } } while (0); |
4946 | |
4947 | task = g_task_new (icon_info, cancellable, callback, user_data); |
4948 | |
4949 | data = g_slice_new0 (AsyncSymbolicData)((AsyncSymbolicData*) g_slice_alloc0 (sizeof (AsyncSymbolicData ))); |
4950 | g_task_set_task_data (task, data, (GDestroyNotify) async_symbolic_data_free); |
4951 | |
4952 | data->is_symbolic = ctk_icon_info_is_symbolic (icon_info); |
4953 | |
4954 | if (!data->is_symbolic) |
4955 | { |
4956 | ctk_icon_info_load_icon_async (icon_info, cancellable, async_load_no_symbolic_cb, g_object_ref (task)((__typeof__ (task)) (g_object_ref) (task))); |
4957 | } |
4958 | else |
4959 | { |
4960 | symbolic_cache = symbolic_pixbuf_cache_matches (icon_info->symbolic_pixbuf_cache, |
4961 | fg, success_color, warning_color, error_color); |
4962 | if (symbolic_cache) |
4963 | { |
4964 | pixbuf = symbolic_cache_get_proxy (symbolic_cache, icon_info); |
4965 | g_task_return_pointer (task, pixbuf, g_object_unref); |
4966 | } |
4967 | else |
4968 | { |
4969 | if (fg) |
4970 | { |
4971 | data->fg = *fg; |
4972 | data->fg_set = TRUE(!(0)); |
4973 | } |
4974 | |
4975 | if (success_color) |
4976 | { |
4977 | data->success_color = *success_color; |
4978 | data->success_color_set = TRUE(!(0)); |
4979 | } |
4980 | |
4981 | if (warning_color) |
4982 | { |
4983 | data->warning_color = *warning_color; |
4984 | data->warning_color_set = TRUE(!(0)); |
4985 | } |
4986 | |
4987 | if (error_color) |
4988 | { |
4989 | data->error_color = *error_color; |
4990 | data->error_color_set = TRUE(!(0)); |
4991 | } |
4992 | |
4993 | data->dup = icon_info_dup (icon_info); |
4994 | g_task_run_in_thread (task, load_symbolic_icon_thread); |
4995 | } |
4996 | } |
4997 | g_object_unref (task); |
4998 | } |
4999 | |
5000 | /** |
5001 | * ctk_icon_info_load_symbolic_finish: |
5002 | * @icon_info: a #CtkIconInfo from ctk_icon_theme_lookup_icon() |
5003 | * @res: a #GAsyncResult |
5004 | * @was_symbolic: (out) (allow-none): a #gboolean, returns whether the |
5005 | * loaded icon was a symbolic one and whether the @fg color was |
5006 | * applied to it. |
5007 | * @error: (allow-none): location to store error information on failure, |
5008 | * or %NULL. |
5009 | * |
5010 | * Finishes an async icon load, see ctk_icon_info_load_symbolic_async(). |
5011 | * |
5012 | * Returns: (transfer full): the rendered icon; this may be a newly |
5013 | * created icon or a new reference to an internal icon, so you must |
5014 | * not modify the icon. Use g_object_unref() to release your reference |
5015 | * to the icon. |
5016 | * |
5017 | * Since: 3.8 |
5018 | */ |
5019 | GdkPixbuf * |
5020 | ctk_icon_info_load_symbolic_finish (CtkIconInfo *icon_info, |
5021 | GAsyncResult *result, |
5022 | gboolean *was_symbolic, |
5023 | GError **error) |
5024 | { |
5025 | GTask *task = G_TASK (result)((((GTask*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((result)), ((g_task_get_type ())))))); |
5026 | AsyncSymbolicData *data = g_task_get_task_data (task); |
5027 | SymbolicPixbufCache *symbolic_cache; |
5028 | GdkPixbuf *pixbuf; |
5029 | |
5030 | if (was_symbolic) |
5031 | *was_symbolic = data->is_symbolic; |
5032 | |
5033 | if (data->dup && !g_task_had_error (task)) |
5034 | { |
5035 | pixbuf = g_task_propagate_pointer (task, NULL((void*)0)); |
5036 | |
5037 | g_assert (pixbuf != NULL)do { if (pixbuf != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkicontheme.c", 5037, ((const char*) (__func__)), "pixbuf != NULL" ); } while (0); /* we checked for !had_error above */ |
5038 | |
5039 | symbolic_cache = symbolic_pixbuf_cache_matches (icon_info->symbolic_pixbuf_cache, |
5040 | data->fg_set ? &data->fg : NULL((void*)0), |
5041 | data->success_color_set ? &data->success_color : NULL((void*)0), |
5042 | data->warning_color_set ? &data->warning_color : NULL((void*)0), |
5043 | data->error_color_set ? &data->error_color : NULL((void*)0)); |
5044 | |
5045 | if (symbolic_cache == NULL((void*)0)) |
5046 | { |
5047 | symbolic_cache = icon_info->symbolic_pixbuf_cache = |
5048 | symbolic_pixbuf_cache_new (pixbuf, |
5049 | data->fg_set ? &data->fg : NULL((void*)0), |
5050 | data->success_color_set ? &data->success_color : NULL((void*)0), |
5051 | data->warning_color_set ? &data->warning_color : NULL((void*)0), |
5052 | data->error_color_set ? &data->error_color : NULL((void*)0), |
5053 | icon_info->symbolic_pixbuf_cache); |
5054 | } |
5055 | |
5056 | g_object_unref (pixbuf); |
5057 | |
5058 | return symbolic_cache_get_proxy (symbolic_cache, icon_info); |
5059 | } |
5060 | |
5061 | return g_task_propagate_pointer (task, error); |
5062 | } |
5063 | |
5064 | /** |
5065 | * ctk_icon_info_load_symbolic_for_context_async: |
5066 | * @icon_info: a #CtkIconInfo from ctk_icon_theme_lookup_icon() |
5067 | * @context: a #CtkStyleContext |
5068 | * @cancellable: (allow-none): optional #GCancellable object, |
5069 | * %NULL to ignore |
5070 | * @callback: (scope async): a #GAsyncReadyCallback to call when the |
5071 | * request is satisfied |
5072 | * @user_data: (closure): the data to pass to callback function |
5073 | * |
5074 | * Asynchronously load, render and scale a symbolic icon previously |
5075 | * looked up from the icon theme using ctk_icon_theme_lookup_icon(). |
5076 | * |
5077 | * For more details, see ctk_icon_info_load_symbolic_for_context() |
5078 | * which is the synchronous version of this call. |
5079 | * |
5080 | * Since: 3.8 |
5081 | */ |
5082 | void |
5083 | ctk_icon_info_load_symbolic_for_context_async (CtkIconInfo *icon_info, |
5084 | CtkStyleContext *context, |
5085 | GCancellable *cancellable, |
5086 | GAsyncReadyCallback callback, |
5087 | gpointer user_data) |
5088 | { |
5089 | CdkRGBA fg; |
5090 | CdkRGBA success_color; |
5091 | CdkRGBA warning_color; |
5092 | CdkRGBA error_color; |
5093 | |
5094 | g_return_if_fail (icon_info != NULL)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return ; } } while (0); |
5095 | g_return_if_fail (context != NULL)do { if ((context != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "context != NULL"); return ; } } while (0); |
5096 | |
5097 | ctk_icon_theme_lookup_symbolic_colors (ctk_style_context_lookup_style (context), |
5098 | &fg, &success_color, |
5099 | &warning_color, &error_color); |
5100 | |
5101 | ctk_icon_info_load_symbolic_async (icon_info, |
5102 | &fg, &success_color, |
5103 | &warning_color, &error_color, |
5104 | cancellable, callback, user_data); |
5105 | } |
5106 | |
5107 | /** |
5108 | * ctk_icon_info_load_symbolic_for_context_finish: |
5109 | * @icon_info: a #CtkIconInfo from ctk_icon_theme_lookup_icon() |
5110 | * @res: a #GAsyncResult |
5111 | * @was_symbolic: (out) (allow-none): a #gboolean, returns whether the |
5112 | * loaded icon was a symbolic one and whether the @fg color was |
5113 | * applied to it. |
5114 | * @error: (allow-none): location to store error information on failure, |
5115 | * or %NULL. |
5116 | * |
5117 | * Finishes an async icon load, see ctk_icon_info_load_symbolic_for_context_async(). |
5118 | * |
5119 | * Returns: (transfer full): the rendered icon; this may be a newly |
5120 | * created icon or a new reference to an internal icon, so you must |
5121 | * not modify the icon. Use g_object_unref() to release your reference |
5122 | * to the icon. |
5123 | * |
5124 | * Since: 3.8 |
5125 | */ |
5126 | GdkPixbuf * |
5127 | ctk_icon_info_load_symbolic_for_context_finish (CtkIconInfo *icon_info, |
5128 | GAsyncResult *result, |
5129 | gboolean *was_symbolic, |
5130 | GError **error) |
5131 | { |
5132 | return ctk_icon_info_load_symbolic_finish (icon_info, result, was_symbolic, error); |
5133 | } |
5134 | |
5135 | static CdkRGBA * |
5136 | color_to_rgba (CdkColor *color, |
5137 | CdkRGBA *rgba) |
5138 | { |
5139 | rgba->red = color->red / 65535.0; |
5140 | rgba->green = color->green / 65535.0; |
5141 | rgba->blue = color->blue / 65535.0; |
5142 | rgba->alpha = 1.0; |
5143 | return rgba; |
5144 | } |
5145 | |
5146 | /** |
5147 | * ctk_icon_info_load_symbolic_for_style: |
5148 | * @icon_info: a #CtkIconInfo |
5149 | * @style: a #CtkStyle to take the colors from |
5150 | * @state: the widget state to use for colors |
5151 | * @was_symbolic: (out) (allow-none): a #gboolean, returns whether the |
5152 | * loaded icon was a symbolic one and whether the @fg color was |
5153 | * applied to it. |
5154 | * @error: (allow-none): location to store error information on failure, |
5155 | * or %NULL. |
5156 | * |
5157 | * Loads an icon, modifying it to match the system colours for the foreground, |
5158 | * success, warning and error colors provided. If the icon is not a symbolic |
5159 | * one, the function will return the result from ctk_icon_info_load_icon(). |
5160 | * |
5161 | * This allows loading symbolic icons that will match the system theme. |
5162 | * |
5163 | * See ctk_icon_info_load_symbolic() for more details. |
5164 | * |
5165 | * Returns: (transfer full): a #GdkPixbuf representing the loaded icon |
5166 | * |
5167 | * Since: 3.0 |
5168 | * |
5169 | * Deprecated: 3.0: Use ctk_icon_info_load_symbolic_for_context() instead |
5170 | */ |
5171 | GdkPixbuf * |
5172 | ctk_icon_info_load_symbolic_for_style (CtkIconInfo *icon_info, |
5173 | CtkStyle *style, |
5174 | CtkStateType state, |
5175 | gboolean *was_symbolic, |
5176 | GError **error) |
5177 | { |
5178 | CdkColor color; |
5179 | CdkRGBA fg; |
5180 | CdkRGBA success_color; |
5181 | CdkRGBA *success_colorp; |
5182 | CdkRGBA warning_color; |
5183 | CdkRGBA *warning_colorp; |
5184 | CdkRGBA error_color; |
5185 | CdkRGBA *error_colorp; |
5186 | gboolean is_symbolic; |
5187 | |
5188 | g_return_val_if_fail (icon_info != NULL, NULL)do { if ((icon_info != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_info != NULL"); return (((void*)0)); } } while (0); |
5189 | g_return_val_if_fail (style != NULL, NULL)do { if ((style != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "style != NULL"); return (((void*)0)); } } while (0); |
5190 | |
5191 | is_symbolic = ctk_icon_info_is_symbolic (icon_info); |
5192 | |
5193 | if (was_symbolic) |
5194 | *was_symbolic = is_symbolic; |
5195 | |
5196 | if (!is_symbolic) |
5197 | return ctk_icon_info_load_icon (icon_info, error); |
5198 | |
5199 | color_to_rgba (&style->fg[state], &fg); |
5200 | |
5201 | success_colorp = warning_colorp = error_colorp = NULL((void*)0); |
5202 | |
5203 | if (ctk_style_lookup_color (style, "success_color", &color)) |
5204 | success_colorp = color_to_rgba (&color, &success_color); |
5205 | |
5206 | if (ctk_style_lookup_color (style, "warning_color", &color)) |
5207 | warning_colorp = color_to_rgba (&color, &warning_color); |
5208 | |
5209 | if (ctk_style_lookup_color (style, "error_color", &color)) |
5210 | error_colorp = color_to_rgba (&color, &error_color); |
5211 | |
5212 | return ctk_icon_info_load_symbolic_internal (icon_info, |
5213 | &fg, success_colorp, |
5214 | warning_colorp, error_colorp, |
5215 | TRUE(!(0)), |
5216 | error); |
5217 | } |
5218 | |
5219 | /** |
5220 | * ctk_icon_info_set_raw_coordinates: |
5221 | * @icon_info: a #CtkIconInfo |
5222 | * @raw_coordinates: whether the coordinates of embedded rectangles |
5223 | * and attached points should be returned in their original |
5224 | * (unscaled) form. |
5225 | * |
5226 | * Sets whether the coordinates returned by ctk_icon_info_get_embedded_rect() |
5227 | * and ctk_icon_info_get_attach_points() should be returned in their |
5228 | * original form as specified in the icon theme, instead of scaled |
5229 | * appropriately for the pixbuf returned by ctk_icon_info_load_icon(). |
5230 | * |
5231 | * Raw coordinates are somewhat strange; they are specified to be with |
5232 | * respect to the unscaled pixmap for PNG and XPM icons, but for SVG |
5233 | * icons, they are in a 1000x1000 coordinate space that is scaled |
5234 | * to the final size of the icon. You can determine if the icon is an SVG |
5235 | * icon by using ctk_icon_info_get_filename(), and seeing if it is non-%NULL |
5236 | * and ends in “.svg”. |
5237 | * |
5238 | * This function is provided primarily to allow compatibility wrappers |
5239 | * for older API's, and is not expected to be useful for applications. |
5240 | * |
5241 | * Since: 2.4 |
5242 | * |
5243 | * Deprecated: 3.14: Embedded rectangles and attachment points are deprecated |
5244 | */ |
5245 | void |
5246 | ctk_icon_info_set_raw_coordinates (CtkIconInfo *icon_info G_GNUC_UNUSED__attribute__ ((__unused__)), |
5247 | gboolean raw_coordinates G_GNUC_UNUSED__attribute__ ((__unused__))) |
5248 | { |
5249 | } |
5250 | |
5251 | /** |
5252 | * ctk_icon_info_get_embedded_rect: |
5253 | * @icon_info: a #CtkIconInfo |
5254 | * @rectangle: (out): #CdkRectangle in which to store embedded |
5255 | * rectangle coordinates; coordinates are only stored |
5256 | * when this function returns %TRUE. |
5257 | * |
5258 | * This function is deprecated and always returns %FALSE. |
5259 | * |
5260 | * Returns: %FALSE |
5261 | * |
5262 | * Since: 2.4 |
5263 | * |
5264 | * Deprecated: 3.14: Embedded rectangles are deprecated |
5265 | */ |
5266 | gboolean |
5267 | ctk_icon_info_get_embedded_rect (CtkIconInfo *icon_info G_GNUC_UNUSED__attribute__ ((__unused__)), |
5268 | CdkRectangle *rectangle G_GNUC_UNUSED__attribute__ ((__unused__))) |
5269 | { |
5270 | return FALSE(0); |
5271 | } |
5272 | |
5273 | /** |
5274 | * ctk_icon_info_get_attach_points: |
5275 | * @icon_info: a #CtkIconInfo |
5276 | * @points: (allow-none) (array length=n_points) (out): location to store pointer |
5277 | * to an array of points, or %NULL free the array of points with g_free(). |
5278 | * @n_points: (allow-none): location to store the number of points in @points, |
5279 | * or %NULL |
5280 | * |
5281 | * This function is deprecated and always returns %FALSE. |
5282 | * |
5283 | * Returns: %FALSE |
5284 | * |
5285 | * Since: 2.4 |
5286 | * |
5287 | * Deprecated: 3.14: Attachment points are deprecated |
5288 | */ |
5289 | gboolean |
5290 | ctk_icon_info_get_attach_points (CtkIconInfo *icon_info G_GNUC_UNUSED__attribute__ ((__unused__)), |
5291 | CdkPoint **points G_GNUC_UNUSED__attribute__ ((__unused__)), |
5292 | gint *n_points G_GNUC_UNUSED__attribute__ ((__unused__))) |
5293 | { |
5294 | return FALSE(0); |
5295 | } |
5296 | |
5297 | /** |
5298 | * ctk_icon_info_get_display_name: |
5299 | * @icon_info: a #CtkIconInfo |
5300 | * |
5301 | * This function is deprecated and always returns %NULL. |
5302 | * |
5303 | * Returns: %NULL |
5304 | * |
5305 | * Since: 2.4 |
5306 | * |
5307 | * Deprecated: 3.14: Display names are deprecated |
5308 | */ |
5309 | const gchar * |
5310 | ctk_icon_info_get_display_name (CtkIconInfo *icon_info G_GNUC_UNUSED__attribute__ ((__unused__))) |
5311 | { |
5312 | return NULL((void*)0); |
5313 | } |
5314 | |
5315 | /* |
5316 | * Builtin icons |
5317 | */ |
5318 | |
5319 | |
5320 | /** |
5321 | * ctk_icon_theme_add_builtin_icon: |
5322 | * @icon_name: the name of the icon to register |
5323 | * @size: the size in pixels at which to register the icon (different |
5324 | * images can be registered for the same icon name at different sizes.) |
5325 | * @pixbuf: #GdkPixbuf that contains the image to use for @icon_name |
5326 | * |
5327 | * Registers a built-in icon for icon theme lookups. The idea |
5328 | * of built-in icons is to allow an application or library |
5329 | * that uses themed icons to function requiring files to |
5330 | * be present in the file system. For instance, the default |
5331 | * images for all of CTK+’s stock icons are registered |
5332 | * as built-icons. |
5333 | * |
5334 | * In general, if you use ctk_icon_theme_add_builtin_icon() |
5335 | * you should also install the icon in the icon theme, so |
5336 | * that the icon is generally available. |
5337 | * |
5338 | * This function will generally be used with pixbufs loaded |
5339 | * via gdk_pixbuf_new_from_inline(). |
5340 | * |
5341 | * Since: 2.4 |
5342 | * |
5343 | * Deprecated: 3.14: Use ctk_icon_theme_add_resource_path() |
5344 | * to add application-specific icons to the icon theme. |
5345 | */ |
5346 | void |
5347 | ctk_icon_theme_add_builtin_icon (const gchar *icon_name, |
5348 | gint size, |
5349 | GdkPixbuf *pixbuf) |
5350 | { |
5351 | BuiltinIcon *default_icon; |
5352 | GSList *icons; |
5353 | gpointer key; |
5354 | |
5355 | g_return_if_fail (icon_name != NULL)do { if ((icon_name != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "icon_name != NULL"); return ; } } while (0); |
5356 | g_return_if_fail (GDK_IS_PIXBUF (pixbuf))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((pixbuf)); GType __t = ((gdk_pixbuf_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "GDK_IS_PIXBUF (pixbuf)"); return; } } while (0); |
5357 | |
5358 | if (!icon_theme_builtin_icons) |
5359 | icon_theme_builtin_icons = g_hash_table_new (g_str_hash, g_str_equal); |
5360 | |
5361 | icons = g_hash_table_lookup (icon_theme_builtin_icons, icon_name); |
5362 | if (!icons) |
5363 | key = g_strdup (icon_name)g_strdup_inline (icon_name); |
5364 | else |
5365 | key = (gpointer)icon_name; /* Won't get stored */ |
5366 | |
5367 | default_icon = g_new (BuiltinIcon, 1)((BuiltinIcon *) g_malloc_n ((1), sizeof (BuiltinIcon))); |
5368 | default_icon->size = size; |
5369 | default_icon->pixbuf = g_object_ref (pixbuf)((__typeof__ (pixbuf)) (g_object_ref) (pixbuf)); |
5370 | icons = g_slist_prepend (icons, default_icon); |
5371 | |
5372 | /* Replaces value, leaves key untouched |
5373 | */ |
5374 | g_hash_table_insert (icon_theme_builtin_icons, key, icons); |
5375 | } |
5376 | |
5377 | /* Look up a builtin icon; the min_difference_p and |
5378 | * has_larger_p out parameters allow us to combine |
5379 | * this lookup with searching through the actual directories |
5380 | * of the “hicolor” icon theme. See theme_lookup_icon() |
5381 | * for how they are used. |
5382 | */ |
5383 | static BuiltinIcon * |
5384 | find_builtin_icon (const gchar *icon_name, |
5385 | gint size, |
5386 | gint scale, |
5387 | gint *min_difference_p) |
5388 | { |
5389 | GSList *icons = NULL((void*)0); |
5390 | gint min_difference = G_MAXINT2147483647; |
5391 | gboolean has_larger = FALSE(0); |
5392 | BuiltinIcon *min_icon = NULL((void*)0); |
5393 | |
5394 | if (!icon_theme_builtin_icons) |
5395 | return NULL((void*)0); |
5396 | |
5397 | size *= scale; |
5398 | |
5399 | icons = g_hash_table_lookup (icon_theme_builtin_icons, icon_name); |
5400 | |
5401 | while (icons) |
5402 | { |
5403 | BuiltinIcon *default_icon = icons->data; |
5404 | int min, max, difference; |
5405 | gboolean smaller; |
5406 | |
5407 | min = default_icon->size - 2; |
5408 | max = default_icon->size + 2; |
5409 | smaller = size < min; |
5410 | if (size < min) |
5411 | difference = min - size; |
5412 | else if (size > max) |
5413 | difference = size - max; |
5414 | else |
5415 | difference = 0; |
5416 | |
5417 | if (difference == 0) |
5418 | { |
5419 | min_difference = 0; |
5420 | min_icon = default_icon; |
5421 | break; |
5422 | } |
5423 | |
5424 | if (!has_larger) |
5425 | { |
5426 | if (difference < min_difference || smaller) |
5427 | { |
5428 | min_difference = difference; |
5429 | min_icon = default_icon; |
5430 | has_larger = smaller; |
5431 | } |
5432 | } |
5433 | else |
5434 | { |
5435 | if (difference < min_difference && smaller) |
5436 | { |
5437 | min_difference = difference; |
5438 | min_icon = default_icon; |
5439 | } |
5440 | } |
5441 | |
5442 | icons = icons->next; |
5443 | } |
5444 | |
5445 | if (min_difference_p) |
5446 | *min_difference_p = min_difference; |
5447 | |
5448 | return min_icon; |
5449 | } |
5450 | |
5451 | /** |
5452 | * ctk_icon_theme_lookup_by_gicon: |
5453 | * @icon_theme: a #CtkIconTheme |
5454 | * @icon: the #GIcon to look up |
5455 | * @size: desired icon size |
5456 | * @flags: flags modifying the behavior of the icon lookup |
5457 | * |
5458 | * Looks up an icon and returns a #CtkIconInfo containing information |
5459 | * such as the filename of the icon. The icon can then be rendered |
5460 | * into a pixbuf using ctk_icon_info_load_icon(). |
5461 | * |
5462 | * When rendering on displays with high pixel densities you should not |
5463 | * use a @size multiplied by the scaling factor returned by functions |
5464 | * like cdk_window_get_scale_factor(). Instead, you should use |
5465 | * ctk_icon_theme_lookup_by_gicon_for_scale(), as the assets loaded |
5466 | * for a given scaling factor may be different. |
5467 | * |
5468 | * Returns: (nullable) (transfer full): a #CtkIconInfo containing |
5469 | * information about the icon, or %NULL if the icon wasn’t |
5470 | * found. Unref with g_object_unref() |
5471 | * |
5472 | * Since: 2.14 |
5473 | */ |
5474 | CtkIconInfo * |
5475 | ctk_icon_theme_lookup_by_gicon (CtkIconTheme *icon_theme, |
5476 | GIcon *icon, |
5477 | gint size, |
5478 | CtkIconLookupFlags flags) |
5479 | { |
5480 | return ctk_icon_theme_lookup_by_gicon_for_scale (icon_theme, icon, |
5481 | size, 1, flags); |
5482 | } |
5483 | |
5484 | |
5485 | /** |
5486 | * ctk_icon_theme_lookup_by_gicon_for_scale: |
5487 | * @icon_theme: a #CtkIconTheme |
5488 | * @icon: the #GIcon to look up |
5489 | * @size: desired icon size |
5490 | * @scale: the desired scale |
5491 | * @flags: flags modifying the behavior of the icon lookup |
5492 | * |
5493 | * Looks up an icon and returns a #CtkIconInfo containing information |
5494 | * such as the filename of the icon. The icon can then be rendered into |
5495 | * a pixbuf using ctk_icon_info_load_icon(). |
5496 | * |
5497 | * Returns: (nullable) (transfer full): a #CtkIconInfo containing |
5498 | * information about the icon, or %NULL if the icon wasn’t |
5499 | * found. Unref with g_object_unref() |
5500 | * |
5501 | * Since: 3.10 |
5502 | */ |
5503 | CtkIconInfo * |
5504 | ctk_icon_theme_lookup_by_gicon_for_scale (CtkIconTheme *icon_theme, |
5505 | GIcon *icon, |
5506 | gint size, |
5507 | gint scale, |
5508 | CtkIconLookupFlags flags) |
5509 | { |
5510 | CtkIconInfo *info; |
5511 | |
5512 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((( void*)0)); } } while (0); |
5513 | g_return_val_if_fail (G_IS_ICON (icon), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon)); GType __t = ((g_icon_get_type ())); gboolean __r ; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "G_IS_ICON (icon)"); return (((void*)0)); } } while (0); |
5514 | g_warn_if_fail ((flags & CTK_ICON_LOOKUP_GENERIC_FALLBACK) == 0)do { if ((flags & CTK_ICON_LOOKUP_GENERIC_FALLBACK) == 0) ; else g_warn_message ("Ctk", "ctkicontheme.c", 5514, ((const char*) (__func__)), "(flags & CTK_ICON_LOOKUP_GENERIC_FALLBACK) == 0" ); } while (0); |
5515 | |
5516 | if (GDK_IS_PIXBUF (icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (icon)); GType __t = ((gdk_pixbuf_get_type ())); gboolean __r ; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
5517 | { |
5518 | GdkPixbuf *pixbuf; |
5519 | |
5520 | pixbuf = GDK_PIXBUF (icon)((((GdkPixbuf*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((icon)), ((gdk_pixbuf_get_type ())))))); |
5521 | |
5522 | if ((flags & CTK_ICON_LOOKUP_FORCE_SIZE) != 0) |
5523 | { |
5524 | gint width, height, max; |
5525 | gdouble pixbuf_scale; |
5526 | GdkPixbuf *scaled; |
5527 | |
5528 | width = gdk_pixbuf_get_width (pixbuf); |
5529 | height = gdk_pixbuf_get_height (pixbuf); |
5530 | max = MAX (width, height)(((width) > (height)) ? (width) : (height)); |
5531 | pixbuf_scale = (gdouble) size * scale / (gdouble) max; |
5532 | |
5533 | scaled = gdk_pixbuf_scale_simple (pixbuf, |
5534 | 0.5 + width * pixbuf_scale, |
5535 | 0.5 + height * pixbuf_scale, |
5536 | GDK_INTERP_BILINEAR); |
5537 | |
5538 | info = ctk_icon_info_new_for_pixbuf (icon_theme, scaled); |
5539 | |
5540 | g_object_unref (scaled); |
5541 | } |
5542 | else |
5543 | { |
5544 | info = ctk_icon_info_new_for_pixbuf (icon_theme, pixbuf); |
5545 | } |
5546 | |
5547 | return info; |
5548 | } |
5549 | else if (G_IS_FILE_ICON (icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (icon)); GType __t = ((g_file_icon_get_type ())); gboolean __r ; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
5550 | { |
5551 | GFile *file = g_file_icon_get_file (G_FILE_ICON (icon)((((GFileIcon*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((icon)), ((g_file_icon_get_type ()))))))); |
5552 | |
5553 | info = ctk_icon_info_new_for_file (file, size, scale); |
5554 | info->forced_size = (flags & CTK_ICON_LOOKUP_FORCE_SIZE) != 0; |
5555 | |
5556 | return info; |
5557 | } |
5558 | else if (G_IS_LOADABLE_ICON (icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (icon)); GType __t = ((g_loadable_icon_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
5559 | { |
5560 | info = icon_info_new (ICON_THEME_DIR_UNTHEMED, size, 1); |
5561 | info->loadable = G_LOADABLE_ICON (g_object_ref (icon))((((GLoadableIcon*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((((__typeof__ (icon)) (g_object_ref) (icon)))), ((g_loadable_icon_get_type ())))))); |
5562 | info->is_svg = FALSE(0); |
5563 | info->desired_size = size; |
5564 | info->desired_scale = scale; |
5565 | info->forced_size = (flags & CTK_ICON_LOOKUP_FORCE_SIZE) != 0; |
5566 | |
5567 | return info; |
5568 | } |
5569 | else if (G_IS_THEMED_ICON (icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (icon)); GType __t = ((g_themed_icon_get_type ())); gboolean __r ; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
5570 | { |
5571 | const gchar **names; |
5572 | |
5573 | names = (const gchar **)g_themed_icon_get_names (G_THEMED_ICON (icon)((((GThemedIcon*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((icon)), ((g_themed_icon_get_type ()))))))); |
5574 | info = ctk_icon_theme_choose_icon_for_scale (icon_theme, names, size, scale, flags); |
5575 | |
5576 | return info; |
5577 | } |
5578 | else if (G_IS_EMBLEMED_ICON (icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (icon)); GType __t = ((g_emblemed_icon_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
5579 | { |
5580 | GIcon *base, *emblem; |
5581 | GList *list, *l; |
5582 | CtkIconInfo *base_info, *emblem_info; |
5583 | |
5584 | G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push
clang diagnostic ignored "-Wdeprecated-declarations" |
5585 | if (CTK_IS_NUMERABLE_ICON (icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (icon)); GType __t = ((ctk_numerable_icon_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
5586 | _ctk_numerable_icon_set_background_icon_size (CTK_NUMERABLE_ICON (icon)((((CtkNumerableIcon*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((icon)), ((ctk_numerable_icon_get_type ()))) ))), size / 2); |
5587 | G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop |
5588 | |
5589 | base = g_emblemed_icon_get_icon (G_EMBLEMED_ICON (icon)((((GEmblemedIcon*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((icon)), ((g_emblemed_icon_get_type ()))))))); |
5590 | base_info = ctk_icon_theme_lookup_by_gicon_for_scale (icon_theme, base, size, scale, flags); |
5591 | if (base_info) |
5592 | { |
5593 | info = icon_info_dup (base_info); |
5594 | g_object_unref (base_info); |
5595 | |
5596 | list = g_emblemed_icon_get_emblems (G_EMBLEMED_ICON (icon)((((GEmblemedIcon*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((icon)), ((g_emblemed_icon_get_type ()))))))); |
5597 | for (l = list; l; l = l->next) |
5598 | { |
5599 | emblem = g_emblem_get_icon (G_EMBLEM (l->data)((((GEmblem*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((l->data)), ((g_emblem_get_type ()))))))); |
5600 | /* always force size for emblems */ |
5601 | emblem_info = ctk_icon_theme_lookup_by_gicon_for_scale (icon_theme, emblem, size / 2, scale, flags | CTK_ICON_LOOKUP_FORCE_SIZE); |
5602 | if (emblem_info) |
5603 | info->emblem_infos = g_slist_prepend (info->emblem_infos, emblem_info); |
5604 | } |
5605 | |
5606 | return info; |
5607 | } |
5608 | else |
5609 | return NULL((void*)0); |
5610 | } |
5611 | |
5612 | return NULL((void*)0); |
5613 | } |
5614 | |
5615 | /** |
5616 | * ctk_icon_info_new_for_pixbuf: |
5617 | * @icon_theme: a #CtkIconTheme |
5618 | * @pixbuf: the pixbuf to wrap in a #CtkIconInfo |
5619 | * |
5620 | * Creates a #CtkIconInfo for a #GdkPixbuf. |
5621 | * |
5622 | * Returns: (transfer full): a #CtkIconInfo |
5623 | * |
5624 | * Since: 2.14 |
5625 | */ |
5626 | CtkIconInfo * |
5627 | ctk_icon_info_new_for_pixbuf (CtkIconTheme *icon_theme, |
5628 | GdkPixbuf *pixbuf) |
5629 | { |
5630 | CtkIconInfo *info; |
5631 | |
5632 | g_return_val_if_fail (CTK_IS_ICON_THEME (icon_theme), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((icon_theme)); GType __t = ((ctk_icon_theme_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ICON_THEME (icon_theme)"); return ((( void*)0)); } } while (0); |
5633 | g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((pixbuf)); GType __t = ((gdk_pixbuf_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "GDK_IS_PIXBUF (pixbuf)"); return (((void*)0)); } } while (0); |
5634 | |
5635 | info = icon_info_new (ICON_THEME_DIR_UNTHEMED, 0, 1); |
5636 | info->pixbuf = g_object_ref (pixbuf)((__typeof__ (pixbuf)) (g_object_ref) (pixbuf)); |
5637 | info->scale = 1.0; |
5638 | |
5639 | return info; |
5640 | } |
5641 | |
5642 | CtkIconInfo * |
5643 | ctk_icon_info_new_for_file (GFile *file, |
5644 | gint size, |
5645 | gint scale) |
5646 | { |
5647 | CtkIconInfo *info; |
5648 | |
5649 | info = icon_info_new (ICON_THEME_DIR_UNTHEMED, size, 1); |
5650 | info->loadable = G_LOADABLE_ICON (g_file_icon_new (file))((((GLoadableIcon*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((g_file_icon_new (file))), ((g_loadable_icon_get_type ()) ))))); |
5651 | info->icon_file = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)); |
5652 | info->is_resource = g_file_has_uri_scheme (file, "resource"); |
5653 | |
5654 | if (info->is_resource) |
5655 | { |
5656 | gchar *uri; |
5657 | |
5658 | uri = g_file_get_uri (file); |
5659 | info->filename = g_strdup (uri + 11)g_strdup_inline (uri + 11); /* resource:// */ |
5660 | g_free (uri); |
5661 | } |
5662 | else |
5663 | { |
5664 | info->filename = g_file_get_path (file); |
5665 | } |
5666 | |
5667 | info->is_svg = suffix_from_name (info->filename) == ICON_SUFFIX_SVG; |
5668 | |
5669 | info->desired_size = size; |
5670 | info->desired_scale = scale; |
5671 | info->forced_size = FALSE(0); |
5672 | |
5673 | return info; |
5674 | } |