Fix 'mono' package typo
[mono.git] / bockbuild / mac-sdk / patches / gtk / 0058-icontheme-Add-support-for-high-resolution-icons.patch
1 From 75299b2806b1bed9e14081f2e108afb39e31896e Mon Sep 17 00:00:00 2001
2 From: Carlos Garnacho <carlos@lanedo.com>
3 Date: Fri, 10 May 2013 18:06:00 +0200
4 Subject: [PATCH 58/68] icontheme: Add support for high resolution icons
5
6 An optional OutputScale integer key has been added to index.theme
7 subdirs description, so icon themes may provide icons that are
8 more suitable to render at a (typically 2x) integer upscaled
9 resolution. This way it is possible to make eg. a 16x16@2x icon has a
10 real size of 32x32, but contains a similar level of detail to the
11 16x16 icon so things don't look any more cluttered on high-dpi
12 screens.
13
14 The pixbuf lookup has changed so it prefers a minimal scale change
15 that yields the minimal real size difference, so if looking up for
16 a 16x16 icon at 2x, it would first prefer 16x16@2x, then 32x32, and
17 then any other icon that's closest to match
18
19 There is now *_for_scale() variants for all GtkIconTheme ways
20 to directly or indirectly fetch a GdkPixbuf.
21 ---
22  gtk/gtkicontheme.c |  152 ++++++++++++++++++++++++++++++++++++++++------------
23  gtk/gtkicontheme.h |   17 +++++-
24  2 files changed, 135 insertions(+), 34 deletions(-)
25
26 diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c
27 index bf81546..500f0ab 100644
28 --- a/gtk/gtkicontheme.c
29 +++ b/gtk/gtkicontheme.c
30 @@ -168,6 +168,7 @@ typedef struct
31    int min_size;
32    int max_size;
33    int threshold;
34 +  int scale;
35
36    char *dir;
37    char *subdir;
38 @@ -206,6 +207,7 @@ static void         theme_destroy     (IconTheme        *theme);
39  static GtkIconInfo *theme_lookup_icon (IconTheme        *theme,
40                                        const char       *icon_name,
41                                        int               size,
42 +                                       gdouble           scale,
43                                        gboolean          allow_svg,
44                                        gboolean          use_default_icons);
45  static void         theme_list_icons  (IconTheme        *theme,
46 @@ -1161,11 +1163,11 @@ _gtk_icon_theme_ensure_builtin_cache (void)
47    IconThemeDir *dir;
48    static IconThemeDir dirs[5] =
49      {
50 -      { ICON_THEME_DIR_THRESHOLD, 0, 16, 16, 16, 2, NULL, "16", -1, NULL, NULL, NULL },
51 -      { ICON_THEME_DIR_THRESHOLD, 0, 20, 20, 20, 2, NULL, "20", -1,  NULL, NULL, NULL },
52 -      { ICON_THEME_DIR_THRESHOLD, 0, 24, 24, 24, 2, NULL, "24", -1, NULL, NULL, NULL },
53 -      { ICON_THEME_DIR_THRESHOLD, 0, 32, 32, 32, 2, NULL, "32", -1, NULL, NULL, NULL },
54 -      { ICON_THEME_DIR_THRESHOLD, 0, 48, 48, 48, 2, NULL, "48", -1, NULL, NULL, NULL }
55 +      { ICON_THEME_DIR_THRESHOLD, 0, 16, 16, 16, 2, 1, NULL, "16", -1, NULL, NULL, NULL },
56 +      { ICON_THEME_DIR_THRESHOLD, 0, 20, 20, 20, 2, 1, NULL, "20", -1,  NULL, NULL, NULL },
57 +      { ICON_THEME_DIR_THRESHOLD, 0, 24, 24, 24, 2, 1, NULL, "24", -1, NULL, NULL, NULL },
58 +      { ICON_THEME_DIR_THRESHOLD, 0, 32, 32, 32, 2, 1, NULL, "32", -1, NULL, NULL, NULL },
59 +      { ICON_THEME_DIR_THRESHOLD, 0, 48, 48, 48, 2, 1, NULL, "48", -1, NULL, NULL, NULL }
60      };
61    gint i;
62
63 @@ -1242,6 +1244,7 @@ static GtkIconInfo *
64  choose_icon (GtkIconTheme       *icon_theme,
65              const gchar        *icon_names[],
66              gint                size,
67 +             gdouble             scale,
68              GtkIconLookupFlags  flags)
69  {
70    GtkIconThemePrivate *priv;
71 @@ -1271,7 +1274,7 @@ choose_icon (GtkIconTheme       *icon_theme,
72
73        for (i = 0; icon_names[i]; i++)
74          {
75 -          icon_info = theme_lookup_icon (theme, icon_names[i], size, allow_svg, use_builtin);
76 +          icon_info = theme_lookup_icon (theme, icon_names[i], size, scale, allow_svg, use_builtin);
77            if (icon_info)
78              goto out;
79          }
80 @@ -1400,12 +1403,32 @@ gtk_icon_theme_lookup_icon (GtkIconTheme       *icon_theme,
81                             gint                size,
82                             GtkIconLookupFlags  flags)
83  {
84 +  g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
85 +  g_return_val_if_fail (icon_name != NULL, NULL);
86 +  g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
87 +                       (flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
88 +
89 +  GTK_NOTE (ICONTHEME,
90 +           g_print ("gtk_icon_theme_lookup_icon %s\n", icon_name));
91 +
92 +  return gtk_icon_theme_lookup_icon_for_scale (icon_theme, icon_name,
93 +                                               size, 1, flags);
94 +}
95 +
96 +GtkIconInfo *
97 +gtk_icon_theme_lookup_icon_for_scale (GtkIconTheme       *icon_theme,
98 +                                      const gchar        *icon_name,
99 +                                      gint                size,
100 +                                      gdouble             scale,
101 +                                      GtkIconLookupFlags  flags)
102 +{
103    GtkIconInfo *info;
104
105    g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
106    g_return_val_if_fail (icon_name != NULL, NULL);
107    g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
108                         (flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
109 +  g_return_val_if_fail (scale >= 1, NULL);
110
111    GTK_NOTE (ICONTHEME,
112             g_print ("gtk_icon_theme_lookup_icon %s\n", icon_name));
113 @@ -1431,7 +1454,7 @@ gtk_icon_theme_lookup_icon (GtkIconTheme       *icon_theme,
114          }
115        names[dashes + 1] = NULL;
116
117 -      info = choose_icon (icon_theme, (const gchar **) names, size, flags);
118 +      info = choose_icon (icon_theme, (const gchar **) names, size, scale, flags);
119
120        g_strfreev (names);
121      }
122 @@ -1442,7 +1465,7 @@ gtk_icon_theme_lookup_icon (GtkIconTheme       *icon_theme,
123        names[0] = icon_name;
124        names[1] = NULL;
125
126 -      info = choose_icon (icon_theme, names, size, flags);
127 +      info = choose_icon (icon_theme, names, size, scale, flags);
128      }
129
130    return info;
131 @@ -1483,9 +1506,26 @@ gtk_icon_theme_choose_icon (GtkIconTheme       *icon_theme,
132    g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
133                         (flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
134
135 -  return choose_icon (icon_theme, icon_names, size, flags);
136 +  return choose_icon (icon_theme, icon_names, size, 1, flags);
137 +}
138 +
139 +GtkIconInfo *
140 +gtk_icon_theme_choose_icon_for_scale (GtkIconTheme       *icon_theme,
141 +                                      const gchar        *icon_names[],
142 +                                      gint                size,
143 +                                      gdouble             scale,
144 +                                      GtkIconLookupFlags  flags)
145 +{
146 +  g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
147 +  g_return_val_if_fail (icon_names != NULL, NULL);
148 +  g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
149 +                       (flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
150 +  g_return_val_if_fail (scale >= 1, NULL);
151 +
152 +  return choose_icon (icon_theme, icon_names, size, scale, flags);
153  }
154
155 +
156  /* Error quark */
157  GQuark
158  gtk_icon_theme_error_quark (void)
159 @@ -1529,6 +1569,24 @@ gtk_icon_theme_load_icon (GtkIconTheme         *icon_theme,
160                           GtkIconLookupFlags    flags,
161                           GError              **error)
162  {
163 +  g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
164 +  g_return_val_if_fail (icon_name != NULL, NULL);
165 +  g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
166 +                       (flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
167 +  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
168 +
169 +  return gtk_icon_theme_load_icon_for_scale (icon_theme, icon_name,
170 +                                             size, 1, flags, error);
171 +}
172 +
173 +GdkPixbuf *
174 +gtk_icon_theme_load_icon_for_scale (GtkIconTheme        *icon_theme,
175 +                                    const gchar         *icon_name,
176 +                                    gint                 size,
177 +                                    gdouble              scale,
178 +                                    GtkIconLookupFlags   flags,
179 +                                    GError             **error)
180 +{
181    GtkIconInfo *icon_info;
182    GdkPixbuf *pixbuf = NULL;
183
184 @@ -1537,9 +1595,10 @@ gtk_icon_theme_load_icon (GtkIconTheme         *icon_theme,
185    g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
186                         (flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
187    g_return_val_if_fail (error == NULL || *error == NULL, NULL);
188 -
189 -  icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size,
190 -                                         flags | GTK_ICON_LOOKUP_USE_BUILTIN);
191 +  g_return_val_if_fail (scale >= 1, NULL);
192 +
193 +  icon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme, icon_name, size, scale,
194 +                                                    flags | GTK_ICON_LOOKUP_USE_BUILTIN);
195    if (!icon_info)
196      {
197        g_set_error (error, GTK_ICON_THEME_ERROR,  GTK_ICON_THEME_NOT_FOUND,
198 @@ -1976,31 +2035,42 @@ theme_dir_destroy (IconThemeDir *dir)
199  }
200
201  static int
202 -theme_dir_size_difference (IconThemeDir *dir, int size, gboolean *smaller)
203 +theme_dir_size_difference (IconThemeDir *dir,
204 +                           int           size,
205 +                           gdouble       scale,
206 +                           gboolean     *smaller,
207 +                           gint         *scale_diff)
208  {
209 +  int scaled_size, scaled_dir_size;
210    int min, max;
211 +
212 +  scaled_size = size * scale;
213 +  scaled_dir_size = dir->size * dir->scale;
214 +  *scale_diff = abs (scale - dir->scale);
215 +
216    switch (dir->type)
217      {
218      case ICON_THEME_DIR_FIXED:
219 -      *smaller = size < dir->size;
220 -      return abs (size - dir->size);
221 +      *smaller = scaled_size < scaled_dir_size;
222 +      return abs (scaled_size - scaled_dir_size);
223        break;
224      case ICON_THEME_DIR_SCALABLE:
225 -      *smaller = size < dir->min_size;
226 -      if (size < dir->min_size)
227 -       return dir->min_size - size;
228 -      if (size > dir->max_size)
229 -       return size - dir->max_size;
230 +      *scale_diff = 0;
231 +      *smaller = scaled_size < (dir->min_size * dir->scale);
232 +      if (scaled_size < (dir->min_size * dir->scale))
233 +       return (dir->min_size * dir->scale) - scaled_size;
234 +      if (size > (dir->max_size * dir->scale))
235 +       return scaled_size - (dir->max_size * dir->scale);
236        return 0;
237        break;
238      case ICON_THEME_DIR_THRESHOLD:
239 -      min = dir->size - dir->threshold;
240 -      max = dir->size + dir->threshold;
241 -      *smaller = size < min;
242 -      if (size < min)
243 -       return min - size;
244 -      if (size > max)
245 -       return size - max;
246 +      min = (dir->size - dir->threshold) * dir->scale;
247 +      max = (dir->size + dir->threshold) * dir->scale;
248 +      *smaller = scaled_size < min;
249 +      if (scaled_size < min)
250 +       return min - scaled_size;
251 +      if (scaled_size > max)
252 +       return scaled_size - max;
253        return 0;
254        break;
255      case ICON_THEME_DIR_UNTHEMED:
256 @@ -2091,6 +2161,7 @@ static GtkIconInfo *
257  theme_lookup_icon (IconTheme          *theme,
258                    const char         *icon_name,
259                    int                 size,
260 +                   gdouble             scale,
261                    gboolean            allow_svg,
262                    gboolean            use_builtin)
263  {
264 @@ -2098,11 +2169,13 @@ theme_lookup_icon (IconTheme          *theme,
265    IconThemeDir *dir, *min_dir;
266    char *file;
267    int min_difference, difference;
268 +  int min_scale_diff, scale_diff;
269    BuiltinIcon *closest_builtin = NULL;
270    gboolean smaller, has_larger, match;
271    IconSuffix suffix;
272
273    min_difference = G_MAXINT;
274 +  min_scale_diff = G_MAXINT;
275    min_dir = NULL;
276    has_larger = FALSE;
277    match = FALSE;
278 @@ -2135,9 +2208,10 @@ theme_lookup_icon (IconTheme          *theme,
279        suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL);
280        if (best_suffix (suffix, allow_svg) != ICON_SUFFIX_NONE)
281         {
282 -         difference = theme_dir_size_difference (dir, size, &smaller);
283 +         difference = theme_dir_size_difference (dir, size, scale,
284 +                                                  &smaller, &scale_diff);
285
286 -         if (difference == 0)
287 +         if (difference == 0 && scale_diff == 0)
288             {
289                if (dir->type == ICON_THEME_DIR_SCALABLE)
290                  {
291 @@ -2156,13 +2230,15 @@ theme_lookup_icon (IconTheme          *theme,
292                     * going and look for a closer match
293                     */
294                    difference = abs (size - dir->size);
295 -                  if (!match || difference < min_difference)
296 +                  if (!match ||
297 +                      (scale_diff <= min_scale_diff && difference < min_difference))
298                      {
299                        match = TRUE;
300                        min_difference = difference;
301 +                      min_scale_diff = scale_diff;
302                       min_dir = dir;
303                      }
304 -                  if (difference == 0)
305 +                  if (difference == 0 && scale_diff == 0)
306                      break;
307                  }
308             }
309 @@ -2171,18 +2247,20 @@ theme_lookup_icon (IconTheme          *theme,
310              {
311               if (!has_larger)
312                 {
313 -                 if (difference < min_difference || smaller)
314 +                 if ((scale_diff <= min_scale_diff && difference < min_difference) || (scale_diff == 0 && smaller))
315                     {
316                       min_difference = difference;
317 +                      min_scale_diff = scale_diff;
318                       min_dir = dir;
319                       has_larger = smaller;
320                     }
321                 }
322               else
323                 {
324 -                 if (difference < min_difference && smaller)
325 +                 if ((scale_diff <= min_scale_diff && difference < min_difference) && (scale_diff == 0 && smaller))
326                     {
327                       min_difference = difference;
328 +                      min_scale_diff = scale_diff;
329                       min_dir = dir;
330                     }
331                 }
332 @@ -2484,6 +2562,7 @@ theme_subdir_load (GtkIconTheme *icon_theme,
333    char *full_dir;
334    GError *error = NULL;
335    IconThemeDirMtime *dir_mtime;
336 +  int scale;
337
338    size = g_key_file_get_integer (theme_file, subdir, "Size", &error);
339    if (error)
340 @@ -2543,6 +2622,11 @@ theme_subdir_load (GtkIconTheme *icon_theme,
341        error = NULL;
342      }
343
344 +  if (g_key_file_has_key (theme_file, subdir, "OutputScale", NULL))
345 +    scale = g_key_file_get_integer (theme_file, subdir, "OutputScale", NULL);
346 +  else
347 +    scale = 1;
348 +
349    for (d = icon_theme->priv->dir_mtimes; d; d = d->next)
350      {
351        dir_mtime = (IconThemeDirMtime *)d->data;
352 @@ -2571,6 +2655,8 @@ theme_subdir_load (GtkIconTheme *icon_theme,
353           dir->dir = full_dir;
354           dir->icon_data = NULL;
355           dir->subdir = g_strdup (subdir);
356 +          dir->scale = scale;
357 +
358           if (dir_mtime->cache != NULL)
359              {
360               dir->cache = _gtk_icon_cache_ref (dir_mtime->cache);
361 diff --git a/gtk/gtkicontheme.h b/gtk/gtkicontheme.h
362 index 3611c74..9b29f96 100644
363 --- a/gtk/gtkicontheme.h
364 +++ b/gtk/gtkicontheme.h
365 @@ -141,16 +141,31 @@ GtkIconInfo * gtk_icon_theme_lookup_icon           (GtkIconTheme
366                                                     const gchar                 *icon_name,
367                                                     gint                         size,
368                                                     GtkIconLookupFlags           flags);
369 +GtkIconInfo * gtk_icon_theme_lookup_icon_for_scale (GtkIconTheme                *icon_theme,
370 +                                                    const gchar                 *icon_name,
371 +                                                    gint                         size,
372 +                                                    gdouble                      scale,
373 +                                                    GtkIconLookupFlags           flags);
374  GtkIconInfo * gtk_icon_theme_choose_icon           (GtkIconTheme                *icon_theme,
375                                                     const gchar                 *icon_names[],
376                                                     gint                         size,
377                                                     GtkIconLookupFlags           flags);
378 +GtkIconInfo * gtk_icon_theme_choose_icon_for_scale (GtkIconTheme                *icon_theme,
379 +                                                   const gchar                 *icon_names[],
380 +                                                   gint                         size,
381 +                                                    gdouble                      scale,
382 +                                                   GtkIconLookupFlags           flags);
383  GdkPixbuf *   gtk_icon_theme_load_icon             (GtkIconTheme                *icon_theme,
384                                                     const gchar                 *icon_name,
385                                                     gint                         size,
386                                                     GtkIconLookupFlags           flags,
387                                                     GError                     **error);
388 -
389 +GdkPixbuf *   gtk_icon_theme_load_icon_for_scale   (GtkIconTheme                *icon_theme,
390 +                                                    const gchar                 *icon_name,
391 +                                                    gint                         size,
392 +                                                    gdouble                      scale,
393 +                                                    GtkIconLookupFlags           flags,
394 +                                                    GError                     **error);
395  GtkIconInfo * gtk_icon_theme_lookup_by_gicon       (GtkIconTheme                *icon_theme,
396                                                      GIcon                       *icon,
397                                                      gint                         size,
398 --
399 1.7.10.2 (Apple Git-33)