[gtksourceview] gutterrenderertext: cache common widths



commit d6c7228a0f31549f341e9bf59b8538288dbf3915
Author: Christian Hergert <chergert redhat com>
Date:   Tue Jun 22 11:58:41 2021 -0700

    gutterrenderertext: cache common widths
    
    Generally, this widget is used as the base for line drawing. Additionally,
    it is generally used in a monospace fashion.
    
    Until we have a reason to consider alternatives, we should aggressively
    cache the widths and re-use them to avoid calculating layout sizes on
    every line number.
    
    This caches them by common sizes (1..5) so that we only do that once per
    snapshot per width.

 gtksourceview/gtksourcegutterrenderertext.c | 68 ++++++++++++++++++++++++-----
 1 file changed, 56 insertions(+), 12 deletions(-)
---
diff --git a/gtksourceview/gtksourcegutterrenderertext.c b/gtksourceview/gtksourcegutterrenderertext.c
index 14c8d8f9..eff0e402 100644
--- a/gtksourceview/gtksourcegutterrenderertext.c
+++ b/gtksourceview/gtksourcegutterrenderertext.c
@@ -31,12 +31,19 @@
  * #GtkSourceGutter.
  */
 
+typedef struct
+{
+       int width;
+       int height;
+} Size;
+
 typedef struct
 {
        gchar       *text;
        PangoLayout *cached_layout;
        GdkRGBA      cached_color;
        gsize        text_len;
+       Size         cached_sizes[5];
        guint        is_markup : 1;
 } GtkSourceGutterRendererTextPrivate;
 
@@ -50,6 +57,45 @@ enum
        N_PROPS
 };
 
+static void
+gtk_source_gutter_renderer_text_clear_cached_sizes (GtkSourceGutterRendererText *text)
+{
+       GtkSourceGutterRendererTextPrivate *priv = gtk_source_gutter_renderer_text_get_instance_private 
(text);
+
+       for (guint i = 0; i < G_N_ELEMENTS (priv->cached_sizes); i++)
+       {
+               priv->cached_sizes[i].width = -1;
+               priv->cached_sizes[i].height = -1;
+       }
+}
+
+static inline void
+gtk_source_gutter_renderer_text_get_size (GtkSourceGutterRendererTextPrivate *priv,
+                                          PangoLayout                        *layout,
+                                          int                                 text_len,
+                                          int                                *width,
+                                          int                                *height)
+{
+       g_assert (text_len > 0);
+
+       if G_UNLIKELY (text_len > G_N_ELEMENTS (priv->cached_sizes) ||
+                      priv->cached_sizes[text_len-1].width == -1)
+       {
+               pango_layout_get_pixel_size (layout, width, height);
+
+               if (text_len <= G_N_ELEMENTS (priv->cached_sizes))
+               {
+                       priv->cached_sizes[text_len-1].width = *width;
+                       priv->cached_sizes[text_len-1].height = *height;
+               }
+       }
+       else
+       {
+               *width = priv->cached_sizes[text_len-1].width;
+               *height = priv->cached_sizes[text_len-1].height;
+       }
+}
+
 static void
 gtk_source_gutter_renderer_text_begin (GtkSourceGutterRenderer *renderer,
                                        GtkSourceGutterLines    *lines)
@@ -62,6 +108,8 @@ gtk_source_gutter_renderer_text_begin (GtkSourceGutterRenderer *renderer,
 
        g_clear_object (&priv->cached_layout);
        priv->cached_layout = gtk_widget_create_pango_layout (GTK_WIDGET (renderer), NULL);
+
+       gtk_source_gutter_renderer_text_clear_cached_sizes (text);
 }
 
 static void
@@ -73,10 +121,10 @@ gtk_source_gutter_renderer_text_snapshot_line (GtkSourceGutterRenderer *renderer
        GtkSourceGutterRendererText *text = GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer);
        GtkSourceGutterRendererTextPrivate *priv = gtk_source_gutter_renderer_text_get_instance_private 
(text);
        PangoLayout *layout;
-       gfloat x;
-       gfloat y;
-       gint width;
-       gint height;
+       float x;
+       float y;
+       int width;
+       int height;
 
        if (priv->text == NULL || priv->text_len == 0)
        {
@@ -98,14 +146,8 @@ gtk_source_gutter_renderer_text_snapshot_line (GtkSourceGutterRenderer *renderer
                                       priv->text_len);
        }
 
-       pango_layout_get_pixel_size (layout, &width, &height);
-
-       gtk_source_gutter_renderer_align_cell (renderer,
-                                              line,
-                                              width,
-                                              height,
-                                              &x,
-                                              &y);
+       gtk_source_gutter_renderer_text_get_size (priv, layout, priv->text_len, &width, &height);
+       gtk_source_gutter_renderer_align_cell (renderer, line, width, height, &x, &y);
 
        gtk_snapshot_render_layout (snapshot,
                                    gtk_widget_get_style_context (GTK_WIDGET (text)),
@@ -388,6 +430,8 @@ gtk_source_gutter_renderer_text_init (GtkSourceGutterRendererText *self)
        GtkSourceGutterRendererTextPrivate *priv = gtk_source_gutter_renderer_text_get_instance_private 
(self);
 
        priv->is_markup = TRUE;
+
+       gtk_source_gutter_renderer_text_clear_cached_sizes (self);
 }
 
 /**


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