From 431d1225b153c1a1389686920aed1d26ff3218b2 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 10 May 2013 18:24:26 +0200 Subject: [PATCH 59/68] iconfactory: Add scale info to GtkIconSource GtkIconSource now has notions knows about scale, so it can correctly fetch the icon at the right scale for ICON_NAME source types. All default stock icons have been made to have a wildcarded scale, so it's up to the GtkIconTheme to do the scaling business. --- gtk/gtkiconfactory.c | 140 ++++++++++++++++++++++++++++++++------------------ gtk/gtkiconfactory.h | 7 ++- 2 files changed, 97 insertions(+), 50 deletions(-) diff --git a/gtk/gtkiconfactory.c b/gtk/gtkiconfactory.c index 0dc31e6..41d1ee7 100644 --- a/gtk/gtkiconfactory.c +++ b/gtk/gtkiconfactory.c @@ -66,6 +66,7 @@ struct _GtkIconSource GtkTextDirection direction; GtkStateType state; GtkIconSize size; + gdouble scale; /* If TRUE, then the parameter is wildcarded, and the above * fields should be ignored. If FALSE, the parameter is @@ -74,6 +75,7 @@ struct _GtkIconSource guint any_direction : 1; guint any_state : 1; guint any_size : 1; + guint any_scale : 1; #if defined (G_OS_WIN32) && !defined (_WIN64) /* System codepage version of filename, for DLL ABI backward @@ -106,10 +108,10 @@ static GtkIconSize icon_size_register_intern (const gchar *name, gint width, gint height); -#define GTK_ICON_SOURCE_INIT(any_direction, any_state, any_size) \ +#define GTK_ICON_SOURCE_INIT(any_direction, any_state, any_size, any_scale) \ { GTK_ICON_SOURCE_EMPTY, { NULL }, NULL, \ - 0, 0, 0, \ - any_direction, any_state, any_size } + 0, 0, 0, 1, \ + any_direction, any_state, any_size, any_scale } G_DEFINE_TYPE_WITH_CODE (GtkIconFactory, gtk_icon_factory, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, @@ -349,7 +351,7 @@ register_stock_icon (GtkIconFactory *factory, const gchar *icon_name) { GtkIconSet *set = gtk_icon_set_new (); - GtkIconSource source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE); + GtkIconSource source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE, TRUE); source.type = GTK_ICON_SOURCE_STATIC_ICON_NAME; source.source.icon_name = (gchar *)icon_name; @@ -366,7 +368,7 @@ register_bidi_stock_icon (GtkIconFactory *factory, const gchar *icon_name) { GtkIconSet *set = gtk_icon_set_new (); - GtkIconSource source = GTK_ICON_SOURCE_INIT (FALSE, TRUE, TRUE); + GtkIconSource source = GTK_ICON_SOURCE_INIT (FALSE, TRUE, TRUE, TRUE); source.type = GTK_ICON_SOURCE_STATIC_ICON_NAME; source.source.icon_name = (gchar *)icon_name; @@ -1094,12 +1096,14 @@ static GdkPixbuf *find_in_cache (GtkIconSet *icon_set, GtkStyle *style, GtkTextDirection direction, GtkStateType state, - GtkIconSize size); + GtkIconSize size, + gdouble scale); static void add_to_cache (GtkIconSet *icon_set, GtkStyle *style, GtkTextDirection direction, GtkStateType state, GtkIconSize size, + gdouble scale, GdkPixbuf *pixbuf); /* Clear icon set contents, drop references to all contained * GdkPixbuf objects and forget all GtkIconSources. Used to @@ -1179,7 +1183,7 @@ gtk_icon_set_new_from_pixbuf (GdkPixbuf *pixbuf) { GtkIconSet *set; - GtkIconSource source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE); + GtkIconSource source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE, TRUE); g_return_val_if_fail (pixbuf != NULL, NULL); @@ -1319,6 +1323,7 @@ find_best_matching_source (GtkIconSet *icon_set, GtkTextDirection direction, GtkStateType state, GtkIconSize size, + gdouble scale, GSList *failed) { GtkIconSource *source; @@ -1340,7 +1345,8 @@ find_best_matching_source (GtkIconSet *icon_set, if ((s->any_direction || (s->direction == direction)) && (s->any_state || (s->state == state)) && - (s->any_size || size == (GtkIconSize)-1 || (sizes_equivalent (size, s->size)))) + (s->any_size || size == (GtkIconSize)-1 || (sizes_equivalent (size, s->size))) && + (s->any_scale || (s->scale == scale))) { if (!g_slist_find (failed, s)) { @@ -1392,7 +1398,7 @@ render_icon_name_pixbuf (GtkIconSource *icon_source, GtkIconSize size, GtkWidget *widget, const char *detail, - gboolean scale_requested) + gdouble scale) { GdkPixbuf *pixbuf; GdkPixbuf *tmp_pixbuf; @@ -1403,7 +1409,6 @@ render_icon_name_pixbuf (GtkIconSource *icon_source, gint width, height, pixel_size; gint *sizes, *s, dist; GError *error = NULL; - gdouble scale = 1; if (widget && gtk_widget_has_screen (widget)) screen = gtk_widget_get_screen (widget); @@ -1419,14 +1424,6 @@ render_icon_name_pixbuf (GtkIconSource *icon_source, icon_theme = gtk_icon_theme_get_for_screen (screen); settings = gtk_settings_get_for_screen (screen); - if (scale_requested && widget) - { - if (!widget->window) - gtk_widget_realize (widget); - - scale = gdk_window_get_scale_factor (widget->window); - } - if (!gtk_icon_size_lookup_for_settings (settings, size, &width, &height)) { if (size == (GtkIconSize)-1) @@ -1469,7 +1466,7 @@ render_icon_name_pixbuf (GtkIconSource *icon_source, } } - pixel_size = MIN (width, height) * scale; + pixel_size = MIN (width, height); if (icon_source->direction != GTK_TEXT_DIR_NONE) { @@ -1483,9 +1480,10 @@ render_icon_name_pixbuf (GtkIconSource *icon_source, names[1] = icon_source->source.icon_name; names[2] = NULL; - info = gtk_icon_theme_choose_icon (icon_theme, - names, - pixel_size, GTK_ICON_LOOKUP_USE_BUILTIN); + info = gtk_icon_theme_choose_icon_for_scale (icon_theme, + names, + pixel_size, scale, + GTK_ICON_LOOKUP_USE_BUILTIN); g_free (name_with_dir); if (info) { @@ -1495,10 +1493,10 @@ render_icon_name_pixbuf (GtkIconSource *icon_source, } else { - tmp_pixbuf = gtk_icon_theme_load_icon (icon_theme, - icon_source->source.icon_name, - pixel_size, 0, - &error); + tmp_pixbuf = gtk_icon_theme_load_icon_for_scale (icon_theme, + icon_source->source.icon_name, + pixel_size, scale, 0, + &error); } if (!tmp_pixbuf) @@ -1534,7 +1532,7 @@ find_and_render_icon_source (GtkIconSet *icon_set, GtkIconSize size, GtkWidget *widget, const char *detail, - gboolean scale_requested) + gdouble scale) { GSList *failed = NULL; GdkPixbuf *pixbuf = NULL; @@ -1551,7 +1549,7 @@ find_and_render_icon_source (GtkIconSet *icon_set, */ while (pixbuf == NULL) { - GtkIconSource *source = find_best_matching_source (icon_set, direction, state, size, failed); + GtkIconSource *source = find_best_matching_source (icon_set, direction, state, size, scale, failed); if (source == NULL) break; @@ -1576,7 +1574,7 @@ find_and_render_icon_source (GtkIconSet *icon_set, case GTK_ICON_SOURCE_STATIC_ICON_NAME: pixbuf = render_icon_name_pixbuf (source, style, direction, state, size, - widget, detail, scale_requested); + widget, detail, scale); if (!pixbuf) failed = g_slist_prepend (failed, source); break; @@ -1601,7 +1599,7 @@ render_fallback_image (GtkStyle *style, const char *detail) { /* This icon can be used for any direction/state/size */ - static GtkIconSource fallback_source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE); + static GtkIconSource fallback_source = GTK_ICON_SOURCE_INIT (TRUE, TRUE, TRUE, TRUE); if (fallback_source.type == GTK_ICON_SOURCE_EMPTY) { @@ -1652,7 +1650,7 @@ _get_real_scale (GtkWidget *widget, settings = gtk_settings_get_for_screen (screen); gtk_icon_size_lookup_for_settings (settings, size, &icon_width, NULL); - return (gdouble) gdk_pixbuf_get_width (icon) / icon_width; + return round ((gdouble) gdk_pixbuf_get_width (icon) / icon_width); } GdkPixbuf* @@ -1663,28 +1661,23 @@ gtk_icon_set_render_icon_internal (GtkIconSet *icon_set, GtkIconSize size, GtkWidget *widget, const char *detail, - gboolean scale_requested, - gdouble *real_scale) + gdouble *scale) { GdkPixbuf *icon; - if (real_scale) - *real_scale = 1; - if (icon_set->sources == NULL) return render_fallback_image (style, direction, state, size, widget, detail); if (detail == NULL) { icon = find_in_cache (icon_set, style, direction, - state, size); + state, size, *scale); if (icon) { g_object_ref (icon); - if (scale_requested && real_scale) - *real_scale = _get_real_scale (widget, style, size, icon); + *scale = _get_real_scale (widget, style, size, icon); return icon; } @@ -1692,16 +1685,15 @@ gtk_icon_set_render_icon_internal (GtkIconSet *icon_set, icon = find_and_render_icon_source (icon_set, style, direction, state, size, - widget, detail, scale_requested); + widget, detail, *scale); if (icon == NULL) icon = render_fallback_image (style, direction, state, size, widget, detail); - if (detail == NULL) - add_to_cache (icon_set, style, direction, state, size, icon); + *scale = _get_real_scale (widget, style, size, icon); - if (scale_requested && real_scale) - *real_scale = _get_real_scale (widget, style, size, icon); + if (detail == NULL) + add_to_cache (icon_set, style, direction, state, size, *scale, icon); return icon; } @@ -1739,12 +1731,14 @@ gtk_icon_set_render_icon (GtkIconSet *icon_set, GtkWidget *widget, const char *detail) { + gdouble scale = 1; + g_return_val_if_fail (icon_set != NULL, NULL); g_return_val_if_fail (style == NULL || GTK_IS_STYLE (style), NULL); return gtk_icon_set_render_icon_internal (icon_set, style, direction, state, size, widget, detail, - FALSE, NULL); + &scale); } GdkPixbuf* @@ -1755,19 +1749,22 @@ gtk_icon_set_render_icon_scaled (GtkIconSet *icon_set, GtkIconSize size, GtkWidget *widget, const char *detail, - gdouble *real_scale) + gdouble *scale) { g_return_val_if_fail (icon_set != NULL, NULL); g_return_val_if_fail (style == NULL || GTK_IS_STYLE (style), NULL); + g_return_val_if_fail (scale != NULL, NULL); + + *scale = MAX (*scale, 1); return gtk_icon_set_render_icon_internal (icon_set, style, direction, state, size, widget, detail, - TRUE, real_scale); + scale); } /* Order sources by their "wildness", so that "wilder" sources are * greater than "specific" sources; for determining ordering, - * direction beats state beats size. + * direction beats state beats size beats scale. */ static int @@ -1788,6 +1785,10 @@ icon_source_compare (gconstpointer ap, gconstpointer bp) return -1; else if (a->any_size && !b->any_size) return 1; + else if (!a->any_scale && b->any_scale) + return -1; + else if (a->any_scale && !b->any_scale) + return 1; else return 0; } @@ -1965,10 +1966,12 @@ gtk_icon_source_new (void) src->direction = GTK_TEXT_DIR_NONE; src->size = GTK_ICON_SIZE_INVALID; src->state = GTK_STATE_NORMAL; + src->scale = 1; src->any_direction = TRUE; src->any_state = TRUE; src->any_size = TRUE; + src->any_scale = TRUE; return src; } @@ -2319,6 +2322,15 @@ gtk_icon_source_set_size_wildcarded (GtkIconSource *source, source->any_size = setting != FALSE; } +void +gtk_icon_source_set_scale_wildcarded (GtkIconSource *source, + gboolean setting) +{ + g_return_if_fail (source != NULL); + + source->any_scale = setting != FALSE; +} + /** * gtk_icon_source_get_size_wildcarded: * @source: a #GtkIconSource @@ -2367,6 +2379,14 @@ gtk_icon_source_get_direction_wildcarded (const GtkIconSource *source) return source->any_direction; } +gboolean +gtk_icon_source_get_scale_wildcarded (const GtkIconSource *source) +{ + g_return_val_if_fail (source != NULL, TRUE); + + return source->any_scale; +} + /** * gtk_icon_source_set_direction: * @source: a #GtkIconSource @@ -2433,6 +2453,15 @@ gtk_icon_source_set_size (GtkIconSource *source, source->size = size; } +void +gtk_icon_source_set_scale (GtkIconSource *source, + gdouble scale) +{ + g_return_if_fail (source != NULL); + + source->scale = scale; +} + /** * gtk_icon_source_get_direction: * @source: a #GtkIconSource @@ -2486,6 +2515,14 @@ gtk_icon_source_get_size (const GtkIconSource *source) return source->size; } +gdouble +gtk_icon_source_get_scale (const GtkIconSource *source) +{ + g_return_val_if_fail (source != NULL, 0); + + return source->scale; +} + #define NUM_CACHED_ICONS 8 typedef struct _CachedIcon CachedIcon; @@ -2499,6 +2536,7 @@ struct _CachedIcon GtkTextDirection direction; GtkStateType state; GtkIconSize size; + gdouble scale; GdkPixbuf *pixbuf; }; @@ -2529,7 +2567,8 @@ find_in_cache (GtkIconSet *icon_set, GtkStyle *style, GtkTextDirection direction, GtkStateType state, - GtkIconSize size) + GtkIconSize size, + gdouble scale) { GSList *tmp_list; GSList *prev; @@ -2545,6 +2584,7 @@ find_in_cache (GtkIconSet *icon_set, if (icon->style == style && icon->direction == direction && icon->state == state && + icon->scale == scale && (size == (GtkIconSize)-1 || icon->size == size)) { if (prev) @@ -2571,6 +2611,7 @@ add_to_cache (GtkIconSet *icon_set, GtkTextDirection direction, GtkStateType state, GtkIconSize size, + gdouble scale, GdkPixbuf *pixbuf) { CachedIcon *icon; @@ -2595,6 +2636,7 @@ add_to_cache (GtkIconSet *icon_set, icon->direction = direction; icon->state = state; icon->size = size; + icon->scale = scale; icon->pixbuf = pixbuf; if (icon->style) diff --git a/gtk/gtkiconfactory.h b/gtk/gtkiconfactory.h index e38f8e6..d646ed9 100644 --- a/gtk/gtkiconfactory.h +++ b/gtk/gtkiconfactory.h @@ -177,19 +177,24 @@ void gtk_icon_source_set_state_wildcarded (GtkIconSource * gboolean setting); void gtk_icon_source_set_size_wildcarded (GtkIconSource *source, gboolean setting); +void gtk_icon_source_set_scale_wildcarded (GtkIconSource *source, + gboolean setting); gboolean gtk_icon_source_get_size_wildcarded (const GtkIconSource *source); gboolean gtk_icon_source_get_state_wildcarded (const GtkIconSource *source); gboolean gtk_icon_source_get_direction_wildcarded (const GtkIconSource *source); +gboolean gtk_icon_source_get_scale_wildcarded (const GtkIconSource *source); void gtk_icon_source_set_direction (GtkIconSource *source, GtkTextDirection direction); void gtk_icon_source_set_state (GtkIconSource *source, GtkStateType state); void gtk_icon_source_set_size (GtkIconSource *source, GtkIconSize size); +void gtk_icon_source_set_scale (GtkIconSource *source, + gdouble scale); GtkTextDirection gtk_icon_source_get_direction (const GtkIconSource *source); GtkStateType gtk_icon_source_get_state (const GtkIconSource *source); GtkIconSize gtk_icon_source_get_size (const GtkIconSource *source); - +gdouble gtk_icon_source_get_scale (const GtkIconSource *source); /* ignore this */ void _gtk_icon_set_invalidate_caches (void); -- 1.7.10.2 (Apple Git-33)