Compare commits

...

11 Commits

Author SHA1 Message Date
Carlos Garnacho
e167c9b88b Add missing GDK_AVAILABLE_IN_3_10 2013-05-14 12:53:37 +02:00
Carlos Garnacho
0fd0e02e44 entry: Add API/properties to deal with icons as icon sets
Icon sets are the best way to automatically deal with high resolution
icons, so allow setting the primary and secondary icons from a
GtkIconSet so the best pixbuf can be picked when rendering.
2013-05-14 12:53:37 +02:00
Carlos Garnacho
106b5dda7b cellrendererpixbuf: Add "icon-set" property
Icon sets are the best way to automatically deal with high resolution
icons, so expose these as a property for cell renderers.
2013-05-14 12:53:37 +02:00
Carlos Garnacho
f90b8404c5 iconhelper: Use GtkIconSet and gtk_cairo_set_source_icon_set() to render high-res icons
Now GtkIconSets are preferred over GdkPixbufs if the storage type goes through
these.

An scale argument has been added to _gtk_icon_helper_draw() to let callers tell
the output scale factor, as those typically have a GdkWindow around to fetch it
from, all callers were updated too.
2013-05-14 12:53:37 +02:00
Carlos Garnacho
9f31b05531 iconfactory: Add gtk_cairo_set_source_icon_set()
As GtkIconSet remains a good candidate to delay pixbuf lookup until
the moment of rendering, a cairo helper function has been added
to easy enabling support for high resolution icons.
2013-05-14 12:53:37 +02:00
Carlos Garnacho
2476a1a7c9 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.
2013-05-14 12:53:37 +02:00
Carlos Garnacho
7540dd751a 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.
2013-05-14 12:53:37 +02:00
Carlos Garnacho
fad5a1d69b widget: Add _scaled() variants for icon rendering
Likewise to the iconfactory changes, this API allows to
deal with stock icons at sizes that are suitable for
gdk_window_get_scale_factor()
2013-05-14 12:53:36 +02:00
Carlos Garnacho
a0c67c53fa iconfactory: Add _scaled() variants
These functions can be used to deal with stock icons
at sizes that are suitable for gdk_window_get_scale_factor()
2013-05-14 12:53:36 +02:00
Michael Natterer
d7c9342abb gtk: add gtk_widget_get_scale_factor() 2013-05-14 12:53:36 +02:00
Michael Natterer
81780731af quartz: add gdk_screen_ and gdk_window_get_scale_factor()
which return 1.0 normally and 2.0 on retina displays.
2013-05-14 12:53:36 +02:00
22 changed files with 703 additions and 133 deletions

View File

@@ -1048,3 +1048,21 @@ gdk_screen_get_setting (GdkScreen *screen,
return GDK_SCREEN_GET_CLASS (screen)->get_setting (screen, name, value);
}
gdouble
gdk_screen_get_monitor_scale_factor (GdkScreen *screen,
gint monitor_num)
{
GdkScreenClass *screen_class;
g_return_val_if_fail (GDK_IS_SCREEN (screen), 1.0);
g_return_val_if_fail (monitor_num >= 0, 1.0);
g_return_val_if_fail (monitor_num < gdk_screen_get_n_monitors (screen), 1.0);
screen_class = GDK_SCREEN_GET_CLASS (screen);
if (screen_class->get_monitor_scale_factor)
return screen_class->get_monitor_scale_factor (screen, monitor_num);
return 1.0;
}

View File

@@ -99,6 +99,9 @@ gint gdk_screen_get_monitor_height_mm (GdkScreen *screen,
GDK_AVAILABLE_IN_ALL
gchar * gdk_screen_get_monitor_plug_name (GdkScreen *screen,
gint monitor_num);
GDK_AVAILABLE_IN_3_10
gdouble gdk_screen_get_monitor_scale_factor (GdkScreen *screen,
gint monitor_num);
GDK_AVAILABLE_IN_ALL
GdkScreen *gdk_screen_get_default (void);

View File

@@ -91,7 +91,8 @@ struct _GdkScreenClass
void (* query_visual_types) (GdkScreen *screen,
GdkVisualType **visual_types,
gint *count);
gdouble (* get_monitor_scale_factor) (GdkScreen *screen,
gint monitor_num);
/* Signals: */
void (*size_changed) (GdkScreen *screen);

View File

@@ -10550,3 +10550,22 @@ gdk_window_get_frame_clock (GdkWindow *window)
return toplevel->frame_clock;
}
gdouble
gdk_window_get_scale_factor (GdkWindow *window)
{
GdkWindowImplClass *impl_class;
g_return_val_if_fail (GDK_IS_WINDOW (window), 1.0);
if (GDK_WINDOW_DESTROYED (window))
return 1.0;
window = gdk_window_get_toplevel (window);
impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
if (impl_class->get_scale_factor)
return impl_class->get_scale_factor (window);
return 1.0;
}

View File

