summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Hergert <chergert@redhat.com>2016-04-25 00:22:54 -0700
committerMatthias Clasen <mclasen@redhat.com>2016-05-05 15:03:58 -0400
commitd505df90b09cd67c2cc3cc4b019e754bb1683723 (patch)
treec7e622e0edb7298510919e82a94f163d646fa859
parentdb326889f91f96a7155bdfa4af353a5b915ebfa0 (diff)
downloadgtk+-d505df90b09cd67c2cc3cc4b019e754bb1683723.tar.gz
builtinicon: avoid calculating font-metrics in vast majority of cases
We perform lots of gadget allocations that require allocating a GtkBuiltinIcon. One notable example is the scrollbar for a scrolled window. In the process of doing this, we often calculate baseline information that isn't necessary. With how much this code path gets exercised, its worth catching the result for the common case, which is that the font-description has not changed and we are using the default language the application was started with. This simply caches the previous result and verifies that we can reuse it with pango_font_description_hash() and a simple language check. Numbers below are scrolling through a textview with GDK_KEY_Down. Before: SELF CUMULATIVE FUNCTION [ 0.08%] [ 9.26%] gtk_builtin_icon_get_preferred_size [ 0.01%] [ 8.82%] pango_context_get_metrics [ 0.02%] [ 0.16%] gtk_widget_get_pango_context [ 0.06%] [ 0.06%] pango_context_get_language [ 0.01%] [ 0.02%] g_type_check_instance_cast [ 0.02%] [ 0.02%] strlen [ 0.02%] [ 0.02%] pango_context_get_font_description [ 0.02%] [ 0.02%] g_list_foreach [ 0.01%] [ 0.01%] gtk_css_style_get_value [ 0.01%] [ 0.01%] itemize_with_font [ 0.01%] [ 0.01%] pango_context_get_type [ 0.01%] [ 0.01%] get_base_metrics [ 0.00%] [ 0.01%] pango_font_metrics_unref [ 0.01%] [ 0.01%] g_list_free [ 0.01%] [ 0.01%] gtk_builtin_icon_get_type After: SELF CUMULATIVE FUNCTION [ 0.08%] [ 0.18%] gtk_builtin_icon_get_preferred_size [ 0.02%] [ 0.02%] pango_font_description_hash [ 0.00%] [ 0.02%] gtk_widget_get_pango_context [ 0.00%] [ 0.02%] g_object_get_qdata [ 0.00%] [ 0.02%] g_datalist_id_get_data [ 0.02%] [ 0.02%] gtk_builtin_icon_get_type [ 0.01%] [ 0.01%] pango_context_get_font_description [ 0.00%] [ 0.01%] - - kernel - - [ 0.01%] [ 0.01%] pango_context_get_language [ 0.00%] [ 0.01%] gtk_css_style_get_value [ 0.00%] [ 0.01%] gtk_css_gadget_get_style https://bugzilla.gnome.org/show_bug.cgi?id=765486
-rw-r--r--gtk/gtkbuiltinicon.c55
1 files changed, 39 insertions, 16 deletions
diff --git a/gtk/gtkbuiltinicon.c b/gtk/gtkbuiltinicon.c
index 8b99573446..feedb2cbf8 100644
--- a/gtk/gtkbuiltinicon.c
+++ b/gtk/gtkbuiltinicon.c
@@ -47,6 +47,8 @@ typedef struct _GtkBuiltinIconPrivate GtkBuiltinIconPrivate;
struct _GtkBuiltinIconPrivate {
GtkCssImageBuiltinType image_type;
int default_size;
+ int strikethrough;
+ gboolean strikethrough_valid;
char * default_size_property;
};
@@ -63,10 +65,6 @@ gtk_builtin_icon_get_preferred_size (GtkCssGadget *gadget,
gint *natural_baseline)
{
GtkBuiltinIconPrivate *priv = gtk_builtin_icon_get_instance_private (GTK_BUILTIN_ICON (gadget));
- GtkWidget *widget;
- PangoContext *pango_context;
- PangoFontMetrics *metrics;
- int strikethrough;
double min_size;
guint property;
@@ -98,21 +96,33 @@ gtk_builtin_icon_get_preferred_size (GtkCssGadget *gadget,
*minimum = *natural = priv->default_size;
}
- widget = gtk_css_gadget_get_owner (gadget);
-
- pango_context = gtk_widget_get_pango_context (widget);
- metrics = pango_context_get_metrics (pango_context,
- pango_context_get_font_description (pango_context),
- pango_context_get_language (pango_context));
-
- strikethrough = pango_font_metrics_get_strikethrough_position (metrics);
-
if (minimum_baseline)
- *minimum_baseline = *minimum * 0.5 + PANGO_PIXELS (strikethrough);
+ {
+ if (!priv->strikethrough_valid)
+ {
+ GtkWidget *widget;
+ PangoContext *pango_context;
+ const PangoFontDescription *font_desc;
+ PangoFontMetrics *metrics;
+
+ widget = gtk_css_gadget_get_owner (gadget);
+ pango_context = gtk_widget_get_pango_context (widget);
+ font_desc = pango_context_get_font_description (pango_context);
+
+ metrics = pango_context_get_metrics (pango_context,
+ font_desc,
+ pango_context_get_language (pango_context));
+ priv->strikethrough = pango_font_metrics_get_strikethrough_position (metrics);
+ priv->strikethrough_valid = TRUE;
+
+ pango_font_metrics_unref (metrics);
+ }
+
+ *minimum_baseline = *minimum * 0.5 + PANGO_PIXELS (priv->strikethrough);
+ }
+
if (natural_baseline)
*natural_baseline = *minimum_baseline;
-
- pango_font_metrics_unref (metrics);
}
static void
@@ -152,6 +162,18 @@ gtk_builtin_icon_draw (GtkCssGadget *gadget,
}
static void
+gtk_builtin_icon_style_changed (GtkCssGadget *gadget,
+ GtkCssStyleChange *change)
+{
+ GtkBuiltinIconPrivate *priv = gtk_builtin_icon_get_instance_private (GTK_BUILTIN_ICON (gadget));
+
+ if (gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_FONT))
+ priv->strikethrough_valid = FALSE;
+
+ GTK_CSS_GADGET_CLASS (gtk_builtin_icon_parent_class)->style_changed (gadget, change);
+}
+
+static void
gtk_builtin_icon_finalize (GObject *object)
{
GtkBuiltinIconPrivate *priv = gtk_builtin_icon_get_instance_private (GTK_BUILTIN_ICON (object));
@@ -172,6 +194,7 @@ gtk_builtin_icon_class_init (GtkBuiltinIconClass *klass)
gadget_class->get_preferred_size = gtk_builtin_icon_get_preferred_size;
gadget_class->allocate = gtk_builtin_icon_allocate;
gadget_class->draw = gtk_builtin_icon_draw;
+ gadget_class->style_changed = gtk_builtin_icon_style_changed;
}
static void