[gtk+/wip/window-scales: 16/16] icontheme: Add support for high resolution icons
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/window-scales: 16/16] icontheme: Add support for high resolution icons
- Date: Thu, 20 Jun 2013 18:05:44 +0000 (UTC)
commit 601e1982371ed77c51642d7f447d7bbfc5a750e3
Author: Carlos Garnacho <carlos lanedo com>
Date: Fri May 10 18:06:00 2013 +0200
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.
This is based on code by Carlos Garnacho with changes by Alexander
Larsson
gtk/gtkicontheme.c | 351 +++++++++++++++++++++++++++++++++++++++++++---------
gtk/gtkicontheme.h | 28 ++++
2 files changed, 320 insertions(+), 59 deletions(-)
---
diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c
index 9a8e4b3..62839a9 100644
--- a/gtk/gtkicontheme.c
+++ b/gtk/gtkicontheme.c
@@ -253,11 +253,13 @@ struct _GtkIconInfo
*/
IconThemeDirType dir_type;
gint dir_size;
+ gint dir_scale;
gint threshold;
/* Parameters influencing the scaled icon
*/
gint desired_size;
+ gint desired_scale;
guint raw_coordinates : 1;
guint forced_size : 1;
guint emblems_applied : 1;
@@ -295,6 +297,7 @@ typedef struct
int min_size;
int max_size;
int threshold;
+ int scale;
char *dir;
char *subdir;
@@ -333,6 +336,7 @@ static void theme_destroy (IconTheme *theme);
static GtkIconInfo *theme_lookup_icon (IconTheme *theme,
const char *icon_name,
int size,
+ gint scale,
gboolean allow_svg,
gboolean use_default_icons);
static void theme_list_icons (IconTheme *theme,
@@ -1365,11 +1369,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;
@@ -1597,6 +1601,7 @@ static GtkIconInfo *
choose_icon (GtkIconTheme *icon_theme,
const gchar *icon_names[],
gint size,
+ gint scale,
GtkIconLookupFlags flags)
{
GtkIconThemePrivate *priv;
@@ -1651,7 +1656,7 @@ choose_icon (GtkIconTheme *icon_theme,
for (l = priv->themes; l; l = l->next)
{
IconTheme *theme = l->data;
- icon_info = theme_lookup_icon (theme, icon_names[0], size, allow_svg, use_builtin);
+ icon_info = theme_lookup_icon (theme, icon_names[0], size, scale, allow_svg, use_builtin);
if (icon_info)
goto out;
}
@@ -1663,7 +1668,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;
}
@@ -1697,6 +1702,7 @@ choose_icon (GtkIconTheme *icon_theme,
DestroyIcon (hIcon);
icon_info->dir_type = ICON_THEME_DIR_UNTHEMED;
icon_info->dir_size = size;
+ icon_info->dir_scale = 1;
}
g_strfreev (resources);
}
@@ -1721,12 +1727,14 @@ choose_icon (GtkIconTheme *icon_theme,
icon_info->dir_type = ICON_THEME_DIR_UNTHEMED;
icon_info->dir_size = size;
+ icon_info->dir_scale = 1;
}
out:
if (icon_info)
{
icon_info->desired_size = size;
+ icon_info->desired_scale = scale;
icon_info->forced_size = (flags & GTK_ICON_LOOKUP_FORCE_SIZE) != 0;
icon_info->key.icon_names = g_strdupv ((char **)icon_names);
@@ -1800,12 +1808,51 @@ 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);
+}
+
+/**
+ * gtk_icon_theme_lookup_icon_for_scale:
+ * @icon_theme: a #GtkIconTheme
+ * @icon_name: the name of the icon to lookup
+ * @size: desired icon size
+ * @scale: the desired scale
+ * @flags: flags modifying the behavior of the icon lookup
+ *
+ * Looks up a named icon for a particular window scale and returns a
+ * structure containing information such as the filename of the
+ * icon. The icon can then be rendered into a pixbuf using
+ * gtk_icon_info_load_icon(). (gtk_icon_theme_load_icon() combines
+ * these two steps if all you need is the pixbuf.)
+ *
+ * Return value: (transfer full): a #GtkIconInfo object containing
+ * information about the icon, or %NULL if the icon wasn't found.
+ *
+ * Since: 3.10
+ */
+GtkIconInfo *
+gtk_icon_theme_lookup_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_name,
+ gint size,
+ gint 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));
@@ -1831,7 +1878,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);
}
@@ -1842,7 +1889,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;
@@ -1882,9 +1929,50 @@ 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);
}
+/**
+ * gtk_icon_theme_choose_icon_for_scale:
+ * @icon_theme: a #GtkIconTheme
+ * @icon_names: (array zero-terminated=1): %NULL-terminated array of
+ * icon names to lookup
+ * @size: desired icon size
+ * @scale: desired scale
+ * @flags: flags modifying the behavior of the icon lookup
+ *
+ * Looks up a named icon for a particular window scale and returns a
+ * structure containing information such as the filename of the
+ * icon. The icon can then be rendered into a pixbuf using
+ * gtk_icon_info_load_icon(). (gtk_icon_theme_load_icon() combines
+ * these two steps if all you need is the pixbuf.)
+ *
+ * If @icon_names contains more than one name, this function
+ * tries them all in the given order before falling back to
+ * inherited icon themes.
+ *
+ * Return value: (transfer full): a #GtkIconInfo object containing information
+ * about the icon, or %NULL if the icon wasn't found.
+ *
+ * Since: 3.10
+ */
+GtkIconInfo *
+gtk_icon_theme_choose_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_names[],
+ gint size,
+ gint 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)
@@ -1929,6 +2017,56 @@ 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);
+}
+
+/**
+ * gtk_icon_theme_load_icon_for_scale:
+ * @icon_theme: a #GtkIconTheme
+ * @icon_name: the name of the icon to lookup
+ * @size: the desired icon size. The resulting icon may not be
+ * exactly this size; see gtk_icon_info_load_icon().
+ * @scale: desired scale
+ * @flags: flags modifying the behavior of the icon lookup
+ * @error: (allow-none): Location to store error information on failure,
+ * or %NULL.
+ *
+ * Looks up an icon in an icon theme for a particular window scale,
+ * scales it to the given size and renders it into a pixbuf. This is a
+ * convenience function; if more details about the icon are needed,
+ * use gtk_icon_theme_lookup_icon() followed by
+ * gtk_icon_info_load_icon().
+ *
+ * Note that you probably want to listen for icon theme changes and
+ * update the icon. This is usually done by connecting to the
+ * GtkWidget::style-set signal. If for some reason you do not want to
+ * update the icon when the icon theme changes, you should consider
+ * using gdk_pixbuf_copy() to make a private copy of the pixbuf
+ * returned by this function. Otherwise GTK+ may need to keep the old
+ * icon theme loaded, which would be a waste of memory.
+ *
+ * Return value: (transfer full): the rendered icon; this may be a
+ * newly created icon or a new reference to an internal icon, so
+ * you must not modify the icon. Use g_object_unref() to release
+ * your reference to the icon. %NULL if the icon isn't found.
+ *
+ * Since: 3.10
+ **/
+GdkPixbuf *
+gtk_icon_theme_load_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_name,
+ gint size,
+ gint scale,
+ GtkIconLookupFlags flags,
+ GError **error)
+{
GtkIconInfo *icon_info;
GdkPixbuf *pixbuf = NULL;
@@ -1937,9 +2075,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,
@@ -2375,31 +2514,43 @@ 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,
+ gint 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;
+ *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);
+ /* If the range covers the scaled_size then there really is no scale difference */
+ *scale_diff = 0;
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:
@@ -2490,6 +2641,7 @@ static GtkIconInfo *
theme_lookup_icon (IconTheme *theme,
const char *icon_name,
int size,
+ gint scale,
gboolean allow_svg,
gboolean use_builtin)
{
@@ -2497,11 +2649,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;
@@ -2534,9 +2688,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)
{
@@ -2553,8 +2708,8 @@ theme_lookup_icon (IconTheme *theme,
{
/* for a matching non-scalable dir keep
* going and look for a closer match
- */
- difference = abs (size - dir->size);
+ */
+ difference = abs (size * scale - dir->size * dir->scale);
if (!match || difference < min_difference)
{
match = TRUE;
@@ -2564,24 +2719,29 @@ theme_lookup_icon (IconTheme *theme,
if (difference == 0)
break;
}
- }
-
+ }
+
if (!match)
{
if (!has_larger)
{
- if (difference < min_difference || smaller)
+ if (difference < min_difference ||
+ (difference == min_difference && (scale_diff < min_scale_diff)) ||
+ smaller)
{
min_difference = difference;
+ min_scale_diff = scale_diff;
min_dir = dir;
has_larger = smaller;
}
}
else
{
- if (difference < min_difference && smaller)
+ if ((difference < min_difference ||
+ (difference == min_difference && scale_diff < min_scale_diff)) && smaller)
{
min_difference = difference;
+ min_scale_diff = scale_diff;
min_dir = dir;
}
}
@@ -2663,6 +2823,7 @@ theme_lookup_icon (IconTheme *theme,
icon_info->dir_type = min_dir->type;
icon_info->dir_size = min_dir->size;
+ icon_info->dir_scale = min_dir->scale;
icon_info->threshold = min_dir->threshold;
return icon_info;
@@ -2881,6 +3042,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)
@@ -2928,6 +3090,11 @@ theme_subdir_load (GtkIconTheme *icon_theme,
else
threshold = 2;
+ 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;
@@ -2956,6 +3123,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);
@@ -3071,8 +3240,10 @@ icon_info_dup (GtkIconInfo *icon_info)
dup->data = icon_data_dup (icon_info->data);
dup->dir_type = icon_info->dir_type;
dup->dir_size = icon_info->dir_size;
+ dup->dir_scale = icon_info->dir_scale;
dup->threshold = icon_info->threshold;
dup->desired_size = icon_info->desired_size;
+ dup->desired_scale = icon_info->desired_scale;
dup->raw_coordinates = icon_info->raw_coordinates;
dup->forced_size = icon_info->forced_size;
dup->emblems_applied = icon_info->emblems_applied;
@@ -3088,6 +3259,7 @@ icon_info_new_builtin (BuiltinIcon *icon)
icon_info->cache_pixbuf = g_object_ref (icon->pixbuf);
icon_info->dir_type = ICON_THEME_DIR_THRESHOLD;
icon_info->dir_size = icon->size;
+ icon_info->dir_scale = 1;
icon_info->threshold = 2;
return icon_info;
@@ -3181,7 +3353,10 @@ gtk_icon_info_class_init (GtkIconInfoClass *klass)
* to a larger icon. These icons will be given
* the same base size as the larger icons to which
* they are attached.
- *
+ *
+ * Note that for scaled icons the base size does
+ * not include the base scale.
+ *
* Return value: the base size, or 0, if no base
* size is known for the icon.
*
@@ -3196,6 +3371,27 @@ gtk_icon_info_get_base_size (GtkIconInfo *icon_info)
}
/**
+ * gtk_icon_info_get_base_scale:
+ * @icon_info: a #GtkIconInfo
+ *
+ * Gets the base scale for the icon. The base scale is a scale for the
+ * icon that was specified by the icon theme creator. For instance an
+ * icon drawn for a high-dpi screen with window-scale 2 for a base
+ * size of 32 will be 64 pixels tall and have a base_scale of 2.
+ *
+ * Return value: the base scale.
+ *
+ * Since: 3.10
+ **/
+gint
+gtk_icon_info_get_base_scale (GtkIconInfo *icon_info)
+{
+ g_return_val_if_fail (icon_info != NULL, 0);
+
+ return icon_info->dir_scale;
+}
+
+/**
* gtk_icon_info_get_filename:
* @icon_info: a #GtkIconInfo
*
@@ -3355,6 +3551,7 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
gboolean scale_only)
{
int image_width, image_height;
+ int scaled_desired_size;
GdkPixbuf *source_pixbuf;
gboolean is_svg;
@@ -3379,6 +3576,8 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
if (icon_info->icon_file && !icon_info->loadable)
icon_info->loadable = G_LOADABLE_ICON (g_file_icon_new (icon_info->icon_file));
+ scaled_desired_size = icon_info->desired_size * icon_info->desired_scale;
+
is_svg = FALSE;
if (G_IS_FILE_ICON (icon_info->loadable))
{
@@ -3406,20 +3605,21 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
{
GInputStream *stream;
- icon_info->scale = icon_info->desired_size / 1000.;
+ icon_info->scale = scaled_desired_size / 1000.;
if (scale_only)
return TRUE;
-
+
+ /* TODO: We should have a load_at_scale */
stream = g_loadable_icon_load (icon_info->loadable,
- icon_info->desired_size,
+ scaled_desired_size,
NULL, NULL,
&icon_info->load_error);
if (stream)
{
icon_info->pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream,
- icon_info->desired_size,
- icon_info->desired_size,
+ scaled_desired_size,
+ scaled_desired_size,
TRUE,
NULL,
&icon_info->load_error);
@@ -3442,19 +3642,19 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
if (icon_info->forced_size)
icon_info->scale = -1;
else if (icon_info->dir_type == ICON_THEME_DIR_FIXED)
- icon_info->scale = 1.0;
+ icon_info->scale = (double) icon_info->desired_scale / icon_info->dir_scale;
else if (icon_info->dir_type == ICON_THEME_DIR_THRESHOLD)
{
- if (icon_info->desired_size >= icon_info->dir_size - icon_info->threshold &&
- icon_info->desired_size <= icon_info->dir_size + icon_info->threshold)
- icon_info->scale = 1.0;
+ if (scaled_desired_size >= (icon_info->dir_size - icon_info->threshold) * icon_info->dir_scale &&
+ scaled_desired_size <= (icon_info->dir_size + icon_info->threshold) * icon_info->dir_scale)
+ icon_info->scale = (double) icon_info->desired_scale / icon_info->dir_scale;
else if (icon_info->dir_size > 0)
- icon_info->scale =(gdouble) icon_info->desired_size / icon_info->dir_size;
+ icon_info->scale =(gdouble) scaled_desired_size / (icon_info->dir_size * icon_info->dir_scale);
}
else if (icon_info->dir_type == ICON_THEME_DIR_SCALABLE)
{
if (icon_info->dir_size > 0)
- icon_info->scale = (gdouble) icon_info->desired_size / icon_info->dir_size;
+ icon_info->scale = (gdouble) scaled_desired_size / (icon_info->dir_size * icon_info->dir_scale);
}
if (icon_info->scale >= 0. && scale_only)
@@ -3470,8 +3670,9 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
{
GInputStream *stream;
+ /* TODO: We should have a load_at_scale */
stream = g_loadable_icon_load (icon_info->loadable,
- icon_info->desired_size,
+ scaled_desired_size,
NULL, NULL,
&icon_info->load_error);
if (stream)
@@ -3495,7 +3696,7 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
{
gint image_size = MAX (image_width, image_height);
if (image_size > 0)
- icon_info->scale = (gdouble)icon_info->desired_size / (gdouble)image_size;
+ icon_info->scale = (gdouble)scaled_desired_size / (gdouble)image_size;
else
icon_info->scale = 1.0;
@@ -3910,8 +4111,8 @@ _gtk_icon_info_load_symbolic_internal (GtkIconInfo *icon_info,
stream = g_memory_input_stream_new_from_data (data, -1, g_free);
pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream,
- icon_info->desired_size,
- icon_info->desired_size,
+ icon_info->desired_size * icon_info->desired_scale,
+ icon_info->desired_size * icon_info->desired_scale,
TRUE,
NULL,
error);
@@ -4851,6 +5052,37 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
gint size,
GtkIconLookupFlags flags)
{
+ return gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme, icon,
+ size, 1, flags);
+}
+
+
+/**
+ * gtk_icon_theme_lookup_by_gicon_for_scale:
+ * @icon_theme: a #GtkIconTheme
+ * @icon: the #GIcon to look up
+ * @size: desired icon size
+ * @scale: the desired scale
+ * @flags: flags modifying the behavior of the icon lookup
+ *
+ * Looks up an icon and returns a structure containing
+ * information such as the filename of the icon.
+ * The icon can then be rendered into a pixbuf using
+ * gtk_icon_info_load_icon_for_scale ().
+ *
+ * Return value: (transfer full): a #GtkIconInfo structure containing
+ * information about the icon, or %NULL if the icon
+ * wasn't found. Unref with g_object_unref()
+ *
+ * Since: 2.14
+ */
+GtkIconInfo *
+gtk_icon_theme_lookup_by_gicon_for_scale (GtkIconTheme *icon_theme,
+ GIcon *icon,
+ gint size,
+ gint scale,
+ GtkIconLookupFlags flags)
+{
GtkIconInfo *info;
g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
@@ -4874,6 +5106,7 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
info->dir_type = ICON_THEME_DIR_UNTHEMED;
info->dir_size = size;
info->desired_size = size;
+ info->desired_scale = scale;
info->threshold = 2;
info->forced_size = (flags & GTK_ICON_LOOKUP_FORCE_SIZE) != 0;
@@ -4884,7 +5117,7 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
const gchar **names;
names = (const gchar **)g_themed_icon_get_names (G_THEMED_ICON (icon));
- info = gtk_icon_theme_choose_icon (icon_theme, names, size, flags);
+ info = gtk_icon_theme_choose_icon_for_scale (icon_theme, names, size, scale, flags);
return info;
}
@@ -4898,7 +5131,7 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
_gtk_numerable_icon_set_background_icon_size (GTK_NUMERABLE_ICON (icon), size / 2);
base = g_emblemed_icon_get_icon (G_EMBLEMED_ICON (icon));
- base_info = gtk_icon_theme_lookup_by_gicon (icon_theme, base, size, flags);
+ base_info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme, base, size, scale, flags);
if (base_info)
{
info = icon_info_dup (base_info);
@@ -4909,7 +5142,7 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
{
emblem = g_emblem_get_icon (G_EMBLEM (l->data));
/* always force size for emblems */
- emblem_info = gtk_icon_theme_lookup_by_gicon (icon_theme, emblem, size / 2, flags |
GTK_ICON_LOOKUP_FORCE_SIZE);
+ emblem_info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme, emblem, size / 2, scale,
flags | GTK_ICON_LOOKUP_FORCE_SIZE);
if (emblem_info)
info->emblem_infos = g_slist_prepend (info->emblem_infos, emblem_info);
}
@@ -4928,17 +5161,17 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
if ((flags & GTK_ICON_LOOKUP_FORCE_SIZE) != 0)
{
gint width, height, max;
- gdouble scale;
+ gdouble pixbuf_scale;
GdkPixbuf *scaled;
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
max = MAX (width, height);
- scale = (gdouble) size / (gdouble) max;
+ pixbuf_scale = (gdouble) size * scale / (gdouble) max;
scaled = gdk_pixbuf_scale_simple (pixbuf,
- 0.5 + width * scale,
- 0.5 + height * scale,
+ 0.5 + width * pixbuf_scale,
+ 0.5 + height * pixbuf_scale,
GDK_INTERP_BILINEAR);
info = gtk_icon_info_new_for_pixbuf (icon_theme, scaled);
diff --git a/gtk/gtkicontheme.h b/gtk/gtkicontheme.h
index 443457d..0902909 100644
--- a/gtk/gtkicontheme.h
+++ b/gtk/gtkicontheme.h
@@ -179,23 +179,49 @@ GtkIconInfo * gtk_icon_theme_lookup_icon (GtkIconTheme
const gchar *icon_name,
gint size,
GtkIconLookupFlags flags);
+GDK_AVAILABLE_IN_3_10
+GtkIconInfo * gtk_icon_theme_lookup_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_name,
+ gint size,
+ gint scale,
+ GtkIconLookupFlags flags);
+
GDK_AVAILABLE_IN_ALL
GtkIconInfo * gtk_icon_theme_choose_icon (GtkIconTheme *icon_theme,
const gchar *icon_names[],
gint size,
GtkIconLookupFlags flags);
+GDK_AVAILABLE_IN_3_10
+GtkIconInfo * gtk_icon_theme_choose_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_names[],
+ gint size,
+ gint scale,
+ GtkIconLookupFlags flags);
GDK_AVAILABLE_IN_ALL
GdkPixbuf * gtk_icon_theme_load_icon (GtkIconTheme *icon_theme,
const gchar *icon_name,
gint size,
GtkIconLookupFlags flags,
GError **error);
+GDK_AVAILABLE_IN_3_10
+GdkPixbuf * gtk_icon_theme_load_icon_for_scale (GtkIconTheme *icon_theme,
+ const gchar *icon_name,
+ gint size,
+ gint scale,
+ GtkIconLookupFlags flags,
+ GError **error);
GDK_AVAILABLE_IN_ALL
GtkIconInfo * gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
GIcon *icon,
gint size,
GtkIconLookupFlags flags);
+GtkIconInfo * gtk_icon_theme_lookup_by_gicon_for_scale (GtkIconTheme *icon_theme,
+ GIcon *icon,
+ gint size,
+ gint scale,
+ GtkIconLookupFlags flags);
+
GDK_AVAILABLE_IN_ALL
GList * gtk_icon_theme_list_icons (GtkIconTheme *icon_theme,
@@ -226,6 +252,8 @@ GtkIconInfo * gtk_icon_info_new_for_pixbuf (GtkIconTheme *icon_them
GDK_AVAILABLE_IN_ALL
gint gtk_icon_info_get_base_size (GtkIconInfo *icon_info);
+GDK_AVAILABLE_IN_3_10
+gint gtk_icon_info_get_base_scale (GtkIconInfo *icon_info);
GDK_AVAILABLE_IN_ALL
const gchar * gtk_icon_info_get_filename (GtkIconInfo *icon_info);
GDK_AVAILABLE_IN_ALL
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]