Bug 730862 - Preview frozen while dragging selection tools...

...(crop, rectangle, etc) in large image zoomed-to-fit

Introduce a hash of the last 16 used icons in GimpStatusbar, it was
loading icons at a very high frequency. Found by Massimo.
This commit is contained in:
Michael Natterer
2014-05-30 19:38:17 +02:00
parent 6714a414a7
commit bb8d65bcee
2 changed files with 87 additions and 6 deletions

View File

@ -73,6 +73,11 @@ static void gimp_statusbar_progress_iface_init (GimpProgressInterface *iface
static void gimp_statusbar_dispose (GObject *object);
static void gimp_statusbar_finalize (GObject *object);
static void gimp_statusbar_screen_changed (GtkWidget *widget,
GdkScreen *previous);
static void gimp_statusbar_style_set (GtkWidget *widget,
GtkStyle *prev_style);
static void gimp_statusbar_hbox_size_request (GtkWidget *widget,
GtkRequisition *requisition,
GimpStatusbar *statusbar);
@ -122,6 +127,9 @@ static void gimp_statusbar_msg_free (GimpStatusbarMsg *msg);
static gchar * gimp_statusbar_vprintf (const gchar *format,
va_list args) G_GNUC_PRINTF (1, 0);
static GdkPixbuf * gimp_statusbar_load_icon (GimpStatusbar *statusbar,
const gchar *icon_name);
G_DEFINE_TYPE_WITH_CODE (GimpStatusbar, gimp_statusbar, GTK_TYPE_STATUSBAR,
G_IMPLEMENT_INTERFACE (GIMP_TYPE_PROGRESS,
@ -133,10 +141,14 @@ G_DEFINE_TYPE_WITH_CODE (GimpStatusbar, gimp_statusbar, GTK_TYPE_STATUSBAR,
static void
gimp_statusbar_class_init (GimpStatusbarClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = gimp_statusbar_dispose;
object_class->finalize = gimp_statusbar_finalize;
object_class->dispose = gimp_statusbar_dispose;
object_class->finalize = gimp_statusbar_finalize;
widget_class->screen_changed = gimp_statusbar_screen_changed;
widget_class->style_set = gimp_statusbar_style_set;
}
static void
@ -296,6 +308,12 @@ gimp_statusbar_finalize (GObject *object)
statusbar->icon = NULL;
}
if (statusbar->icon_hash)
{
g_hash_table_unref (statusbar->icon_hash);
statusbar->icon_hash = NULL;
}
g_slist_free_full (statusbar->messages,
(GDestroyNotify) gimp_statusbar_msg_free);
statusbar->messages = NULL;
@ -309,6 +327,37 @@ gimp_statusbar_finalize (GObject *object)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gimp_statusbar_screen_changed (GtkWidget *widget,
GdkScreen *previous)
{
GimpStatusbar *statusbar = GIMP_STATUSBAR (widget);
if (GTK_WIDGET_CLASS (parent_class)->screen_changed)
GTK_WIDGET_CLASS (parent_class)->screen_changed (widget, previous);
if (statusbar->icon_hash)
{
g_hash_table_unref (statusbar->icon_hash);
statusbar->icon_hash = NULL;
}
}
static void
gimp_statusbar_style_set (GtkWidget *widget,
GtkStyle *prev_style)
{
GimpStatusbar *statusbar = GIMP_STATUSBAR (widget);
GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
if (statusbar->icon_hash)
{
g_hash_table_unref (statusbar->icon_hash);
statusbar->icon_hash = NULL;
}
}
static void
gimp_statusbar_hbox_size_request (GtkWidget *widget,
GtkRequisition *requisition,
@ -551,7 +600,7 @@ gimp_statusbar_progress_message (GimpProgress *progress,
{
GdkPixbuf *pixbuf;
pixbuf = gimp_widget_load_icon (statusbar->label, icon_name, 16);
pixbuf = gimp_statusbar_load_icon (statusbar, icon_name);
width += ICON_SPACING + gdk_pixbuf_get_width (pixbuf);
@ -601,8 +650,7 @@ gimp_statusbar_set_text (GimpStatusbar *statusbar,
}
if (icon_name)
statusbar->icon = gimp_widget_load_icon (statusbar->label,
icon_name, 16);
statusbar->icon = gimp_statusbar_load_icon (statusbar, icon_name);
if (statusbar->icon)
{
@ -1547,3 +1595,35 @@ gimp_statusbar_vprintf (const gchar *format,
return message;
}
static GdkPixbuf *
gimp_statusbar_load_icon (GimpStatusbar *statusbar,
const gchar *icon_name)
{
GdkPixbuf *icon;
if (G_UNLIKELY (! statusbar->icon_hash))
{
statusbar->icon_hash =
g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_object_unref);
}
icon = g_hash_table_lookup (statusbar->icon_hash, icon_name);
if (icon)
return g_object_ref (icon);
icon = gimp_widget_load_icon (statusbar->label, icon_name, 16);
/* this is not optimal but so what */
if (g_hash_table_size (statusbar->icon_hash) > 16)
g_hash_table_remove_all (statusbar->icon_hash);
g_hash_table_insert (statusbar->icon_hash,
g_strdup (icon_name), g_object_ref (icon));
return icon;
}