@@ -829,6 +829,9 @@ GDK_AVAILABLE_IN_ALL
void gdk_window_get_frame_extents (GdkWindow *window,
GdkRectangle *rect);
GDK_AVAILABLE_IN_3_10
gdouble gdk_window_get_scale_factor (GdkWindow *window);
#ifndef GDK_MULTIDEVICE_SAFE
GDK_DEPRECATED_IN_3_0_FOR(gdk_window_get_device_position)
GdkWindow * gdk_window_get_pointer (GdkWindow *window,

View File

@@ -285,6 +285,8 @@ struct _GdkWindowImplClass
gint n_elements);
void (*delete_property) (GdkWindow *window,
GdkAtom property);
gdouble (* get_scale_factor) (GdkWindow *window);
};
/* Interface Functions */

View File

@@ -427,6 +427,35 @@ gdk_quartz_screen_get_monitor_workarea (GdkScreen *screen,
GDK_QUARTZ_RELEASE_POOL;
}
/* Protocol to build cleanly for OSX < 10.7 */
@protocol ScaleFactor
- (CGFloat) backingScaleFactor;
@end
gdouble
_gdk_quartz_screen_get_monitor_scale_factor (GdkScreen *screen,
gint monitor_num)
{
GdkScreenQuartz *quartz_screen;
NSArray *array;
NSScreen *nsscreen;
gdouble scale_factor = 1.0;
quartz_screen = GDK_SCREEN_QUARTZ (screen);
GDK_QUARTZ_ALLOC_POOL;
array = [NSScreen screens];
nsscreen = [array objectAtIndex:monitor_num];
if (gdk_quartz_osx_version() >= GDK_OSX_LION)
scale_factor = [(id <ScaleFactor>) nsscreen backingScaleFactor];
GDK_QUARTZ_RELEASE_POOL;
return scale_factor;
}
static gchar *
gdk_quartz_screen_make_display_name (GdkScreen *screen)
{
@@ -491,4 +520,5 @@ gdk_quartz_screen_class_init (GdkQuartzScreenClass *klass)
screen_class->query_depths = _gdk_quartz_screen_query_depths;
screen_class->query_visual_types = _gdk_quartz_screen_query_visual_types;
screen_class->list_visuals = _gdk_quartz_screen_list_visuals;
screen_class->get_monitor_scale_factor = _gdk_quartz_screen_get_monitor_scale_factor;
}

View File

@@ -2997,6 +2997,26 @@ gdk_quartz_window_get_input_shape (GdkWindow *window)
return NULL;
}
/* Protocol to build cleanly for OSX < 10.7 */
@protocol ScaleFactor
- (CGFloat) backingScaleFactor;
@end
static gdouble
gdk_quartz_window_get_scale_factor (GdkWindow *window)
{
GdkWindowImplQuartz *impl;
if (GDK_WINDOW_DESTROYED (window))
return 1.0;
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
if (gdk_quartz_osx_version() >= GDK_OSX_LION)
return [(id <ScaleFactor>) impl->toplevel backingScaleFactor];
return 1.0;
}
static void
gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
@@ -3036,6 +3056,7 @@ gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
impl_class->get_input_shape = gdk_quartz_window_get_input_shape;
impl_class->begin_paint_region = gdk_window_impl_quartz_begin_paint_region;
impl_class->end_paint = gdk_window_impl_quartz_end_paint;
impl_class->get_scale_factor = gdk_quartz_window_get_scale_factor;
impl_class->focus = gdk_quartz_window_focus;
impl_class->set_type_hint = gdk_quartz_window_set_type_hint;
@@ -3089,6 +3110,7 @@ gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
impl_quartz_class->get_context = gdk_window_impl_quartz_get_context;
impl_quartz_class->release_context = gdk_window_impl_quartz_release_context;
}
GType

View File

