linux-packaging-mono/external/bockbuild/packages/patches/gtk/0058-icontheme-Add-support-for-high-resolution-icons.patch
Xamarin Public Jenkins (auto-signing) 6bdd276d05 Imported Upstream version 5.0.0.42
Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
2017-04-10 11:41:01 +00:00

400 lines
16 KiB
Diff

From 75299b2806b1bed9e14081f2e108afb39e31896e Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlos@lanedo.com>
Date: Fri, 10 May 2013 18:06:00 +0200
Subject: [PATCH 58/68] icontheme: Add support for high resolution icons
An optional OutputScale integer key has been added to index.theme
subdirs description, so icon themes may provide icons that are
more suitable to render at a (typically 2x) integer upscaled
resolution. This way it is possible to make eg. a 16x16@2x icon has a
real size of 32x32, but contains a similar level of detail to the
16x16 icon so things don't look any more cluttered on high-dpi
screens.
The pixbuf lookup has changed so it prefers a minimal scale change
that yields the minimal real size difference, so if looking up for
a 16x16 icon at 2x, it would first prefer 16x16@2x, then 32x32, and
then any other icon that's closest to match
There is now *_for_scale() variants for all GtkIconTheme ways
to directly or indirectly fetch a GdkPixbuf.
---
gtk/gtkicontheme.c | 152 ++++++++++++++++++++++++++++++++++++++++------------
gtk/gtkicontheme.h | 17 +++++-
2 files changed, 135 insertions(+), 34 deletions(-)
diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c
index bf81546..500f0ab 100644
--- a/gtk/gtkicontheme.c
+++ b/gtk/gtkicontheme.c
@@ -168,6 +168,7 @@ typedef struct
int min_size;
int max_size;
int threshold;
+ int scale;
char *dir;
char *subdir;
@@ -206,6 +207,7 @@ static void theme_destroy (IconTheme *theme);
static GtkIconInfo *theme_lookup_icon (IconTheme *theme,
const char *icon_name,
int size,
+ gdouble scale,
gboolean allow_svg,
gboolean use_default_icons);
static void theme_list_icons (IconTheme *theme,
@@ -1161,11 +1163,11 @@ _gtk_icon_theme_ensure_builtin_cache (void)
IconThemeDir *dir;
static IconThemeDir dirs[5] =
{
- { ICON_THEME_DIR_THRESHOLD, 0, 16, 16, 16, 2, NULL, "16", -1, NULL, NULL, NULL },
- { ICON_THEME_DIR_THRESHOLD, 0, 20, 20, 20, 2, NULL, "20", -1, NULL, NULL, NULL },
- { ICON_THEME_DIR_THRESHOLD, 0, 24, 24, 24, 2, NULL, "24", -1, NULL, NULL, NULL },
- { ICON_THEME_DIR_THRESHOLD, 0, 32, 32, 32, 2, NULL, "32", -1, NULL, NULL, NULL },
- { ICON_THEME_DIR_THRESHOLD, 0, 48, 48, 48, 2, NULL, "48", -1, NULL, NULL, NULL }
+ { ICON_THEME_DIR_THRESHOLD, 0, 16, 16, 16, 2, 1, NULL, "16", -1, NULL, NULL, NULL },
+ { ICON_THEME_DIR_THRESHOLD, 0, 20, 20, 20, 2, 1, NULL, "20", -1, NULL, NULL, NULL },
+ { ICON_THEME_DIR_THRESHOLD, 0, 24, 24, 24, 2, 1, NULL, "24", -1, NULL, NULL, NULL },
+ { ICON_THEME_DIR_THRESHOLD, 0, 32, 32, 32, 2, 1, NULL, "32", -1, NULL, NULL, NULL },
+ { ICON_THEME_DIR_THRESHOLD, 0, 48, 48, 48, 2, 1, NULL, "48", -1, NULL, NULL, NULL }
};
gint i;
@@ -1242,6 +1244,7 @@ static GtkIconInfo *
choose_icon (GtkIconTheme *icon_theme,
const gchar *icon_names[],
gint size,
+ gdouble scale,
GtkIconLookupFlags flags)
{
GtkIconThemePrivate *priv;
@@ -1271,7 +1274,7 @@ choose_icon (GtkIconTheme *icon_theme,
for (i = 0; icon_names[i]; i++)
{
- icon_info = theme_lookup_icon (theme, icon_names[i], size, allow_svg, use_builtin);
+ icon_info = theme_lookup_icon (theme, icon_names[i], size, scale, allow_svg, use_builtin);
if (icon_info)
goto out;
}
@@ -1400,12 +1403,32 @@ gtk_icon_theme_lookup_icon (GtkIconTheme *icon_theme,
gint size,
GtkIconLookupFlags flags)
{
+ g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
+ g_return_val_if_fail (icon_name != NULL, NULL);
+ g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
+ (flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
+
+ GTK_NOTE (ICONTHEME,
+ g_print ("gtk_icon_theme_lookup_icon %s\n", icon_name));
+
+ return gtk_icon_theme_lookup_icon_for_scale (icon_theme, icon_name,
+ size, 1, flags);
+}
+
+GtkIconInfo *
+gtk_icon_theme_lookup_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_name,
+ gint size,
+ gdouble scale,
+ GtkIconLookupFlags flags)
+{
GtkIconInfo *info;
g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
g_return_val_if_fail (icon_name != NULL, NULL);
g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
(flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
+ g_return_val_if_fail (scale >= 1, NULL);
GTK_NOTE (ICONTHEME,
g_print ("gtk_icon_theme_lookup_icon %s\n", icon_name));
@@ -1431,7 +1454,7 @@ gtk_icon_theme_lookup_icon (GtkIconTheme *icon_theme,
}
names[dashes + 1] = NULL;
- info = choose_icon (icon_theme, (const gchar **) names, size, flags);
+ info = choose_icon (icon_theme, (const gchar **) names, size, scale, flags);
g_strfreev (names);
}
@@ -1442,7 +1465,7 @@ gtk_icon_theme_lookup_icon (GtkIconTheme *icon_theme,
names[0] = icon_name;
names[1] = NULL;
- info = choose_icon (icon_theme, names, size, flags);
+ info = choose_icon (icon_theme, names, size, scale, flags);
}
return info;
@@ -1483,9 +1506,26 @@ gtk_icon_theme_choose_icon (GtkIconTheme *icon_theme,
g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
(flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
- return choose_icon (icon_theme, icon_names, size, flags);
+ return choose_icon (icon_theme, icon_names, size, 1, flags);
+}
+
+GtkIconInfo *
+gtk_icon_theme_choose_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_names[],
+ gint size,
+ gdouble scale,
+ GtkIconLookupFlags flags)
+{
+ g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
+ g_return_val_if_fail (icon_names != NULL, NULL);
+ g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
+ (flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
+ g_return_val_if_fail (scale >= 1, NULL);
+
+ return choose_icon (icon_theme, icon_names, size, scale, flags);
}
+
/* Error quark */
GQuark
gtk_icon_theme_error_quark (void)
@@ -1529,6 +1569,24 @@ gtk_icon_theme_load_icon (GtkIconTheme *icon_theme,
GtkIconLookupFlags flags,
GError **error)
{
+ g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
+ g_return_val_if_fail (icon_name != NULL, NULL);
+ g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
+ (flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ return gtk_icon_theme_load_icon_for_scale (icon_theme, icon_name,
+ size, 1, flags, error);
+}
+
+GdkPixbuf *
+gtk_icon_theme_load_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_name,
+ gint size,
+ gdouble scale,
+ GtkIconLookupFlags flags,
+ GError **error)
+{
GtkIconInfo *icon_info;
GdkPixbuf *pixbuf = NULL;
@@ -1537,9 +1595,10 @@ gtk_icon_theme_load_icon (GtkIconTheme *icon_theme,
g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
(flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size,
- flags | GTK_ICON_LOOKUP_USE_BUILTIN);
+ g_return_val_if_fail (scale >= 1, NULL);
+
+ icon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme, icon_name, size, scale,
+ flags | GTK_ICON_LOOKUP_USE_BUILTIN);
if (!icon_info)
{
g_set_error (error, GTK_ICON_THEME_ERROR, GTK_ICON_THEME_NOT_FOUND,
@@ -1976,31 +2035,42 @@ theme_dir_destroy (IconThemeDir *dir)
}
static int
-theme_dir_size_difference (IconThemeDir *dir, int size, gboolean *smaller)
+theme_dir_size_difference (IconThemeDir *dir,
+ int size,
+ gdouble scale,
+ gboolean *smaller,
+ gint *scale_diff)
{
+ int scaled_size, scaled_dir_size;
int min, max;
+
+ scaled_size = size * scale;
+ scaled_dir_size = dir->size * dir->scale;
+ *scale_diff = abs (scale - dir->scale);
+
switch (dir->type)
{
case ICON_THEME_DIR_FIXED:
- *smaller = size < dir->size;
- return abs (size - dir->size);
+ *smaller = scaled_size < scaled_dir_size;
+ return abs (scaled_size - scaled_dir_size);
break;
case ICON_THEME_DIR_SCALABLE:
- *smaller = size < dir->min_size;
- if (size < dir->min_size)
- return dir->min_size - size;
- if (size > dir->max_size)
- return size - dir->max_size;
+ *scale_diff = 0;
+ *smaller = scaled_size < (dir->min_size * dir->scale);
+ if (scaled_size < (dir->min_size * dir->scale))
+ return (dir->min_size * dir->scale) - scaled_size;
+ if (size > (dir->max_size * dir->scale))
+ return scaled_size - (dir->max_size * dir->scale);
return 0;
break;
case ICON_THEME_DIR_THRESHOLD:
- min = dir->size - dir->threshold;
- max = dir->size + dir->threshold;
- *smaller = size < min;
- if (size < min)
- return min - size;
- if (size > max)
- return size - max;
+ min = (dir->size - dir->threshold) * dir->scale;
+ max = (dir->size + dir->threshold) * dir->scale;
+ *smaller = scaled_size < min;
+ if (scaled_size < min)
+ return min - scaled_size;
+ if (scaled_size > max)
+ return scaled_size - max;
return 0;
break;
case ICON_THEME_DIR_UNTHEMED:
@@ -2091,6 +2161,7 @@ static GtkIconInfo *
theme_lookup_icon (IconTheme *theme,
const char *icon_name,
int size,
+ gdouble scale,
gboolean allow_svg,
gboolean use_builtin)
{
@@ -2098,11 +2169,13 @@ theme_lookup_icon (IconTheme *theme,
IconThemeDir *dir, *min_dir;
char *file;
int min_difference, difference;
+ int min_scale_diff, scale_diff;
BuiltinIcon *closest_builtin = NULL;
gboolean smaller, has_larger, match;
IconSuffix suffix;
min_difference = G_MAXINT;
+ min_scale_diff = G_MAXINT;
min_dir = NULL;
has_larger = FALSE;
match = FALSE;
@@ -2135,9 +2208,10 @@ theme_lookup_icon (IconTheme *theme,
suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL);
if (best_suffix (suffix, allow_svg) != ICON_SUFFIX_NONE)
{
- difference = theme_dir_size_difference (dir, size, &smaller);
+ difference = theme_dir_size_difference (dir, size, scale,
+ &smaller, &scale_diff);
- if (difference == 0)
+ if (difference == 0 && scale_diff == 0)
{
if (dir->type == ICON_THEME_DIR_SCALABLE)
{
@@ -2156,13 +2230,15 @@ theme_lookup_icon (IconTheme *theme,
* going and look for a closer match
*/
difference = abs (size - dir->size);
- if (!match || difference < min_difference)
+ if (!match ||
+ (scale_diff <= min_scale_diff && difference < min_difference))
{
match = TRUE;
min_difference = difference;
+ min_scale_diff = scale_diff;
min_dir = dir;
}
- if (difference == 0)
+ if (difference == 0 && scale_diff == 0)
break;
}
}
@@ -2171,18 +2247,20 @@ theme_lookup_icon (IconTheme *theme,
{
if (!has_larger)
{
- if (difference < min_difference || smaller)
+ if ((scale_diff <= min_scale_diff && difference < min_difference) || (scale_diff == 0 && smaller))
{
min_difference = difference;
+ min_scale_diff = scale_diff;
min_dir = dir;
has_larger = smaller;
}
}
else
{
- if (difference < min_difference && smaller)
+ if ((scale_diff <= min_scale_diff && difference < min_difference) && (scale_diff == 0 && smaller))
{
min_difference = difference;
+ min_scale_diff = scale_diff;
min_dir = dir;
}
}
@@ -2484,6 +2562,7 @@ theme_subdir_load (GtkIconTheme *icon_theme,
char *full_dir;
GError *error = NULL;
IconThemeDirMtime *dir_mtime;
+ int scale;
size = g_key_file_get_integer (theme_file, subdir, "Size", &error);
if (error)
@@ -2543,6 +2622,11 @@ theme_subdir_load (GtkIconTheme *icon_theme,
error = NULL;
}
+ if (g_key_file_has_key (theme_file, subdir, "OutputScale", NULL))
+ scale = g_key_file_get_integer (theme_file, subdir, "OutputScale", NULL);
+ else
+ scale = 1;
+
for (d = icon_theme->priv->dir_mtimes; d; d = d->next)
{
dir_mtime = (IconThemeDirMtime *)d->data;
@@ -2571,6 +2655,8 @@ theme_subdir_load (GtkIconTheme *icon_theme,
dir->dir = full_dir;
dir->icon_data = NULL;
dir->subdir = g_strdup (subdir);
+ dir->scale = scale;
+
if (dir_mtime->cache != NULL)
{
dir->cache = _gtk_icon_cache_ref (dir_mtime->cache);
diff --git a/gtk/gtkicontheme.h b/gtk/gtkicontheme.h
index 3611c74..9b29f96 100644
--- a/gtk/gtkicontheme.h
+++ b/gtk/gtkicontheme.h
@@ -141,16 +141,31 @@ GtkIconInfo * gtk_icon_theme_lookup_icon (GtkIconTheme
const gchar *icon_name,
gint size,
GtkIconLookupFlags flags);
+GtkIconInfo * gtk_icon_theme_lookup_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_name,
+ gint size,
+ gdouble scale,
+ GtkIconLookupFlags flags);
GtkIconInfo * gtk_icon_theme_choose_icon (GtkIconTheme *icon_theme,
const gchar *icon_names[],
gint size,
GtkIconLookupFlags flags);
+GtkIconInfo * gtk_icon_theme_choose_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_names[],
+ gint size,
+ gdouble scale,
+ GtkIconLookupFlags flags);
GdkPixbuf * gtk_icon_theme_load_icon (GtkIconTheme *icon_theme,
const gchar *icon_name,
gint size,
GtkIconLookupFlags flags,
GError **error);
-
+GdkPixbuf * gtk_icon_theme_load_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_name,
+ gint size,
+ gdouble scale,
+ GtkIconLookupFlags flags,
+ GError **error);
GtkIconInfo * gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
GIcon *icon,
gint size,
--
1.7.10.2 (Apple Git-33)