[gtk+/gtk-3-20] builtinicon: avoid calculating font-metrics in vast majority of cases



commit d505df90b09cd67c2cc3cc4b019e754bb1683723
Author: Christian Hergert <chergert redhat com>
Date:   Mon Apr 25 00:22:54 2016 -0700

    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

 gtk/gtkbuiltinicon.c |   55 +++++++++++++++++++++++++++++++++++--------------
 1 files changed, 39 insertions(+), 16 deletions(-)
---
diff --git a/gtk/gtkbuiltinicon.c b/gtk/gtkbuiltinicon.c
index 8b99573..feedb2c 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]