@@ -79,7 +79,8 @@ enum {
PROP_STOCK_DETAIL,
PROP_FOLLOW_STATE,
PROP_ICON_NAME,
PROP_GICON
PROP_GICON,
PROP_ICON_SET
};
@@ -247,6 +248,13 @@ gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class)
G_TYPE_ICON,
GTK_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_ICON_SET,
g_param_spec_boxed ("icon-set",
P_("Icon set"),
P_("Icon set to render the image from"),
GTK_TYPE_ICON_SET,
GTK_PARAM_READABLE));
g_type_class_add_private (object_class, sizeof (GtkCellRendererPixbufPrivate));
@@ -292,6 +300,9 @@ gtk_cell_renderer_pixbuf_get_property (GObject *object,
case PROP_GICON:
g_value_set_object (value, _gtk_icon_helper_peek_gicon (priv->icon_helper));
break;
case PROP_ICON_SET:
g_value_set_boxed (value, _gtk_icon_helper_peek_icon_set (priv->icon_helper));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -318,6 +329,9 @@ gtk_cell_renderer_pixbuf_reset (GtkCellRendererPixbuf *cellpixbuf)
case GTK_IMAGE_GICON:
g_object_notify (G_OBJECT (cellpixbuf), "gicon");
break;
case GTK_IMAGE_ICON_SET:
g_object_notify (G_OBJECT (cellpixbuf), "icon-set");
break;
case GTK_IMAGE_EMPTY:
default:
break;
@@ -374,6 +388,10 @@ gtk_cell_renderer_pixbuf_set_property (GObject *object,
gtk_cell_renderer_pixbuf_reset (cellpixbuf);
_gtk_icon_helper_set_gicon (priv->icon_helper, g_value_get_object (value), priv->icon_size);
break;
case PROP_ICON_SET:
gtk_cell_renderer_pixbuf_reset (cellpixbuf);
_gtk_icon_helper_set_icon_set (priv->icon_helper, g_value_get_boxed (value), priv->icon_size);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -549,6 +567,7 @@ gtk_cell_renderer_pixbuf_render (GtkCellRenderer *cell,
_gtk_icon_helper_draw (icon_helper,
context, cr,
gtk_widget_get_scale_factor (widget),
pix_rect.x, pix_rect.y);
g_object_unref (icon_helper);

View File

@@ -321,7 +321,9 @@ enum {
PROP_INPUT_PURPOSE,
PROP_INPUT_HINTS,
PROP_ATTRIBUTES,
PROP_POPULATE_ALL
PROP_POPULATE_ALL,
PROP_ICON_SET_PRIMARY,
PROP_ICON_SET_SECONDARY
};
static guint signals[LAST_SIGNAL] = { 0 };
@@ -1148,7 +1150,21 @@ gtk_entry_class_init (GtkEntryClass *class)
P_("GIcon for secondary icon"),
G_TYPE_ICON,
GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_ICON_SET_PRIMARY,
g_param_spec_boxed ("primary-icon-set",
P_("Primary icon set"),
P_("Icon set for the primary icon"),
GTK_TYPE_ICON_SET,
GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_ICON_SET_SECONDARY,
g_param_spec_boxed ("secondary-icon-set",
P_("Secondary icon set"),
P_("Icon set for the secondary icon"),
GTK_TYPE_ICON_SET,
GTK_PARAM_READWRITE));
/**
* GtkEntry:primary-icon-storage-type:
*
@@ -2196,6 +2212,18 @@ gtk_entry_set_property (GObject *object,
g_value_get_object (value));
break;
case PROP_ICON_SET_PRIMARY:
gtk_entry_set_icon_from_icon_set (entry,
GTK_ENTRY_ICON_PRIMARY,
g_value_get_boxed (value));
break;
case PROP_ICON_SET_SECONDARY:
gtk_entry_set_icon_from_icon_set (entry,
GTK_ENTRY_ICON_SECONDARY,
g_value_get_boxed (value));
break;
case PROP_ACTIVATABLE_PRIMARY:
gtk_entry_set_icon_activatable (entry,
GTK_ENTRY_ICON_PRIMARY,
@@ -2438,6 +2466,18 @@ gtk_entry_get_property (GObject *object,
GTK_ENTRY_ICON_SECONDARY));
break;
case PROP_ICON_SET_PRIMARY:
g_value_set_boxed (value,
gtk_entry_get_icon_set (entry,
GTK_ENTRY_ICON_PRIMARY));
break;
case PROP_ICON_SET_SECONDARY:
g_value_set_boxed (value,
gtk_entry_get_icon_set (entry,
GTK_ENTRY_ICON_SECONDARY));
break;
case PROP_STORAGE_TYPE_PRIMARY:
g_value_set_enum (value,
gtk_entry_get_icon_storage_type (entry,
@@ -3641,6 +3681,7 @@ draw_icon (GtkWidget *widget,
_gtk_icon_helper_draw (icon_info->icon_helper,
context, cr,
gtk_widget_get_scale_factor (widget),
x, y);
gtk_style_context_restore (context);
@@ -7113,6 +7154,11 @@ gtk_entry_clear (GtkEntry *entry,
icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-gicon" : "secondary-icon-gicon");
break;
case GTK_IMAGE_ICON_SET:
g_object_notify (G_OBJECT (entry),
icon_pos == GTK_ENTRY_ICON_PRIMARY ? "primary-icon-set" : "secondary-icon-set");
break;
default:
g_assert_not_reached ();
break;
@@ -8305,6 +8351,58 @@ gtk_entry_set_icon_from_gicon (GtkEntry *entry,
g_object_thaw_notify (G_OBJECT (entry));
}
void
gtk_entry_set_icon_from_icon_set (GtkEntry *entry,
GtkEntryIconPosition icon_pos,
GtkIconSet *icon_set)
{
GtkEntryPrivate *priv;
EntryIconInfo *icon_info;
g_return_if_fail (GTK_IS_ENTRY (entry));
g_return_if_fail (IS_VALID_ICON_POSITION (icon_pos));
priv = entry->priv;
if ((icon_info = priv->icons[icon_pos]) == NULL)
icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
g_object_freeze_notify (G_OBJECT (entry));
/* need to ref before clearing */
if (icon_set)
gtk_icon_set_ref (icon_set);
gtk_entry_clear (entry, icon_pos);
if (icon_set)
{
_gtk_icon_helper_set_icon_set (icon_info->icon_helper, icon_set,
GTK_ICON_SIZE_MENU);
if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
{
g_object_notify (G_OBJECT (entry), "primary-icon-set");
g_object_notify (G_OBJECT (entry), "primary-icon-storage-type");
}
else
{
g_object_notify (G_OBJECT (entry), "secondary-icon-set");
g_object_notify (G_OBJECT (entry), "secondary-icon-storage-type");
}
if (gtk_widget_get_mapped (GTK_WIDGET (entry)))
gdk_window_show_unraised (icon_info->window);
gtk_icon_set_unref (icon_set);
}
if (gtk_widget_get_visible (GTK_WIDGET (entry)))
gtk_widget_queue_resize (GTK_WIDGET (entry));
g_object_thaw_notify (G_OBJECT (entry));
}
/**
* gtk_entry_set_icon_activatable:
* @entry: A #GtkEntry
@@ -8515,6 +8613,25 @@ gtk_entry_get_icon_name (GtkEntry *entry,
return _gtk_icon_helper_get_icon_name (icon_info->icon_helper);
}
const GtkIconSet *
gtk_entry_get_icon_set (GtkEntry *entry,
GtkEntryIconPosition icon_pos)
{
GtkEntryPrivate *priv;
EntryIconInfo *icon_info;
g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
g_return_val_if_fail (IS_VALID_ICON_POSITION (icon_pos), NULL);
priv = entry->priv;
icon_info = priv->icons[icon_pos];
if (!icon_info)
return NULL;
return _gtk_icon_helper_peek_icon_set (icon_info->icon_helper);
}
/**
* gtk_entry_set_icon_sensitive:
* @entry: A #GtkEntry

View File

@@ -278,6 +278,10 @@ GDK_AVAILABLE_IN_ALL
void gtk_entry_set_icon_from_gicon (GtkEntry *entry,
GtkEntryIconPosition icon_pos,
GIcon *icon);
GDK_AVAILABLE_IN_3_10
void gtk_entry_set_icon_from_icon_set (GtkEntry *entry,
GtkEntryIconPosition icon_pos,
GtkIconSet *icon);
GDK_AVAILABLE_IN_ALL
GtkImageType gtk_entry_get_icon_storage_type (GtkEntry *entry,
GtkEntryIconPosition icon_pos);
@@ -293,6 +297,10 @@ const gchar* gtk_entry_get_icon_name (GtkEntry *
GDK_AVAILABLE_IN_ALL
GIcon* gtk_entry_get_icon_gicon (GtkEntry *entry,
GtkEntryIconPosition icon_pos);
GDK_AVAILABLE_IN_3_10
const GtkIconSet*
gtk_entry_get_icon_set (GtkEntry *entry,
GtkEntryIconPosition icon_pos);
GDK_AVAILABLE_IN_ALL
void gtk_entry_set_icon_activatable (GtkEntry *entry,
GtkEntryIconPosition icon_pos,

View File

@@ -172,6 +172,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
@@ -180,6 +181,7 @@ struct _GtkIconSource
guint any_direction : 1;
guint any_state : 1;
guint any_size : 1;
guint any_scale : 1;
};
@@ -205,10 +207,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,
@@ -482,7 +484,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;
@@ -499,7 +501,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;
@@ -934,6 +936,7 @@ icon_sizes_init_for_settings (GtkSettings *settings)
static gboolean
icon_size_lookup_intern (GtkSettings *settings,
GtkIconSize size,
gdouble scale,
gint *widthp,
gint *heightp)
{
@@ -973,10 +976,16 @@ icon_size_lookup_intern (GtkSettings *settings,
}
if (widthp)
*widthp = width_for_settings >= 0 ? width_for_settings : icon_sizes[size].width;
{
*widthp = width_for_settings >= 0 ? width_for_settings : icon_sizes[size].width;
(*widthp) *= scale;
}
if (heightp)
*heightp = height_for_settings >= 0 ? height_for_settings : icon_sizes[size].height;
{
*heightp = height_for_settings >= 0 ? height_for_settings : icon_sizes[size].height;
(*heightp) *= scale;
}
return TRUE;
}
@@ -1012,7 +1021,7 @@ gtk_icon_size_lookup_for_settings (GtkSettings *settings,
{
g_return_val_if_fail (GTK_IS_SETTINGS (settings), FALSE);
return icon_size_lookup_intern (settings, size, width, height);
return icon_size_lookup_intern (settings, size, 1, width, height);
}
/**
@@ -1047,6 +1056,18 @@ gtk_icon_size_lookup (GtkIconSize size,
size, widthp, heightp);
}
gboolean
gtk_icon_size_lookup_scaled (GtkSettings *settings,
GtkIconSize size,
gdouble scale,
gint *width,
gint *height)
{
g_return_val_if_fail (GTK_IS_SETTINGS (settings), FALSE);
return icon_size_lookup_intern (settings, size, scale, width, height);
}
static GtkIconSize
icon_size_register_intern (const gchar *name,
gint width,
@@ -1133,7 +1154,7 @@ gtk_icon_size_register_alias (const gchar *alias,
init_icon_sizes ();
if (!icon_size_lookup_intern (NULL, target, NULL, NULL))
if (!icon_size_lookup_intern (NULL, target, 1, NULL, NULL))
g_warning ("gtk_icon_size_register_alias: Icon size %u does not exist", target);
ia = g_hash_table_lookup (icon_aliases, alias);
@@ -1208,12 +1229,14 @@ static GdkPixbuf *find_in_cache (GtkIconSet *icon_set,
GtkStyleContext *style_context,
GtkTextDirection direction,
GtkStateType state,
GtkIconSize size);
GtkIconSize size,
gdouble scale);
static void add_to_cache (GtkIconSet *icon_set,
GtkStyleContext *style_context,
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
@@ -1293,7 +1316,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);
@@ -1412,8 +1435,8 @@ sizes_equivalent (GtkIconSize lhs,
gint r_w, r_h, l_w, l_h;
icon_size_lookup_intern (NULL, rhs, &r_w, &r_h);
icon_size_lookup_intern (NULL, lhs, &l_w, &l_h);
icon_size_lookup_intern (NULL, rhs, 1, &r_w, &r_h);
icon_size_lookup_intern (NULL, lhs, 1, &l_w, &l_h);
return r_w == l_w && r_h == l_h;
#endif
@@ -1424,6 +1447,7 @@ find_best_matching_source (GtkIconSet *icon_set,
GtkTextDirection direction,
GtkStateType state,
GtkIconSize size,
gdouble scale,
GSList *failed)
{
GtkIconSource *source;
@@ -1445,7 +1469,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))
{
@@ -1492,7 +1517,8 @@ ensure_filename_pixbuf (GtkIconSet *icon_set,
static GdkPixbuf *
render_icon_name_pixbuf (GtkIconSource *icon_source,
GtkStyleContext *context,
GtkIconSize size)
GtkIconSize size,
gdouble scale)
{
GdkPixbuf *pixbuf;
GdkPixbuf *tmp_pixbuf;
@@ -1550,7 +1576,7 @@ render_icon_name_pixbuf (GtkIconSource *icon_source,
}
}
pixel_size = MIN (width, height);
pixel_size = MIN (width, height) * scale;
if (icon_source->direction != GTK_TEXT_DIR_NONE)
{
@@ -1562,9 +1588,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,
(const char **) names,
pixel_size, GTK_ICON_LOOKUP_USE_BUILTIN);
info = gtk_icon_theme_choose_icon_for_scale (icon_theme,
(const char **) names,
pixel_size, scale,
GTK_ICON_LOOKUP_USE_BUILTIN);
g_free (names[0]);
if (info)
{
@@ -1576,10 +1603,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)
@@ -1610,7 +1637,8 @@ find_and_render_icon_source (GtkIconSet *icon_set,
GtkStyleContext *context,
GtkTextDirection direction,
GtkStateType state,
GtkIconSize size)
GtkIconSize size,
gdouble scale)
{
GSList *failed = NULL;
GdkPixbuf *pixbuf = NULL;
@@ -1627,7 +1655,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;
@@ -1648,7 +1676,8 @@ find_and_render_icon_source (GtkIconSet *icon_set,
break;
case GTK_ICON_SOURCE_ICON_NAME:
case GTK_ICON_SOURCE_STATIC_ICON_NAME:
pixbuf = render_icon_name_pixbuf (source, context, size);
pixbuf = render_icon_name_pixbuf (source, context,
size, scale);
if (!pixbuf)
failed = g_slist_prepend (failed, source);
break;
@@ -1671,7 +1700,7 @@ render_fallback_image (GtkStyleContext *context,
GtkIconSize size)
{
/* 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)
{
@@ -1692,6 +1721,80 @@ render_fallback_image (GtkStyleContext *context,
return gtk_render_icon_pixbuf (context, &fallback_source, size);
}
static gdouble
_get_real_scale (GtkStyleContext *context,
GtkIconSize size,
GdkPixbuf *icon)
{
GtkSettings *settings;
GdkScreen *screen;
gint icon_width;
screen = gtk_style_context_get_screen (context);
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;
}
GdkPixbuf*
gtk_icon_set_render_icon_pixbuf_scaled (GtkIconSet *icon_set,
GtkStyleContext *context,
GtkIconSize size,
gdouble *scale)
{
GdkPixbuf *icon = NULL;
GtkStateFlags flags = 0;
GtkStateType state;
GtkTextDirection direction;
g_return_val_if_fail (icon_set != NULL, NULL);
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
g_return_val_if_fail (scale != NULL, NULL);
*scale = MAX (*scale, 1);
flags = gtk_style_context_get_state (context);
if (flags & GTK_STATE_FLAG_INSENSITIVE)
state = GTK_STATE_INSENSITIVE;
else if (flags & GTK_STATE_FLAG_PRELIGHT)
state = GTK_STATE_PRELIGHT;
else
state = GTK_STATE_NORMAL;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
direction = gtk_style_context_get_direction (context);
G_GNUC_END_IGNORE_DEPRECATIONS;
if (icon_set->sources)
{
icon = find_in_cache (icon_set, context, direction, state, size, *scale);
if (icon)
{
g_object_ref (icon);
if (scale)
*scale = _get_real_scale (context, size, icon);
return icon;
}
}
if (icon_set->sources)
icon = find_and_render_icon_source (icon_set, context, direction, state,
size, *scale);
if (icon == NULL)
icon = render_fallback_image (context, direction, state, size);
add_to_cache (icon_set, context, direction, state, size, *scale, icon);
if (scale)
*scale = _get_real_scale (context, size, icon);
return icon;
}
/**
* gtk_icon_set_render_icon_pixbuf:
* @icon_set: a #GtkIconSet
@@ -1715,45 +1818,12 @@ gtk_icon_set_render_icon_pixbuf (GtkIconSet *icon_set,
GtkStyleContext *context,
GtkIconSize size)
{
GdkPixbuf *icon = NULL;
GtkStateFlags flags = 0;
GtkStateType state;
GtkTextDirection direction;
gdouble scale = 1;
g_return_val_if_fail (icon_set != NULL, NULL);
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
flags = gtk_style_context_get_state (context);
if (flags & GTK_STATE_FLAG_INSENSITIVE)
state = GTK_STATE_INSENSITIVE;
else if (flags & GTK_STATE_FLAG_PRELIGHT)
state = GTK_STATE_PRELIGHT;
else
state = GTK_STATE_NORMAL;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
direction = gtk_style_context_get_direction (context);
G_GNUC_END_IGNORE_DEPRECATIONS;
if (icon_set->sources)
{
icon = find_in_cache (icon_set, context, direction, state, size);
if (icon)
{
g_object_ref (icon);
return icon;
}
}
if (icon_set->sources)
icon = find_and_render_icon_source (icon_set, context, direction, state, size);
if (icon == NULL)
icon = render_fallback_image (context, direction, state, size);
add_to_cache (icon_set, context, direction, state, size, icon);
return icon;
return gtk_icon_set_render_icon_pixbuf_scaled (icon_set, context, size, &scale);
}
/**
@@ -1844,7 +1914,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS;
/* 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
@@ -1865,6 +1935,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;
}
@@ -2377,6 +2451,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
@@ -2425,6 +2508,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
@@ -2491,6 +2582,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
@@ -2544,6 +2644,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;
@@ -2557,6 +2665,7 @@ struct _CachedIcon
GtkTextDirection direction;
GtkStateType state;
GtkIconSize size;
gdouble scale;
GdkPixbuf *pixbuf;
};
@@ -2585,7 +2694,8 @@ find_in_cache (GtkIconSet *icon_set,
GtkStyleContext *style_context,
GtkTextDirection direction,
GtkStateType state,
GtkIconSize size)
GtkIconSize size,
gdouble scale)
{
GSList *tmp_list;
GSList *prev;
@@ -2601,6 +2711,7 @@ find_in_cache (GtkIconSet *icon_set,
if (icon->style == style_context &&
icon->direction == direction &&
icon->state == state &&
icon->scale == scale &&
(size == (GtkIconSize)-1 || icon->size == size))
{
if (prev)
@@ -2627,6 +2738,7 @@ add_to_cache (GtkIconSet *icon_set,
GtkTextDirection direction,
GtkStateType state,
GtkIconSize size,
gdouble scale,
GdkPixbuf *pixbuf)
{
CachedIcon *icon;
@@ -2643,6 +2755,7 @@ add_to_cache (GtkIconSet *icon_set,
icon->direction = direction;
icon->state = state;
icon->size = size;
icon->scale = scale;
icon->pixbuf = pixbuf;
attach_to_style (icon_set, icon->style);
@@ -3086,3 +3199,31 @@ gtk_icon_factory_buildable_custom_tag_end (GtkBuildable *buildable,
gtk_icon_factory_add_default (icon_factory);
}
}
void
gtk_cairo_set_source_icon_set (cairo_t *cr,
GtkStyleContext *context,
GtkIconSet *icon_set,
GtkIconSize size,
gdouble scale,
gdouble icon_x,
gdouble icon_y)
{
cairo_pattern_t *pattern;
cairo_matrix_t matrix;
GdkPixbuf *pixbuf;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
g_return_if_fail (icon_set != NULL);
pixbuf = gtk_icon_set_render_icon_pixbuf_scaled (icon_set, context, size, &scale);
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
pattern = cairo_get_source (cr);
cairo_matrix_init_scale (&matrix, scale, scale);
cairo_matrix_translate (&matrix, -icon_x, -icon_y);
cairo_pattern_set_matrix (pattern, &matrix);
g_object_unref (pixbuf);
}

View File

@@ -193,12 +193,17 @@ void gtk_icon_source_set_state_wildcarded (GtkIconSource *
GDK_AVAILABLE_IN_ALL
void gtk_icon_source_set_size_wildcarded (GtkIconSource *source,
gboolean setting);
GDK_AVAILABLE_IN_3_10
void gtk_icon_source_set_scale_wildcarded (GtkIconSource *source,
gboolean setting);
GDK_AVAILABLE_IN_ALL
gboolean gtk_icon_source_get_size_wildcarded (const GtkIconSource *source);
GDK_AVAILABLE_IN_ALL
gboolean gtk_icon_source_get_state_wildcarded (const GtkIconSource *source);
GDK_AVAILABLE_IN_ALL
gboolean gtk_icon_source_get_direction_wildcarded (const GtkIconSource *source);
GDK_AVAILABLE_IN_3_10
gboolean gtk_icon_source_get_scale_wildcarded (const GtkIconSource *source);
GDK_AVAILABLE_IN_ALL
void gtk_icon_source_set_direction (GtkIconSource *source,
GtkTextDirection direction);
@@ -208,13 +213,27 @@ void gtk_icon_source_set_state (GtkIconSource *
GDK_AVAILABLE_IN_ALL
void gtk_icon_source_set_size (GtkIconSource *source,
GtkIconSize size);
GDK_AVAILABLE_IN_3_10
void gtk_icon_source_set_scale (GtkIconSource *source,
gdouble scale);
GDK_AVAILABLE_IN_ALL
GtkTextDirection gtk_icon_source_get_direction (const GtkIconSource *source);
GDK_AVAILABLE_IN_ALL
GtkStateType gtk_icon_source_get_state (const GtkIconSource *source);
GDK_AVAILABLE_IN_ALL
GtkIconSize gtk_icon_source_get_size (const GtkIconSource *source);
GDK_AVAILABLE_IN_3_10
gdouble gtk_icon_source_get_scale (const GtkIconSource *source);
/* Cairo helper */
GDK_AVAILABLE_IN_3_10
void gtk_cairo_set_source_icon_set (cairo_t *cr,
GtkStyleContext *context,
GtkIconSet *icon_set,
GtkIconSize size,
gdouble scale,
gdouble icon_x,
gdouble icon_y);
/* ignore this */
void _gtk_icon_set_invalidate_caches (void);

View File

@@ -266,18 +266,6 @@ ensure_pixbuf_for_icon_name_or_gicon (GtkIconHelper *self,
g_object_unref (info);
}
static void
ensure_pixbuf_for_icon_set (GtkIconHelper *self,
GtkStyleContext *context,
GtkIconSet *icon_set)
{
if (!check_invalidate_pixbuf (self, context))
return;
self->priv->rendered_pixbuf =
gtk_icon_set_render_icon_pixbuf (icon_set, context, self->priv->icon_size);
}
static void
ensure_pixbuf_at_size (GtkIconHelper *self,
GtkStyleContext *context)
@@ -307,12 +295,26 @@ ensure_pixbuf_at_size (GtkIconHelper *self,
self->priv->rendered_pixbuf = g_object_ref (self->priv->orig_pixbuf);
}
GtkIconSet *
_gtk_icon_helper_ensure_icon_set (GtkIconHelper *self,
GtkStyleContext *context)
{
switch (self->priv->storage_type)
{
case GTK_IMAGE_ICON_SET:
return self->priv->icon_set;
case GTK_IMAGE_STOCK:
return gtk_style_context_lookup_icon_set (context, self->priv->stock_id);
default:
return NULL;
}
}
GdkPixbuf *
_gtk_icon_helper_ensure_pixbuf (GtkIconHelper *self,
GtkStyleContext *context)
{
GdkPixbuf *pixbuf = NULL;
GtkIconSet *icon_set;
switch (self->priv->storage_type)
{
@@ -323,19 +325,6 @@ _gtk_icon_helper_ensure_pixbuf (GtkIconHelper *self,
pixbuf = g_object_ref (self->priv->orig_pixbuf);
break;
case GTK_IMAGE_STOCK:
icon_set = gtk_style_context_lookup_icon_set (context, self->priv->stock_id);
if (icon_set != NULL)
ensure_pixbuf_for_icon_set (self, context, icon_set);
else
pixbuf = NULL;
break;
case GTK_IMAGE_ICON_SET:
icon_set = self->priv->icon_set;
ensure_pixbuf_for_icon_set (self, context, icon_set);
break;
case GTK_IMAGE_ICON_NAME:
case GTK_IMAGE_GICON:
ensure_pixbuf_for_icon_name_or_gicon (self, context);
@@ -581,17 +570,33 @@ void
_gtk_icon_helper_draw (GtkIconHelper *self,
GtkStyleContext *context,
cairo_t *cr,
gdouble scale,
gdouble x,
gdouble y)
{
GtkIconSet *icon_set;
GdkPixbuf *pixbuf;
pixbuf = _gtk_icon_helper_ensure_pixbuf (self, context);
icon_set = _gtk_icon_helper_ensure_icon_set (self, context);
if (pixbuf != NULL)
if (icon_set)
{
gtk_render_icon (context, cr, pixbuf, x, y);
g_object_unref (pixbuf);
cairo_save (cr);
gtk_cairo_set_source_icon_set (cr, context,
icon_set, self->priv->icon_size,
scale, x, y);
cairo_paint (cr);
cairo_restore (cr);
}
else
{
pixbuf = _gtk_icon_helper_ensure_pixbuf (self, context);
if (pixbuf != NULL)
{
gtk_render_icon (context, cr, pixbuf, x, y);
g_object_unref (pixbuf);
}
}
}

View File

@@ -121,6 +121,7 @@ void _gtk_icon_helper_get_size (GtkIconHelper *self,
void _gtk_icon_helper_draw (GtkIconHelper *self,
GtkStyleContext *context,
cairo_t *cr,
gdouble scale,
gdouble x,
gdouble y);

View File

@@ -295,6 +295,7 @@ typedef struct
int min_size;
int max_size;
int threshold;
int scale;
char *dir;
char *subdir;
@@ -333,6 +334,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,
@@ -1354,11 +1356,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;
@@ -1585,6 +1587,7 @@ static GtkIconInfo *
choose_icon (GtkIconTheme *icon_theme,
const gchar *icon_names[],
gint size,
gdouble scale,
GtkIconLookupFlags flags)
{
GtkIconThemePrivate *priv;
@@ -1639,7 +1642,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;
}
@@ -1651,7 +1654,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;
}
@@ -1787,6 +1790,25 @@ gtk_icon_theme_lookup_icon (GtkIconTheme *icon_theme,
const gchar *icon_name,
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;
@@ -1794,6 +1816,7 @@ gtk_icon_theme_lookup_icon (GtkIconTheme *icon_theme,
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));
@@ -1819,7 +1842,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);
}
@@ -1830,7 +1853,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;
@@ -1870,9 +1893,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)
@@ -1916,6 +1956,24 @@ gtk_icon_theme_load_icon (GtkIconTheme *icon_theme,
gint size,
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;
@@ -1925,9 +1983,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,
@@ -2363,31 +2422,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:
@@ -2478,6 +2548,7 @@ static GtkIconInfo *
theme_lookup_icon (IconTheme *theme,
const char *icon_name,
int size,
gdouble scale,
gboolean allow_svg,
gboolean use_builtin)
{
@@ -2485,11 +2556,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;
@@ -2522,9 +2595,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)
{
@@ -2543,13 +2617,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;
}
}
@@ -2558,18 +2634,20 @@ theme_lookup_icon (IconTheme *theme,
{
if (!has_larger)
{
if (difference < min_difference || smaller)
if ((scale_diff <= min_scale_diff && difference < min_difference) || 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) && smaller)
{
min_difference = difference;
min_scale_diff = scale_diff;
min_dir = dir;
}
}
@@ -2868,6 +2946,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)
@@ -2915,6 +2994,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;
@@ -2943,6 +3027,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);

View File

@@ -179,17 +179,37 @@ 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,
gdouble 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,
gdouble 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,
gdouble scale,
GtkIconLookupFlags flags,
GError **error);
GDK_AVAILABLE_IN_ALL
GtkIconInfo * gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,

