Commit a2386321 authored by Carlos Garnacho's avatar Carlos Garnacho

GtkStyleContext: Add gtk_render_icon_pixbuf()

This function is similar to gtk_style_render_icon(), which is now
implemented on top of this one.
parent 06c88571
......@@ -327,6 +327,9 @@ static void hls_to_rgb (gdouble *h,
static void style_unrealize_cursors (GtkStyle *style);
static void transform_detail_string (const gchar *detail,
GtkStyleContext *context);
/*
* Data for default check and radio buttons
*/
......@@ -1607,54 +1610,6 @@ out:
cairo_restore (cr);
}
static GdkPixbuf *
scale_or_ref (GdkPixbuf *src,
gint width,
gint height)
{
if (width == gdk_pixbuf_get_width (src) &&
height == gdk_pixbuf_get_height (src))
{
return g_object_ref (src);
}
else
{
return gdk_pixbuf_scale_simple (src,
width, height,
GDK_INTERP_BILINEAR);
}
}
static gboolean
lookup_icon_size (GtkStyle *style,
GtkWidget *widget,
GtkIconSize size,
gint *width,
gint *height)
{
GdkScreen *screen;
GtkSettings *settings;
if (widget && gtk_widget_has_screen (widget))
{
screen = gtk_widget_get_screen (widget);
settings = gtk_settings_get_for_screen (screen);
}
else if (style && style->visual)
{
screen = gdk_visual_get_screen (style->visual);
settings = gtk_settings_get_for_screen (screen);
}
else
{
settings = gtk_settings_get_default ();
GTK_NOTE (MULTIHEAD,
g_warning ("Using the default screen for gtk_default_render_icon()"));
}
return gtk_icon_size_lookup_for_settings (settings, size, width, height);
}
static GdkPixbuf *
gtk_default_render_icon (GtkStyle *style,
const GtkIconSource *source,
......@@ -1664,65 +1619,31 @@ gtk_default_render_icon (GtkStyle *style,
GtkWidget *widget,
const gchar *detail)
{
gint width = 1;
gint height = 1;
GdkPixbuf *scaled;
GdkPixbuf *stated;
GdkPixbuf *base_pixbuf;
/* Oddly, style can be NULL in this function, because
* GtkIconSet can be used without a style and if so
* it uses this function.
*/
base_pixbuf = gtk_icon_source_get_pixbuf (source);
g_return_val_if_fail (base_pixbuf != NULL, NULL);
GtkStyleContext *context;
GtkStylePrivate *priv;
GdkPixbuf *pixbuf;
if (size != (GtkIconSize) -1 && !lookup_icon_size(style, widget, size, &width, &height))
if (widget)
context = gtk_widget_get_style_context (widget);
else
{
g_warning (G_STRLOC ": invalid icon size '%d'", size);
return NULL;
priv = GTK_STYLE_GET_PRIVATE (style);
context = priv->context;
}
/* If the size was wildcarded, and we're allowed to scale, then scale; otherwise,
* leave it alone.
*/
if (size != (GtkIconSize)-1 && gtk_icon_source_get_size_wildcarded (source))
scaled = scale_or_ref (base_pixbuf, width, height);
else
scaled = g_object_ref (base_pixbuf);
if (!context)
return NULL;
/* If the state was wildcarded, then generate a state. */
if (gtk_icon_source_get_state_wildcarded (source))
{
if (state == GTK_STATE_INSENSITIVE)
{
stated = gdk_pixbuf_copy (scaled);
gdk_pixbuf_saturate_and_pixelate (scaled, stated,
0.8, TRUE);
g_object_unref (scaled);
}
else if (state == GTK_STATE_PRELIGHT)
{
stated = gdk_pixbuf_copy (scaled);
gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1.2, FALSE);
g_object_unref (scaled);
}
else
{
stated = scaled;
}
}
else
stated = scaled;
return stated;
gtk_style_context_save (context);
if (detail)
transform_detail_string (detail, context);
pixbuf = gtk_render_icon_pixbuf (context, source, size);
gtk_style_context_restore (context);
return pixbuf;
}
static void
......
......@@ -3270,3 +3270,36 @@ gtk_render_activity (GtkStyleContext *context,
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_activity (priv->theming_engine, cr, x, y, width, height);
}
/**
* gtk_render_icon_pixbuf:
* @context: a #GtkStyleContext
* @source: the #GtkIconSource specifying the icon to render
* @size: (type int): the size to render the icon at. A size of (GtkIconSize) -1
* means render at the size of the source and don't scale.
*
* Renders the icon specified by @source at the given @size, returning the result
* in a pixbuf.
*
* Returns: (transfer full): a newly-created #GdkPixbuf containing the rendered icon
*
* Since: 3.0
**/
GdkPixbuf *
gtk_render_icon_pixbuf (GtkStyleContext *context,
const GtkIconSource *source,
GtkIconSize size)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
g_return_val_if_fail (size >= -1, NULL);
g_return_val_if_fail (source != NULL, NULL);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
_gtk_theming_engine_set_context (priv->theming_engine, context);
return engine_class->render_icon_pixbuf (priv->theming_engine, source, size);
}
......@@ -404,6 +404,10 @@ void gtk_render_activity (GtkStyleContext *context,
gdouble width,
gdouble height);
GdkPixbuf * gtk_render_icon_pixbuf (GtkStyleContext *context,
const GtkIconSource *source,
GtkIconSize size);
G_END_DECLS
#endif /* __GTK_STYLE_CONTEXT_H__ */
......@@ -168,6 +168,9 @@ static void gtk_theming_engine_render_activity (GtkThemingEngine *engine,
gdouble y,
gdouble width,
gdouble height);
static GdkPixbuf * gtk_theming_engine_render_icon_pixbuf (GtkThemingEngine *engine,
const GtkIconSource *source,
GtkIconSize size);
G_DEFINE_TYPE (GtkThemingEngine, gtk_theming_engine, G_TYPE_OBJECT)
......@@ -220,6 +223,7 @@ gtk_theming_engine_class_init (GtkThemingEngineClass *klass)
klass->render_extension = gtk_theming_engine_render_extension;
klass->render_handle = gtk_theming_engine_render_handle;
klass->render_activity = gtk_theming_engine_render_activity;
klass->render_icon_pixbuf = gtk_theming_engine_render_icon_pixbuf;
/**
* GtkThemingEngine:name:
......@@ -2807,3 +2811,91 @@ gtk_theming_engine_render_activity (GtkThemingEngine *engine,
gtk_theming_engine_render_frame (engine, cr, x, y, width, height);
}
}
static GdkPixbuf *
scale_or_ref (GdkPixbuf *src,
gint width,
gint height)
{
if (width == gdk_pixbuf_get_width (src) &&
height == gdk_pixbuf_get_height (src))
return g_object_ref (src);
else
return gdk_pixbuf_scale_simple (src,
width, height,
GDK_INTERP_BILINEAR);
}
static gboolean
lookup_icon_size (GtkThemingEngine *engine,
GtkIconSize size,
gint *width,
gint *height)
{
GdkScreen *screen;
GtkSettings *settings;
screen = gtk_theming_engine_get_screen (engine);
settings = gtk_settings_get_for_screen (screen);
return gtk_icon_size_lookup_for_settings (settings, size, width, height);
}
static GdkPixbuf *
gtk_theming_engine_render_icon_pixbuf (GtkThemingEngine *engine,
const GtkIconSource *source,
GtkIconSize size)
{
GdkPixbuf *scaled;
GdkPixbuf *stated;
GdkPixbuf *base_pixbuf;
GtkStateFlags state;
gint width = 1;
gint height = 1;
base_pixbuf = gtk_icon_source_get_pixbuf (source);
state = gtk_theming_engine_get_state (engine);
g_return_val_if_fail (base_pixbuf != NULL, NULL);
if (size != (GtkIconSize) -1 &&
!lookup_icon_size (engine, size, &width, &height))
{
g_warning (G_STRLOC ": invalid icon size '%d'", size);
return NULL;
}
/* If the size was wildcarded, and we're allowed to scale, then scale; otherwise,
* leave it alone.
*/
if (size != (GtkIconSize) -1 &&
gtk_icon_source_get_size_wildcarded (source))
scaled = scale_or_ref (base_pixbuf, width, height);
else
scaled = g_object_ref (base_pixbuf);
/* If the state was wildcarded, then generate a state. */
if (gtk_icon_source_get_state_wildcarded (source))
{
if (state & GTK_STATE_FLAG_INSENSITIVE)
{
stated = gdk_pixbuf_copy (scaled);
gdk_pixbuf_saturate_and_pixelate (scaled, stated,
0.8, TRUE);
g_object_unref (scaled);
}
else if (state & GTK_STATE_FLAG_PRELIGHT)
{
stated = gdk_pixbuf_copy (scaled);
gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1.2, FALSE);
g_object_unref (scaled);
}
else
stated = scaled;
}
else
stated = scaled;
return stated;
}
......@@ -157,6 +157,10 @@ struct _GtkThemingEngineClass
gdouble y,
gdouble width,
gdouble height);
GdkPixbuf * (* render_icon_pixbuf) (GtkThemingEngine *engine,
const GtkIconSource *source,
GtkIconSize size);
};
GType gtk_theming_engine_get_type (void) G_GNUC_CONST;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment