1From 431d1225b153c1a1389686920aed1d26ff3218b2 Mon Sep 17 00:00:00 2001
2From: Carlos Garnacho <carlos@lanedo.com>
3Date: Fri, 10 May 2013 18:24:26 +0200
4Subject: [PATCH 59/68] iconfactory: Add scale info to GtkIconSource
5
6GtkIconSource now has notions knows about scale, so it can correctly
7fetch the icon at the right scale for ICON_NAME source types.
8
9All default stock icons have been made to have a wildcarded scale,
10so it's up to the GtkIconTheme to do the scaling business.
11---
12 gtk/gtkiconfactory.c |  140 ++++++++++++++++++++++++++++++++------------------
13 gtk/gtkiconfactory.h |    7 ++-
14 2 files changed, 97 insertions(+), 50 deletions(-)
15
16diff --git a/gtk/gtkiconfactory.c b/gtk/gtkiconfactory.c
17index 0dc31e6..41d1ee7 100644
18--- a/gtk/gtkiconfactory.c
19+++ b/gtk/gtkiconfactory.c
20@@ -66,6 +66,7 @@ struct _GtkIconSource
21   GtkTextDirection direction;
22   GtkStateType state;
23   GtkIconSize size;
24+  gdouble scale;
25
26   /* If TRUE, then the parameter is wildcarded, and the above
27    * fields should be ignored. If FALSE, the parameter is
28@@ -74,6 +75,7 @@ struct _GtkIconSource
29   guint any_direction : 1;
30   guint any_state : 1;
31   guint any_size : 1;
32+  guint any_scale : 1;
33
34 #if defined (G_OS_WIN32) && !defined (_WIN64)
35   /* System codepage version of filename, for DLL ABI backward
36@@ -106,10 +108,10 @@ static GtkIconSize icon_size_register_intern (const gchar *name,
37					      gint         width,
38					      gint         height);
39
40-#define GTK_ICON_SOURCE_INIT(any_direction, any_state, any_size)	\
41+#define GTK_ICON_SOURCE_INIT(any_direction, any_state, any_size, any_scale)	\
42   { GTK_ICON_SOURCE_EMPTY, { NULL }, NULL,				\
43-   0, 0, 0,								\
44-   any_direction, any_state, any_size }
45+   0, 0, 0, 1,								\
46+   any_direction, any_state, any_size, any_scale }
47
48 G_DEFINE_TYPE_WITH_CODE (GtkIconFactory, gtk_icon_factory, G_TYPE_OBJECT,
49			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
50@@ -349,7 +351,7 @@ register_stock_icon (GtkIconFactory *factory,
51                      const gchar    *icon_name)
52 {
53   GtkIconSet *set = gtk_icon_set_new ();
54-  GtkIconSource source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE);
55+  GtkIconSource source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE, TRUE);
56
57   source.type = GTK_ICON_SOURCE_STATIC_ICON_NAME;
58   source.source.icon_name = (gchar *)icon_name;
59@@ -366,7 +368,7 @@ register_bidi_stock_icon (GtkIconFactory *factory,
60                           const gchar    *icon_name)
61 {
62   GtkIconSet *set = gtk_icon_set_new ();
63-  GtkIconSource source = GTK_ICON_SOURCE_INIT (FALSE, TRUE, TRUE);
64+  GtkIconSource source = GTK_ICON_SOURCE_INIT (FALSE, TRUE, TRUE, TRUE);
65
66   source.type = GTK_ICON_SOURCE_STATIC_ICON_NAME;
67   source.source.icon_name = (gchar *)icon_name;
68@@ -1094,12 +1096,14 @@ static GdkPixbuf *find_in_cache     (GtkIconSet       *icon_set,
69                                      GtkStyle         *style,
70                                      GtkTextDirection  direction,
71                                      GtkStateType      state,
72-                                     GtkIconSize       size);
73+                                     GtkIconSize       size,
74+				     gdouble           scale);
75 static void       add_to_cache      (GtkIconSet       *icon_set,
76                                      GtkStyle         *style,
77                                      GtkTextDirection  direction,
78                                      GtkStateType      state,
79                                      GtkIconSize       size,
80+                                     gdouble           scale,
81                                      GdkPixbuf        *pixbuf);
82 /* Clear icon set contents, drop references to all contained
83  * GdkPixbuf objects and forget all GtkIconSources. Used to
84@@ -1179,7 +1183,7 @@ gtk_icon_set_new_from_pixbuf (GdkPixbuf *pixbuf)
85 {
86   GtkIconSet *set;
87
88-  GtkIconSource source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE);
89+  GtkIconSource source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE, TRUE);
90
91   g_return_val_if_fail (pixbuf != NULL, NULL);
92
93@@ -1319,6 +1323,7 @@ find_best_matching_source (GtkIconSet       *icon_set,
94			   GtkTextDirection  direction,
95			   GtkStateType      state,
96			   GtkIconSize       size,
97+			   gdouble           scale,
98			   GSList           *failed)
99 {
100   GtkIconSource *source;
101@@ -1340,7 +1345,8 @@ find_best_matching_source (GtkIconSet       *icon_set,
102
103       if ((s->any_direction || (s->direction == direction)) &&
104           (s->any_state || (s->state == state)) &&
105-          (s->any_size || size == (GtkIconSize)-1 || (sizes_equivalent (size, s->size))))
106+          (s->any_size || size == (GtkIconSize)-1 || (sizes_equivalent (size, s->size))) &&
107+          (s->any_scale || (s->scale == scale)))
108         {
109	  if (!g_slist_find (failed, s))
110	    {
111@@ -1392,7 +1398,7 @@ render_icon_name_pixbuf (GtkIconSource    *icon_source,
112			 GtkIconSize       size,
113			 GtkWidget        *widget,
114			 const char       *detail,
115-                         gboolean          scale_requested)
116+                         gdouble           scale)
117 {
118   GdkPixbuf *pixbuf;
119   GdkPixbuf *tmp_pixbuf;
120@@ -1403,7 +1409,6 @@ render_icon_name_pixbuf (GtkIconSource    *icon_source,
121   gint width, height, pixel_size;
122   gint *sizes, *s, dist;
123   GError *error = NULL;
124-  gdouble scale = 1;
125
126   if (widget && gtk_widget_has_screen (widget))
127     screen = gtk_widget_get_screen (widget);
128@@ -1419,14 +1424,6 @@ render_icon_name_pixbuf (GtkIconSource    *icon_source,
129   icon_theme = gtk_icon_theme_get_for_screen (screen);
130   settings = gtk_settings_get_for_screen (screen);
131
132-  if (scale_requested && widget)
133-    {
134-      if (!widget->window)
135-        gtk_widget_realize (widget);
136-
137-      scale = gdk_window_get_scale_factor (widget->window);
138-    }
139-
140   if (!gtk_icon_size_lookup_for_settings (settings, size, &width, &height))
141     {
142       if (size == (GtkIconSize)-1)
143@@ -1469,7 +1466,7 @@ render_icon_name_pixbuf (GtkIconSource    *icon_source,
144	}
145     }
146
147-  pixel_size = MIN (width, height) * scale;
148+  pixel_size = MIN (width, height);
149
150   if (icon_source->direction != GTK_TEXT_DIR_NONE)
151     {
152@@ -1483,9 +1480,10 @@ render_icon_name_pixbuf (GtkIconSource    *icon_source,
153       names[1] = icon_source->source.icon_name;
154       names[2] = NULL;
155
156-      info = gtk_icon_theme_choose_icon (icon_theme,
157-                                         names,
158-                                         pixel_size, GTK_ICON_LOOKUP_USE_BUILTIN);
159+      info = gtk_icon_theme_choose_icon_for_scale (icon_theme,
160+                                                   names,
161+                                                   pixel_size, scale,
162+                                                   GTK_ICON_LOOKUP_USE_BUILTIN);
163       g_free (name_with_dir);
164       if (info)
165         {
166@@ -1495,10 +1493,10 @@ render_icon_name_pixbuf (GtkIconSource    *icon_source,
167     }
168   else
169     {
170-      tmp_pixbuf = gtk_icon_theme_load_icon (icon_theme,
171-                                             icon_source->source.icon_name,
172-                                             pixel_size, 0,
173-                                             &error);
174+      tmp_pixbuf = gtk_icon_theme_load_icon_for_scale (icon_theme,
175+                                                       icon_source->source.icon_name,
176+                                                       pixel_size, scale, 0,
177+                                                       &error);
178     }
179
180   if (!tmp_pixbuf)
181@@ -1534,7 +1532,7 @@ find_and_render_icon_source (GtkIconSet       *icon_set,
182			     GtkIconSize       size,
183			     GtkWidget         *widget,
184			     const char        *detail,
185-                             gboolean           scale_requested)
186+			     gdouble           scale)
187 {
188   GSList *failed = NULL;
189   GdkPixbuf *pixbuf = NULL;
190@@ -1551,7 +1549,7 @@ find_and_render_icon_source (GtkIconSet       *icon_set,
191    */
192   while (pixbuf == NULL)
193     {
194-      GtkIconSource *source = find_best_matching_source (icon_set, direction, state, size, failed);
195+      GtkIconSource *source = find_best_matching_source (icon_set, direction, state, size, scale, failed);
196
197       if (source == NULL)
198	break;
199@@ -1576,7 +1574,7 @@ find_and_render_icon_source (GtkIconSet       *icon_set,
200	case GTK_ICON_SOURCE_STATIC_ICON_NAME:
201	  pixbuf = render_icon_name_pixbuf (source, style,
202					    direction, state, size,
203-					    widget, detail, scale_requested);
204+					    widget, detail, scale);
205	  if (!pixbuf)
206	    failed = g_slist_prepend (failed, source);
207	  break;
208@@ -1601,7 +1599,7 @@ render_fallback_image (GtkStyle          *style,
209                        const char        *detail)
210 {
211   /* This icon can be used for any direction/state/size */
212-  static GtkIconSource fallback_source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE);
213+  static GtkIconSource fallback_source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE, TRUE);
214
215   if (fallback_source.type == GTK_ICON_SOURCE_EMPTY)
216     {
217@@ -1652,7 +1650,7 @@ _get_real_scale (GtkWidget   *widget,
218   settings = gtk_settings_get_for_screen (screen);
219   gtk_icon_size_lookup_for_settings (settings, size, &icon_width, NULL);
220
221-  return (gdouble) gdk_pixbuf_get_width (icon) / icon_width;
222+  return round ((gdouble) gdk_pixbuf_get_width (icon) / icon_width);
223 }
224
225 GdkPixbuf*
226@@ -1663,28 +1661,23 @@ gtk_icon_set_render_icon_internal (GtkIconSet        *icon_set,
227                                    GtkIconSize        size,
228                                    GtkWidget         *widget,
229                                    const char        *detail,
230-                                   gboolean           scale_requested,
231-                                   gdouble           *real_scale)
232+				   gdouble           *scale)
233 {
234   GdkPixbuf *icon;
235
236-  if (real_scale)
237-    *real_scale = 1;
238-
239   if (icon_set->sources == NULL)
240     return render_fallback_image (style, direction, state, size, widget, detail);
241
242   if (detail == NULL)
243     {
244       icon = find_in_cache (icon_set, style, direction,
245-                        state, size);
246+			    state, size, *scale);
247
248       if (icon)
249	{
250	  g_object_ref (icon);
251
252-          if (scale_requested && real_scale)
253-            *real_scale = _get_real_scale (widget, style, size, icon);
254+	  *scale = _get_real_scale (widget, style, size, icon);
255
256	  return icon;
257	}
258@@ -1692,16 +1685,15 @@ gtk_icon_set_render_icon_internal (GtkIconSet        *icon_set,
259
260
261   icon = find_and_render_icon_source (icon_set, style, direction, state, size,
262-				      widget, detail, scale_requested);
263+				      widget, detail, *scale);
264
265   if (icon == NULL)
266     icon = render_fallback_image (style, direction, state, size, widget, detail);
267
268-  if (detail == NULL)
269-    add_to_cache (icon_set, style, direction, state, size, icon);
270+  *scale = _get_real_scale (widget, style, size, icon);
271
272-  if (scale_requested && real_scale)
273-    *real_scale = _get_real_scale (widget, style, size, icon);
274+  if (detail == NULL)
275+    add_to_cache (icon_set, style, direction, state, size, *scale, icon);
276
277   return icon;
278 }
279@@ -1739,12 +1731,14 @@ gtk_icon_set_render_icon (GtkIconSet        *icon_set,
280                           GtkWidget         *widget,
281                           const char        *detail)
282 {
283+  gdouble scale = 1;
284+
285   g_return_val_if_fail (icon_set != NULL, NULL);
286   g_return_val_if_fail (style == NULL || GTK_IS_STYLE (style), NULL);
287
288   return gtk_icon_set_render_icon_internal (icon_set, style, direction,
289                                             state, size, widget, detail,
290-                                            FALSE, NULL);
291+                                            &scale);
292 }
293
294 GdkPixbuf*
295@@ -1755,19 +1749,22 @@ gtk_icon_set_render_icon_scaled (GtkIconSet        *icon_set,
296                                  GtkIconSize        size,
297                                  GtkWidget         *widget,
298                                  const char        *detail,
299-                                 gdouble           *real_scale)
300+                                 gdouble           *scale)
301 {
302   g_return_val_if_fail (icon_set != NULL, NULL);
303   g_return_val_if_fail (style == NULL || GTK_IS_STYLE (style), NULL);
304+  g_return_val_if_fail (scale != NULL, NULL);
305+
306+  *scale = MAX (*scale, 1);
307
308   return gtk_icon_set_render_icon_internal (icon_set, style, direction,
309                                             state, size, widget, detail,
310-                                            TRUE, real_scale);
311+                                            scale);
312 }
313
314 /* Order sources by their "wildness", so that "wilder" sources are
315  * greater than "specific" sources; for determining ordering,
316- * direction beats state beats size.
317+ * direction beats state beats size beats scale.
318  */
319
320 static int
321@@ -1788,6 +1785,10 @@ icon_source_compare (gconstpointer ap, gconstpointer bp)
322     return -1;
323   else if (a->any_size && !b->any_size)
324     return 1;
325+  else if (!a->any_scale && b->any_scale)
326+    return -1;
327+  else if (a->any_scale && !b->any_scale)
328+    return 1;
329   else
330     return 0;
331 }
332@@ -1965,10 +1966,12 @@ gtk_icon_source_new (void)
333   src->direction = GTK_TEXT_DIR_NONE;
334   src->size = GTK_ICON_SIZE_INVALID;
335   src->state = GTK_STATE_NORMAL;
336+  src->scale = 1;
337
338   src->any_direction = TRUE;
339   src->any_state = TRUE;
340   src->any_size = TRUE;
341+  src->any_scale = TRUE;
342
343   return src;
344 }
345@@ -2319,6 +2322,15 @@ gtk_icon_source_set_size_wildcarded (GtkIconSource *source,
346   source->any_size = setting != FALSE;
347 }
348
349+void
350+gtk_icon_source_set_scale_wildcarded (GtkIconSource *source,
351+                                      gboolean       setting)
352+{
353+  g_return_if_fail (source != NULL);
354+
355+  source->any_scale = setting != FALSE;
356+}
357+
358 /**
359  * gtk_icon_source_get_size_wildcarded:
360  * @source: a #GtkIconSource
361@@ -2367,6 +2379,14 @@ gtk_icon_source_get_direction_wildcarded (const GtkIconSource *source)
362   return source->any_direction;
363 }
364
365+gboolean
366+gtk_icon_source_get_scale_wildcarded (const GtkIconSource *source)
367+{
368+  g_return_val_if_fail (source != NULL, TRUE);
369+
370+  return source->any_scale;
371+}
372+
373 /**
374  * gtk_icon_source_set_direction:
375  * @source: a #GtkIconSource
376@@ -2433,6 +2453,15 @@ gtk_icon_source_set_size (GtkIconSource *source,
377   source->size = size;
378 }
379
380+void
381+gtk_icon_source_set_scale (GtkIconSource *source,
382+                           gdouble        scale)
383+{
384+  g_return_if_fail (source != NULL);
385+
386+  source->scale = scale;
387+}
388+
389 /**
390  * gtk_icon_source_get_direction:
391  * @source: a #GtkIconSource
392@@ -2486,6 +2515,14 @@ gtk_icon_source_get_size (const GtkIconSource *source)
393   return source->size;
394 }
395
396+gdouble
397+gtk_icon_source_get_scale (const GtkIconSource *source)
398+{
399+  g_return_val_if_fail (source != NULL, 0);
400+
401+  return source->scale;
402+}
403+
404 #define NUM_CACHED_ICONS 8
405
406 typedef struct _CachedIcon CachedIcon;
407@@ -2499,6 +2536,7 @@ struct _CachedIcon
408   GtkTextDirection direction;
409   GtkStateType state;
410   GtkIconSize size;
411+  gdouble scale;
412
413   GdkPixbuf *pixbuf;
414 };
415@@ -2529,7 +2567,8 @@ find_in_cache (GtkIconSet      *icon_set,
416                GtkStyle        *style,
417                GtkTextDirection direction,
418                GtkStateType     state,
419-               GtkIconSize      size)
420+               GtkIconSize      size,
421+               gdouble          scale)
422 {
423   GSList *tmp_list;
424   GSList *prev;
425@@ -2545,6 +2584,7 @@ find_in_cache (GtkIconSet      *icon_set,
426       if (icon->style == style &&
427           icon->direction == direction &&
428           icon->state == state &&
429+          icon->scale == scale &&
430           (size == (GtkIconSize)-1 || icon->size == size))
431         {
432           if (prev)
433@@ -2571,6 +2611,7 @@ add_to_cache (GtkIconSet      *icon_set,
434               GtkTextDirection direction,
435               GtkStateType     state,
436               GtkIconSize      size,
437+              gdouble          scale,
438               GdkPixbuf       *pixbuf)
439 {
440   CachedIcon *icon;
441@@ -2595,6 +2636,7 @@ add_to_cache (GtkIconSet      *icon_set,
442   icon->direction = direction;
443   icon->state = state;
444   icon->size = size;
445+  icon->scale = scale;
446   icon->pixbuf = pixbuf;
447
448   if (icon->style)
449diff --git a/gtk/gtkiconfactory.h b/gtk/gtkiconfactory.h
450index e38f8e6..d646ed9 100644
451--- a/gtk/gtkiconfactory.h
452+++ b/gtk/gtkiconfactory.h
453@@ -177,19 +177,24 @@ void             gtk_icon_source_set_state_wildcarded     (GtkIconSource       *
454                                                            gboolean             setting);
455 void             gtk_icon_source_set_size_wildcarded      (GtkIconSource       *source,
456                                                            gboolean             setting);
457+void             gtk_icon_source_set_scale_wildcarded     (GtkIconSource       *source,
458+                                                           gboolean             setting);
459 gboolean         gtk_icon_source_get_size_wildcarded      (const GtkIconSource *source);
460 gboolean         gtk_icon_source_get_state_wildcarded     (const GtkIconSource *source);
461 gboolean         gtk_icon_source_get_direction_wildcarded (const GtkIconSource *source);
462+gboolean         gtk_icon_source_get_scale_wildcarded     (const GtkIconSource *source);
463 void             gtk_icon_source_set_direction            (GtkIconSource       *source,
464                                                            GtkTextDirection     direction);
465 void             gtk_icon_source_set_state                (GtkIconSource       *source,
466                                                            GtkStateType         state);
467 void             gtk_icon_source_set_size                 (GtkIconSource       *source,
468                                                            GtkIconSize          size);
469+void             gtk_icon_source_set_scale                (GtkIconSource       *source,
470+                                                           gdouble              scale);
471 GtkTextDirection gtk_icon_source_get_direction            (const GtkIconSource *source);
472 GtkStateType     gtk_icon_source_get_state                (const GtkIconSource *source);
473 GtkIconSize      gtk_icon_source_get_size                 (const GtkIconSource *source);
474-
475+gdouble          gtk_icon_source_get_scale                (const GtkIconSource *source);
476
477 /* ignore this */
478 void _gtk_icon_set_invalidate_caches (void);
479--
4801.7.10.2 (Apple Git-33)
481