View File

@@ -1477,8 +1477,9 @@ gtk_image_draw (GtkWidget *widget,
}
else
{
_gtk_icon_helper_draw (priv->icon_helper,
_gtk_icon_helper_draw (priv->icon_helper,
context, cr,
gtk_widget_get_scale_factor (widget),
x, y);
}

View File

@@ -1020,6 +1020,7 @@ gtk_spin_button_panel_draw (GtkSpinButton *spin_button,
y = floor ((height - icon_height) / 2.0);
_gtk_icon_helper_draw (icon_helper, context, cr,
gtk_widget_get_scale_factor (widget),
x, y);
cairo_restore (cr);

View File

@@ -861,6 +861,12 @@ GDK_AVAILABLE_IN_ALL
GdkPixbuf * gtk_icon_set_render_icon_pixbuf (GtkIconSet *icon_set,
GtkStyleContext *context,
GtkIconSize size);
GDK_AVAILABLE_IN_3_10
GdkPixbuf *
gtk_icon_set_render_icon_pixbuf_scaled (GtkIconSet *icon_set,
GtkStyleContext *context,
GtkIconSize size,
gdouble *scale);
GDK_AVAILABLE_IN_ALL
void gtk_style_context_set_screen (GtkStyleContext *context,

View File

@@ -9681,6 +9681,29 @@ gtk_widget_render_icon_pixbuf (GtkWidget *widget,
return gtk_icon_set_render_icon_pixbuf (icon_set, context, size);
}
GdkPixbuf*
gtk_widget_render_icon_pixbuf_scaled (GtkWidget *widget,
const gchar *stock_id,
GtkIconSize size,
gdouble *scale)
{
GtkStyleContext *context;
GtkIconSet *icon_set;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
g_return_val_if_fail (stock_id != NULL, NULL);
g_return_val_if_fail (size > GTK_ICON_SIZE_INVALID || size == -1, NULL);
context = gtk_widget_get_style_context (widget);
icon_set = gtk_style_context_lookup_icon_set (context, stock_id);
if (icon_set == NULL)
return NULL;
return gtk_icon_set_render_icon_pixbuf_scaled (icon_set, context,
size, scale);
}
/**
* gtk_widget_set_parent_window:
* @widget: a #GtkWidget.
@@ -9925,6 +9948,26 @@ gtk_widget_has_screen (GtkWidget *widget)
return (gtk_widget_get_screen_unchecked (widget) != NULL);
}
gdouble
gtk_widget_get_scale_factor (GtkWidget *widget)
{
GtkWidget *toplevel;
g_return_val_if_fail (GTK_IS_WIDGET (widget), 1.0);
toplevel = gtk_widget_get_toplevel (widget);
if (toplevel && toplevel != widget)
return gtk_widget_get_scale_factor (toplevel);
if (gtk_widget_get_realized (widget))
return gdk_window_get_scale_factor (gtk_widget_get_window (widget));
/* else fall back to something that is more likely to be right than
* just returning 1.0:
*/
return gdk_screen_get_monitor_scale_factor (gtk_widget_get_screen (widget), 0);
}
/**
* gtk_widget_get_display:
* @widget: a #GtkWidget

View File

@@ -848,6 +848,7 @@ GDK_AVAILABLE_IN_ALL
GdkScreen * gtk_widget_get_screen (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
gboolean gtk_widget_has_screen (GtkWidget *widget);
gdouble gtk_widget_get_scale_factor (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
GdkDisplay * gtk_widget_get_display (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
@@ -1005,6 +1006,10 @@ GDK_AVAILABLE_IN_ALL
GdkPixbuf *gtk_widget_render_icon_pixbuf (GtkWidget *widget,
const gchar *stock_id,
GtkIconSize size);
GdkPixbuf *gtk_widget_render_icon_scaled (GtkWidget *widget,
const gchar *stock_id,
GtkIconSize size,
gdouble *scale);
/* handle composite names for GTK_COMPOSITE_CHILD widgets,
* the returned name is newly allocated.