From e4e7a76a173620394a4bff9738d9b156c40e8c45 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 19 Aug 2020 14:09:00 -0400 Subject: 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. --- pango/pangofc-fontmap.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) 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; @@ -1313,6 +1321,29 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (PangoFcFontMap, pango_fc_font_map, PANGO_TYPE_ G_ADD_PRIVATE (PangoFcFontMap) 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) { @@ -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); -- cgit v1.2.1