summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-08-19 14:09:00 -0400
committerMatthias Clasen <mclasen@redhat.com>2021-02-22 08:27:16 -0500
commite4e7a76a173620394a4bff9738d9b156c40e8c45 (patch)
tree256d1aea4760c4e331a3554bd24baf5454a0853a
parent8f15d1b320f1d859cc0a1a70c1de3c8092ba6b43 (diff)
downloadpango-e4e7a76a173620394a4bff9738d9b156c40e8c45.tar.gz
Move FcInit call to a thread
With a big fontconfig configuration, FcInit takes some time (60-100ms on my system). Doing this work off the main thread can potentially avoid blocking other work. To take advantage of this, GTK calls pango_cairo_font_map_get_default() early to initiate the creation of a fontmap, thereby triggering the FcInit() call.
-rw-r--r--pango/pangofc-fontmap.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index 14492607..9364c082 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -109,6 +109,14 @@
* FcCharSetMerge().
*/
+/* We call FcInit in a thread and set fc_initialized
+ * when done, and are protected by a mutex. The thread
+ * signals the cond when FcInit is done.
+ */
+static GMutex fc_init_mutex;
+static GCond fc_init_cond;
+static gboolean fc_initialized;
+
typedef struct _PangoFcFontFaceData PangoFcFontFaceData;
typedef struct _PangoFcFace PangoFcFace;
@@ -1314,6 +1322,29 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (PangoFcFontMap, pango_fc_font_map, PANGO_TYPE_
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, pango_fc_font_map_list_model_init))
static void
+init_in_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ FcInit ();
+
+ g_mutex_lock (&fc_init_mutex);
+ fc_initialized = TRUE;
+ g_cond_signal (&fc_init_cond);
+ g_mutex_unlock (&fc_init_mutex);
+}
+
+static void
+wait_for_fc_init (void)
+{
+ g_mutex_lock (&fc_init_mutex);
+ while (!fc_initialized)
+ g_cond_wait (&fc_init_cond, &fc_init_mutex);
+ g_mutex_unlock (&fc_init_mutex);
+}
+
+static void
pango_fc_font_map_init (PangoFcFontMap *fcfontmap)
{
PangoFcFontMapPrivate *priv;
@@ -1343,6 +1374,16 @@ pango_fc_font_map_init (PangoFcFontMap *fcfontmap)
(GDestroyNotify)pango_fc_font_face_data_free,
NULL);
priv->dpi = -1;
+
+ if (!fc_initialized)
+ {
+ GTask *task;
+
+ task = g_task_new (fcfontmap, NULL, NULL, NULL);
+ g_task_set_name (task, "[pango] FcInit");
+ g_task_run_in_thread (task, init_in_thread);
+ g_object_unref (task);
+ }
}
static void
@@ -1567,6 +1608,8 @@ ensure_families (PangoFcFontMap *fcfontmap)
int i;
int count;
+ wait_for_fc_init ();
+
if (priv->n_families < 0)
{
FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, FC_SPACING, FC_STYLE, FC_WEIGHT, FC_WIDTH, FC_SLANT,
@@ -2233,6 +2276,9 @@ pango_fc_font_map_set_config (PangoFcFontMap *fcfontmap,
if (oldconfig)
FcConfigDestroy (oldconfig);
+
+ /* No need to wait anymore */
+ fc_initialized = TRUE;
}
/**
@@ -2253,6 +2299,8 @@ pango_fc_font_map_get_config (PangoFcFontMap *fcfontmap)
{
g_return_val_if_fail (PANGO_IS_FC_FONT_MAP (fcfontmap), NULL);
+ wait_for_fc_init ();
+
return fcfontmap->priv->config;
}
@@ -2263,6 +2311,8 @@ pango_fc_font_map_get_config_fonts (PangoFcFontMap *fcfontmap)
{
FcFontSet *sets[2];
+ wait_for_fc_init ();
+
sets[0] = FcConfigGetFonts (fcfontmap->priv->config, 0);
sets[1] = FcConfigGetFonts (fcfontmap->priv->config, 1);
fcfontmap->priv->fonts = filter_by_format (sets, 2);