[gtksourceview/wip/chergert/snippets: 87/119] spacedrawer: port to GTK 4
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/chergert/snippets: 87/119] spacedrawer: port to GTK 4
- Date: Wed, 29 Jan 2020 17:34:07 +0000 (UTC)
commit 5cfb487be002963718634dd97568937e3473e3e4
Author: Christian Hergert <chergert redhat com>
Date: Wed Jan 15 14:28:00 2020 -0800
spacedrawer: port to GTK 4
- Use snapshot instead of cairo draw
- Cache textures for better chance of reuse
- Don't allocate a GdkRGBA, just track if it's set
gtksourceview/gtksourcespacedrawer-private.h | 2 +-
gtksourceview/gtksourcespacedrawer.c | 270 ++++++++++++++++-----------
2 files changed, 164 insertions(+), 108 deletions(-)
---
diff --git a/gtksourceview/gtksourcespacedrawer-private.h b/gtksourceview/gtksourcespacedrawer-private.h
index e7d3a5b4..62152e23 100644
--- a/gtksourceview/gtksourcespacedrawer-private.h
+++ b/gtksourceview/gtksourcespacedrawer-private.h
@@ -33,6 +33,6 @@ void _gtk_source_space_drawer_update_color (GtkSourceSpaceDrawer *drawer,
GTK_SOURCE_INTERNAL
void _gtk_source_space_drawer_draw (GtkSourceSpaceDrawer *drawer,
GtkSourceView *view,
- cairo_t *cr);
+ GtkSnapshot *snapshot);
G_END_DECLS
diff --git a/gtksourceview/gtksourcespacedrawer.c b/gtksourceview/gtksourcespacedrawer.c
index 51ed4219..15db7559 100644
--- a/gtksourceview/gtksourcespacedrawer.c
+++ b/gtksourceview/gtksourcespacedrawer.c
@@ -30,6 +30,7 @@
#include "gtksourcebuffer.h"
#include "gtksourcebuffer-private.h"
#include "gtksourceiter-private.h"
+#include "gtksourcestylescheme.h"
#include "gtksourcestylescheme-private.h"
#include "gtksourcetag.h"
#include "gtksourceview.h"
@@ -88,17 +89,41 @@
* default with a DVD of Matrix, in case the astronauts are bored.
*/
-/*
-#define ENABLE_PROFILE
-*/
-#undef ENABLE_PROFILE
+#if 0
+# define ENABLE_PROFILE
+#else
+# undef ENABLE_PROFILE
+#endif
+
+typedef enum
+{
+ DRAW_TAB,
+ DRAW_NARROW_NBSP,
+ DRAW_NBSP,
+ DRAW_SPACE,
+ DRAW_NEWLINE,
+ N_DRAW
+} Draw;
+
+typedef struct
+{
+ GskRenderNode *node;
+ gint width;
+ gint height;
+} CachedNode;
struct _GtkSourceSpaceDrawer
{
- GObject parent_instance;
+ GObject parent_instance;
+
GtkSourceSpaceTypeFlags *matrix;
- GdkRGBA *color;
- guint enable_matrix : 1;
+
+ CachedNode cached[N_DRAW];
+
+ GdkRGBA color;
+
+ guint color_set : 1;
+ guint enable_matrix : 1;
};
enum
@@ -113,6 +138,19 @@ static GParamSpec *properties[N_PROPERTIES];
G_DEFINE_TYPE (GtkSourceSpaceDrawer, gtk_source_space_drawer, G_TYPE_OBJECT)
+static void
+gtk_source_space_drawer_purge_cache (GtkSourceSpaceDrawer *drawer)
+{
+ guint i;
+
+ g_return_if_fail (GTK_SOURCE_IS_SPACE_DRAWER (drawer));
+
+ for (i = 0; i < G_N_ELEMENTS (drawer->cached); i++)
+ {
+ g_clear_pointer (&drawer->cached[i].node, gsk_render_node_unref);
+ }
+}
+
static gint
get_number_of_locations (void)
{
@@ -305,13 +343,9 @@ gtk_source_space_drawer_finalize (GObject *object)
{
GtkSourceSpaceDrawer *drawer = GTK_SOURCE_SPACE_DRAWER (object);
+ gtk_source_space_drawer_purge_cache (drawer);
g_free (drawer->matrix);
- if (drawer->color != NULL)
- {
- gdk_rgba_free (drawer->color);
- }
-
G_OBJECT_CLASS (gtk_source_space_drawer_parent_class)->finalize (object);
}
@@ -706,11 +740,9 @@ _gtk_source_space_drawer_update_color (GtkSourceSpaceDrawer *drawer,
g_return_if_fail (GTK_SOURCE_IS_SPACE_DRAWER (drawer));
g_return_if_fail (GTK_SOURCE_IS_VIEW (view));
- if (drawer->color != NULL)
- {
- gdk_rgba_free (drawer->color);
- drawer->color = NULL;
- }
+ gtk_source_space_drawer_purge_cache (drawer);
+
+ drawer->color_set = FALSE;
buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
style_scheme = gtk_source_buffer_get_style_scheme (buffer);
@@ -736,14 +768,15 @@ _gtk_source_space_drawer_update_color (GtkSourceSpaceDrawer *drawer,
color_str != NULL &&
gdk_rgba_parse (&color, color_str))
{
- drawer->color = gdk_rgba_copy (&color);
+ drawer->color = color;
+ drawer->color_set = TRUE;
}
g_free (color_str);
}
}
- if (drawer->color == NULL)
+ if (!drawer->color_set)
{
GtkStyleContext *context;
GdkRGBA color;
@@ -751,12 +784,11 @@ _gtk_source_space_drawer_update_color (GtkSourceSpaceDrawer *drawer,
context = gtk_widget_get_style_context (GTK_WIDGET (view));
gtk_style_context_save (context);
gtk_style_context_set_state (context, GTK_STATE_FLAG_INSENSITIVE);
- gtk_style_context_get_color (context,
- gtk_style_context_get_state (context),
- &color);
+ gtk_style_context_get_color (context, &color);
gtk_style_context_restore (context);
- drawer->color = gdk_rgba_copy (&color);
+ drawer->color = color;
+ drawer->color_set = TRUE;
}
}
@@ -806,61 +838,43 @@ is_whitespace (gunichar ch)
}
static void
-draw_space_at_pos (cairo_t *cr,
- GdkRectangle rect)
+draw_space_at_pos (cairo_t *cr,
+ gdouble w,
+ gdouble h)
{
- gint x, y;
- gdouble w;
-
- x = rect.x;
- y = rect.y + rect.height * 2 / 3;
-
- w = rect.width;
+ const gint x = 0;
+ const gint y = h * 2 / 3;
- cairo_save (cr);
cairo_move_to (cr, x + w * 0.5, y);
cairo_arc (cr, x + w * 0.5, y, 0.8, 0, 2 * G_PI);
cairo_stroke (cr);
- cairo_restore (cr);
}
static void
-draw_tab_at_pos (cairo_t *cr,
- GdkRectangle rect)
+draw_tab_at_pos (cairo_t *cr,
+ gdouble w,
+ gdouble h)
{
- gint x, y;
- gdouble w, h;
+ const gint x = 0;
+ const gint y = h * 2 / 3;
- x = rect.x;
- y = rect.y + rect.height * 2 / 3;
-
- w = rect.width;
- h = rect.height;
-
- cairo_save (cr);
cairo_move_to (cr, x + w * 1 / 8, y);
cairo_rel_line_to (cr, w * 6 / 8, 0);
cairo_rel_line_to (cr, -h * 1 / 4, -h * 1 / 4);
cairo_rel_move_to (cr, +h * 1 / 4, +h * 1 / 4);
cairo_rel_line_to (cr, -h * 1 / 4, +h * 1 / 4);
cairo_stroke (cr);
- cairo_restore (cr);
}
static void
-draw_newline_at_pos (cairo_t *cr,
- GdkRectangle rect)
+draw_newline_at_pos (cairo_t *cr,
+ gdouble w,
+ gdouble h)
{
- gint x, y;
- gdouble w, h;
-
- x = rect.x;
- y = rect.y + rect.height / 3;
-
- w = 2 * rect.width;
- h = rect.height;
+ const gint x = 0;
+ const gint y = h / 3;
- cairo_save (cr);
+ w = w * 2;
if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_LTR)
{
@@ -882,48 +896,50 @@ draw_newline_at_pos (cairo_t *cr,
}
cairo_stroke (cr);
- cairo_restore (cr);
}
static void
-draw_nbsp_at_pos (cairo_t *cr,
- GdkRectangle rect,
- gboolean narrowed)
+draw_narrow_nbsp_at_pos (cairo_t *cr,
+ gdouble w,
+ gdouble h)
{
- gint x, y;
- gdouble w, h;
+ const gint x = 0;
+ const gint y = h / 2;
- x = rect.x;
- y = rect.y + rect.height / 2;
-
- w = rect.width;
- h = rect.height;
-
- cairo_save (cr);
cairo_move_to (cr, x + w * 1 / 6, y);
cairo_rel_line_to (cr, w * 4 / 6, 0);
cairo_rel_line_to (cr, -w * 2 / 6, +h * 1 / 4);
cairo_rel_line_to (cr, -w * 2 / 6, -h * 1 / 4);
+ cairo_fill (cr);
+}
- if (narrowed)
- {
- cairo_fill (cr);
- }
- else
- {
- cairo_stroke (cr);
- }
+static void
+draw_nbsp_at_pos (cairo_t *cr,
+ gdouble w,
+ gdouble h)
+{
+ const gint x = 0;
+ const gint y = h / 2;
- cairo_restore (cr);
+ cairo_move_to (cr, x + w * 1 / 6, y);
+ cairo_rel_line_to (cr, w * 4 / 6, 0);
+ cairo_rel_line_to (cr, -w * 2 / 6, +h * 1 / 4);
+ cairo_rel_line_to (cr, -w * 2 / 6, -h * 1 / 4);
+ cairo_stroke (cr);
}
static void
-draw_whitespace_at_iter (GtkTextView *text_view,
- GtkTextIter *iter,
- cairo_t *cr)
+draw_whitespace_at_iter (GtkSourceSpaceDrawer *drawer,
+ GtkTextView *text_view,
+ const GtkTextIter *iter,
+ const GdkRGBA *color,
+ GtkSnapshot *snapshot)
{
- gunichar ch;
+ void (*draw) (cairo_t *cr, gdouble w, gdouble h) = NULL;
+ CachedNode *cache = NULL;
GdkRectangle rect;
+ gunichar ch;
+ gint ratio = 1;
gtk_text_view_get_iter_location (text_view, iter, &rect);
@@ -939,19 +955,66 @@ draw_whitespace_at_iter (GtkTextView *text_view,
if (is_tab (ch))
{
- draw_tab_at_pos (cr, rect);
+ draw = draw_tab_at_pos;
+ cache = &drawer->cached[DRAW_TAB];
}
else if (is_nbsp (ch))
{
- draw_nbsp_at_pos (cr, rect, is_narrowed_nbsp (ch));
+ if (is_narrowed_nbsp (ch))
+ {
+ draw = draw_narrow_nbsp_at_pos;
+ cache = &drawer->cached[DRAW_NARROW_NBSP];
+ }
+ else
+ {
+ draw = draw_nbsp_at_pos;
+ cache = &drawer->cached[DRAW_NBSP];
+ }
}
else if (is_space (ch))
{
- draw_space_at_pos (cr, rect);
+ draw = draw_space_at_pos;
+ cache = &drawer->cached[DRAW_SPACE];
}
else if (is_newline (iter))
{
- draw_newline_at_pos (cr, rect);
+ draw = draw_newline_at_pos;
+ cache = &drawer->cached[DRAW_NEWLINE];
+ ratio = 2;
+ }
+
+ g_assert (draw == NULL || cache != NULL);
+
+ if (draw != NULL)
+ {
+ if (cache->width != rect.width || cache->height != rect.height)
+ {
+ g_clear_pointer (&cache->node, gsk_render_node_unref);
+ }
+
+ if G_UNLIKELY (cache->node == NULL)
+ {
+ GtkSnapshot *to_cache;
+ cairo_t *cr;
+
+ to_cache = gtk_snapshot_new ();
+ cr = gtk_snapshot_append_cairo (to_cache,
+ &GRAPHENE_RECT_INIT (0, 0, rect.width * ratio,
rect.height));
+ gdk_cairo_set_source_rgba (cr, color);
+ cairo_set_line_width (cr, 0.8);
+ cairo_translate (cr, -0.5, -0.5);
+ draw (cr, rect.width, rect.height);
+ cairo_destroy (cr);
+
+ cache->node = gtk_snapshot_free_to_node (g_steal_pointer (&to_cache));
+ cache->width = rect.width;
+ cache->height = rect.height;
+ }
+
+ gtk_snapshot_save (snapshot);
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (rect.x, rect.y));
+ gtk_snapshot_append_node (snapshot, cache->node);
+ gtk_snapshot_restore (snapshot);
}
}
@@ -1143,11 +1206,11 @@ get_line_end (GtkTextView *text_view,
void
_gtk_source_space_drawer_draw (GtkSourceSpaceDrawer *drawer,
GtkSourceView *view,
- cairo_t *cr)
+ GtkSnapshot *snapshot)
{
GtkTextView *text_view;
GtkTextBuffer *buffer;
- GdkRectangle clip;
+ GdkRectangle visible;
gint min_x;
gint min_y;
gint max_x;
@@ -1172,9 +1235,8 @@ _gtk_source_space_drawer_draw (GtkSourceSpaceDrawer *drawer,
g_return_if_fail (GTK_SOURCE_IS_SPACE_DRAWER (drawer));
g_return_if_fail (GTK_SOURCE_IS_VIEW (view));
- g_return_if_fail (cr != NULL);
- if (drawer->color == NULL)
+ if (!drawer->color_set)
{
g_warning ("GtkSourceSpaceDrawer: color not set.");
return;
@@ -1189,26 +1251,18 @@ _gtk_source_space_drawer_draw (GtkSourceSpaceDrawer *drawer,
return;
}
- if (!gdk_cairo_get_clip_rectangle (cr, &clip))
- {
- return;
- }
+ gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (view), &visible);
is_wrapping = gtk_text_view_get_wrap_mode (text_view) != GTK_WRAP_NONE;
- min_x = clip.x;
- min_y = clip.y;
- max_x = min_x + clip.width;
- max_y = min_y + clip.height;
+ min_x = visible.x;
+ min_y = visible.y;
+ max_x = min_x + visible.width;
+ max_y = min_y + visible.height;
gtk_text_view_get_iter_at_location (text_view, &start, min_x, min_y);
gtk_text_view_get_iter_at_location (text_view, &end, max_x, max_y);
- cairo_save (cr);
- gdk_cairo_set_source_rgba (cr, drawer->color);
- cairo_set_line_width (cr, 0.8);
- cairo_translate (cr, -0.5, -0.5);
-
iter = start;
_gtk_source_iter_get_leading_spaces_end_boundary (&iter, &leading_end);
_gtk_source_iter_get_trailing_spaces_start_boundary (&iter, &trailing_start);
@@ -1223,7 +1277,11 @@ _gtk_source_space_drawer_draw (GtkSourceSpaceDrawer *drawer,
if ((is_whitespace (ch) || gtk_text_iter_is_end (&iter)) &&
space_needs_drawing (drawer, &iter, &leading_end, &trailing_start))
{
- draw_whitespace_at_iter (text_view, &iter, cr);
+ draw_whitespace_at_iter (drawer,
+ text_view,
+ &iter,
+ &drawer->color,
+ snapshot);
}
if (gtk_text_iter_is_end (&iter) ||
@@ -1276,8 +1334,6 @@ _gtk_source_space_drawer_draw (GtkSourceSpaceDrawer *drawer,
}
};
- cairo_restore (cr);
-
#ifdef ENABLE_PROFILE
g_timer_stop (timer);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]