vte r2154 - in trunk: . src
- From: behdad svn gnome org
- To: svn-commits-list gnome org
- Subject: vte r2154 - in trunk: . src
- Date: Thu, 20 Nov 2008 15:11:41 +0000 (UTC)
Author: behdad
Date: Thu Nov 20 15:11:41 2008
New Revision: 2154
URL: http://svn.gnome.org/viewvc/vte?rev=2154&view=rev
Log:
2008-11-20 Behdad Esfahbod <behdad gnome org>
Bug 560818 â pangocairo backend doesn't share font cache across
widgets
* src/vtepangocairo.c (font_info_cache_ascii),
(font_info_allocate), (font_info_free), (font_info_register),
(font_info_unregister), (font_info_reference),
(font_info_destroy_delayed), (font_info_destroy), (context_hash),
(context_equal), (font_info_find_for_context),
(font_info_create_for_context), (font_info_create_for_screen),
(font_info_get_unichar_info): Cache font info and use it for multiple
widgets.
Modified:
trunk/ChangeLog
trunk/src/vtedraw.h
trunk/src/vtepangocairo.c
Modified: trunk/src/vtedraw.h
==============================================================================
--- trunk/src/vtedraw.h (original)
+++ trunk/src/vtedraw.h Thu Nov 20 15:11:41 2008
@@ -30,7 +30,7 @@
G_BEGIN_DECLS
#define VTE_DRAW_SINGLE_WIDE_CHARACTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
- "abcdefgjijklmnopqrstuvwxyz" \
+ "abcdefghijklmnopqrstuvwxyz" \
"0123456789./+@&"
#define VTE_DRAW_DOUBLE_WIDE_CHARACTERS 0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x4e94,\
0xac00, 0xac01, 0xac04, 0xac08, 0xac10
Modified: trunk/src/vtepangocairo.c
==============================================================================
--- trunk/src/vtepangocairo.c (original)
+++ trunk/src/vtepangocairo.c Thu Nov 20 15:11:41 2008
@@ -32,11 +32,12 @@
#include <pango/pangocairo.h>
#include <glib/gi18n-lib.h>
-#undef PROFILE_COVERAGE
+#undef VTEPANGOCAIRO_PROFILE
+
+
+/* All shared data structures are implicitly protected by GDK mutex, because
+ * that's how vte.c works and we only get called from there. */
-#ifdef PROFILE_COVERAGE
-static int coverage_count[4];
-#endif
/* cairo_show_glyphs accepts runs up to 102 glyphs before it allocates a
* temporary array.
@@ -127,14 +128,21 @@
}
struct font_info {
+ int ref_count;
+
PangoLayout *layout;
struct unichar_info ascii_unichar_info[128];
GHashTable *other_unichar_info;
gint width, height, ascent;
+
+#ifdef VTEPANGOCAIRO_PROFILE
+ int coverage_count[4];
+#endif
};
+
static struct unichar_info *
font_info_find_unichar_info (struct font_info *info,
gunichar c)
@@ -156,6 +164,7 @@
return uinfo;
}
+
static void
font_info_cache_ascii (struct font_info *info)
{
@@ -235,7 +244,16 @@
ufi->using_cairo_glyph.scaled_font = cairo_scaled_font_reference (scaled_font);
ufi->using_cairo_glyph.glyph_index = glyph;
+
+#ifdef VTEPANGOCAIRO_PROFILE
+ info->coverage_count[0]++;
+ info->coverage_count[uinfo->coverage]++;
+#endif
}
+
+#ifdef VTEPANGOCAIRO_PROFILE
+ g_message ("vtepangocairo: cached %d ASCII letters", info->coverage_count[0]);
+#endif
}
static void
@@ -290,20 +308,164 @@
info->width, info->height, info->ascent);
}
+
static struct font_info *
-font_info_create_for_screen (GdkScreen *screen,
- const PangoFontDescription *desc,
- VteTerminalAntiAlias antialias)
+font_info_allocate (PangoContext *context)
{
struct font_info *info;
- PangoContext *context;
- PangoLayout *layout;
- /* XXX caching */
+#ifdef VTEPANGOCAIRO_PROFILE
+ g_message ("vtepangocairo: allocating font_info");
+#endif
info = g_slice_new0 (struct font_info);
- context = gdk_pango_context_get_for_screen (screen);
+ info->layout = pango_layout_new (context);
+
+ font_info_measure_font (info);
+
+ return info;
+}
+
+static void
+font_info_free (struct font_info *info)
+{
+ gunichar i;
+
+#ifdef VTEPANGOCAIRO_PROFILE
+ g_message ("vtepangocairo: freeing font_info. coverages %d = %d + %d + %d",
+ info->coverage_count[0],
+ info->coverage_count[1],
+ info->coverage_count[2],
+ info->coverage_count[3]);
+#endif
+
+ g_object_unref (info->layout);
+
+ for (i = 0; i < G_N_ELEMENTS (info->ascii_unichar_info); i++)
+ unichar_info_finish (&info->ascii_unichar_info[i]);
+
+ if (info->other_unichar_info) {
+ g_hash_table_destroy (info->other_unichar_info);
+ }
+
+ g_slice_free (struct font_info, info);
+}
+
+
+static GHashTable *font_info_for_context;
+
+static struct font_info *
+font_info_register (struct font_info *info)
+{
+ /* claims the context reference, but doesn't hold a ref to font_info */
+ g_hash_table_insert (font_info_for_context,
+ pango_layout_get_context (info->layout),
+ info);
+
+ return info;
+}
+
+static void
+font_info_unregister (struct font_info *info)
+{
+ g_hash_table_remove (font_info_for_context,
+ pango_layout_get_context (info->layout));
+}
+
+
+static struct font_info *
+font_info_reference (struct font_info *info)
+{
+ if (!info)
+ return info;
+
+ g_return_val_if_fail (info->ref_count >= 0, info);
+
+ info->ref_count++;
+
+ return info;
+}
+
+static gboolean
+font_info_destroy_delayed (struct font_info *info)
+{
+ GDK_THREADS_ENTER ();
+
+ if (info->ref_count == 0) {
+ font_info_unregister (info);
+ font_info_free (info);
+ }
+
+ GDK_THREADS_LEAVE ();
+
+ return FALSE;
+}
+
+static void
+font_info_destroy (struct font_info *info)
+{
+ if (!info)
+ return;
+
+ g_return_if_fail (info->ref_count > 0);
+
+ info->ref_count--;
+ if (info->ref_count)
+ return;
+
+ /* Delay destruction by a few seconds, in case we need it again */
+ g_timeout_add_seconds (30, (GSourceFunc) font_info_destroy_delayed, info);
+}
+
+static guint
+context_hash (PangoContext *context)
+{
+ return pango_units_from_double (pango_cairo_context_get_resolution (context))
+ ^ pango_font_description_hash (pango_context_get_font_description (context))
+ ^ cairo_font_options_hash (pango_cairo_context_get_font_options (context));
+}
+
+static gboolean
+context_equal (PangoContext *a,
+ PangoContext *b)
+{
+ return pango_cairo_context_get_resolution (a) == pango_cairo_context_get_resolution (b)
+ && pango_font_description_equal (pango_context_get_font_description (a), pango_context_get_font_description (b))
+ && cairo_font_options_equal (pango_cairo_context_get_font_options (a), pango_cairo_context_get_font_options (b));
+}
+
+static struct font_info *
+font_info_find_for_context (PangoContext *context)
+{
+ struct font_info *info;
+
+ if (G_UNLIKELY (font_info_for_context == NULL))
+ font_info_for_context = g_hash_table_new ((GHashFunc) context_hash, (GEqualFunc) context_equal);
+
+ info = g_hash_table_lookup (font_info_for_context, context);
+ if (G_LIKELY (info)) {
+#ifdef VTEPANGOCAIRO_PROFILE
+ g_message ("vtepangocairo: found font_info in cache");
+#endif
+ return font_info_reference (info);
+ }
+
+ info = font_info_allocate (context);
+ info->ref_count = 1;
+ font_info_register (info);
+
+ g_object_unref (context);
+
+ return info;
+}
+
+/* assumes ownership/reference of context */
+static struct font_info *
+font_info_create_for_context (PangoContext *context,
+ const PangoFontDescription *desc,
+ VteTerminalAntiAlias antialias)
+{
if (!PANGO_IS_CAIRO_FONT_MAP (pango_context_get_font_map (context))) {
/* Ouch, Gtk+ switched over to some drawing system?
* Lets just create one from the default font map.
@@ -337,45 +499,27 @@
default:
case VTE_ANTI_ALIAS_USE_DEFAULT:
+ /* Make sure our contexts have a font_options set. We use
+ * this invariant in our context hash and equal functions.
+ */
+ if (!pango_cairo_context_get_font_options (context)) {
+ font_options = cairo_font_options_create ();
+ pango_cairo_context_set_font_options (context, font_options);
+ cairo_font_options_destroy (font_options);
+ }
break;
}
- info->layout = layout = pango_layout_new (context);
- g_object_unref (context);
-
- font_info_measure_font (info);
-
- return info;
+ return font_info_find_for_context (context);
}
-static void
-font_info_destroy (struct font_info *info)
+static struct font_info *
+font_info_create_for_screen (GdkScreen *screen,
+ const PangoFontDescription *desc,
+ VteTerminalAntiAlias antialias)
{
- gunichar i;
-
- if (!info)
- return;
-
- g_object_unref (info->layout);
- info->layout = NULL;
-
- for (i = 0; i < G_N_ELEMENTS (info->ascii_unichar_info); i++)
- unichar_info_finish (&info->ascii_unichar_info[i]);
-
- if (info->other_unichar_info) {
- g_hash_table_destroy (info->other_unichar_info);
- info->other_unichar_info = NULL;
- }
-
- info->width = info->height = info->ascent = 1;
-
-#ifdef PROFILE_COVERAGE
- g_message ("coverages %d = %d + %d + %d",
- coverage_count[0],
- coverage_count[1],
- coverage_count[2],
- coverage_count[3]);
-#endif
+ return font_info_create_for_context (gdk_pango_context_get_for_screen (screen),
+ desc, antialias);
}
static struct font_info *
@@ -460,9 +604,9 @@
}
}
-#ifdef PROFILE_COVERAGE
- coverage_count[0]++;
- coverage_count[uinfo->coverage]++;
+#ifdef VTEPANGOCAIRO_PROFILE
+ info->coverage_count[0]++;
+ info->coverage_count[uinfo->coverage]++;
#endif
return uinfo;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]