GimpFontFactory: Move font loading to another thread

This is to make sure than regardless of how many fonts there are, font loading
won't delay startup.

FontConfig if compiled against libxml2 might fail to parse huge xml configs.
So instead of passing it a huge xml, pass the xml every MAX_NUM_FONTS_PER_CONFIG (currently 1000) fonts.

Also made GimpFontFactory custom config strings private because there is no reason for them to be public.
This commit is contained in:
Idriss Fekir 2025-05-06 01:49:34 +02:00 committed by Jehan
parent f63e8afe60
commit 8328dfb25b
10 changed files with 170 additions and 145 deletions

View file

@ -279,5 +279,6 @@ libappcore = static_library('appcore',
math, math,
dl, dl,
libunwind, libunwind,
pango,
], ],
) )

View file

@ -68,7 +68,7 @@ fonts_get_custom_configs_invoker (GimpProcedure *procedure,
GimpValueArray *return_vals; GimpValueArray *return_vals;
gchar *config = NULL; gchar *config = NULL;
gchar *sysconfig = NULL; gchar *sysconfig = NULL;
gchar *renaming_config = NULL; gchar **renaming_config = NULL;
gchar **dirs = NULL; gchar **dirs = NULL;
if (! gimp_data_factory_data_wait (gimp->font_factory)) if (! gimp_data_factory_data_wait (gimp->font_factory))
@ -77,6 +77,7 @@ fonts_get_custom_configs_invoker (GimpProcedure *procedure,
if (success) if (success)
{ {
GList *list = gimp_font_factory_get_custom_fonts_dirs (GIMP_FONT_FACTORY (gimp->font_factory)); GList *list = gimp_font_factory_get_custom_fonts_dirs (GIMP_FONT_FACTORY (gimp->font_factory));
GSList *fonts_renaming_config = gimp_font_factory_get_fonts_renaming_config (GIMP_FONT_FACTORY (gimp->font_factory));
guint length = g_list_length (list); guint length = g_list_length (list);
gint i; gint i;
@ -86,14 +87,19 @@ fonts_get_custom_configs_invoker (GimpProcedure *procedure,
config = g_strdup (config); config = g_strdup (config);
sysconfig = g_strdup (sysconfig); sysconfig = g_strdup (sysconfig);
renaming_config = g_strdup (gimp_font_factory_get_fonts_renaming_config (GIMP_FONT_FACTORY (gimp->font_factory)));
dirs = g_new0 (gchar *, length + 1); dirs = g_new0 (gchar *, length + 1);
for (i = 0; list; list = g_list_next (list), i++) for (i = 0; list; list = g_list_next (list), i++)
dirs[i] = g_file_get_path (list->data); dirs[i] = g_file_get_path (list->data);
g_list_free_full (list, (GDestroyNotify) g_object_unref); g_list_free_full (list, (GDestroyNotify) g_object_unref);
length = g_slist_length (fonts_renaming_config);
renaming_config = g_new0 (gchar *, length + 1);
for (i = 0; fonts_renaming_config; fonts_renaming_config = g_slist_next (fonts_renaming_config), i++)
renaming_config[i] = g_strdup (fonts_renaming_config->data);
} }
return_vals = gimp_procedure_get_return_values (procedure, success, return_vals = gimp_procedure_get_return_values (procedure, success,
@ -103,7 +109,7 @@ fonts_get_custom_configs_invoker (GimpProcedure *procedure,
{ {
g_value_take_string (gimp_value_array_index (return_vals, 1), config); g_value_take_string (gimp_value_array_index (return_vals, 1), config);
g_value_take_string (gimp_value_array_index (return_vals, 2), sysconfig); g_value_take_string (gimp_value_array_index (return_vals, 2), sysconfig);
g_value_take_string (gimp_value_array_index (return_vals, 3), renaming_config); g_value_take_boxed (gimp_value_array_index (return_vals, 3), renaming_config);
g_value_take_boxed (gimp_value_array_index (return_vals, 4), dirs); g_value_take_boxed (gimp_value_array_index (return_vals, 4), dirs);
} }
@ -195,11 +201,10 @@ register_fonts_procs (GimpPDB *pdb)
NULL, NULL,
GIMP_PARAM_READWRITE)); GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure, gimp_procedure_add_return_value (procedure,
gimp_param_spec_string ("renaming-config", g_param_spec_boxed ("renaming-config",
"renaming config", "renaming config",
"fonts renaming config", "fonts renaming config",
FALSE, FALSE, FALSE, G_TYPE_STRV,
NULL,
GIMP_PARAM_READWRITE)); GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure, gimp_procedure_add_return_value (procedure,
g_param_spec_boxed ("dirs", g_param_spec_boxed ("dirs",

View file

@ -83,7 +83,7 @@ libappinternalprocs = static_library('appinternalprocs',
include_directories: [ rootInclude, rootAppInclude, ], include_directories: [ rootInclude, rootAppInclude, ],
c_args: '-DG_LOG_DOMAIN="Gimp-PDB"', c_args: '-DG_LOG_DOMAIN="Gimp-PDB"',
dependencies: [ dependencies: [
cairo, gegl, gdk_pixbuf, pangocairo, cairo, gegl, gdk_pixbuf, pangocairo, pango,
], ],
sources: [ sources: [
pdbgen pdbgen

View file

@ -85,8 +85,6 @@ struct _GimpFont
{ {
GimpData parent_instance; GimpData parent_instance;
PangoContext *pango_context;
PangoLayout *popup_layout; PangoLayout *popup_layout;
gint popup_width; gint popup_width;
gint popup_height; gint popup_height;
@ -114,15 +112,11 @@ struct _GimpFontClass
{ {
GimpDataClass parent_class; GimpDataClass parent_class;
GimpContainer *fonts_container; GimpFontFactory *font_factory;
}; };
static void gimp_font_finalize (GObject *object); static void gimp_font_finalize (GObject *object);
static void gimp_font_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_font_get_preview_size (GimpViewable *viewable, static void gimp_font_get_preview_size (GimpViewable *viewable,
gint size, gint size,
@ -240,9 +234,9 @@ gimp_font_deserialize_create (GType type,
gpointer data) gpointer data)
{ {
GimpFont *font = NULL; GimpFont *font = NULL;
GimpContainer *fonts_container = GIMP_FONT_CLASS (g_type_class_peek (GIMP_TYPE_FONT))->fonts_container; GimpContainer *fonts_container;
gint most_similar_font_index = -1; gint most_similar_font_index = -1;
gint font_count = gimp_container_get_n_children (fonts_container); gint font_count;
gint largest_similarity = 0; gint largest_similarity = 0;
GList *similar_fonts = NULL; GList *similar_fonts = NULL;
GList *iter; GList *iter;
@ -260,6 +254,8 @@ gimp_font_deserialize_create (GType type,
guint scope_id; guint scope_id;
guint old_scope_id; guint old_scope_id;
fonts_container = gimp_data_factory_get_container (GIMP_DATA_FACTORY (GIMP_FONT_CLASS (g_type_class_peek (GIMP_TYPE_FONT))->font_factory));
font_count = gimp_container_get_n_children (fonts_container);
/* This is for backward compatibility with older xcf files. /* This is for backward compatibility with older xcf files.
* The font used to be serialized as a string containing * The font used to be serialized as a string containing
* its name. * its name.
@ -540,7 +536,7 @@ gimp_font_class_set_font_factory (GimpFontFactory *factory)
g_return_if_fail (GIMP_IS_FONT_FACTORY (factory)); g_return_if_fail (GIMP_IS_FONT_FACTORY (factory));
klass->fonts_container = gimp_data_factory_get_container (GIMP_DATA_FACTORY (factory)); klass->font_factory = factory;
} }
void void
@ -596,7 +592,6 @@ gimp_font_class_init (GimpFontClass *klass)
GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
object_class->finalize = gimp_font_finalize; object_class->finalize = gimp_font_finalize;
object_class->set_property = gimp_font_set_property;
gimp_object_class->get_memsize = gimp_font_get_memsize; gimp_object_class->get_memsize = gimp_font_get_memsize;
viewable_class->get_preview_size = gimp_font_get_preview_size; viewable_class->get_preview_size = gimp_font_get_preview_size;
@ -604,12 +599,6 @@ gimp_font_class_init (GimpFontClass *klass)
viewable_class->get_new_preview = gimp_font_get_new_preview; viewable_class->get_new_preview = gimp_font_get_new_preview;
viewable_class->default_icon_name = "gtk-select-font"; viewable_class->default_icon_name = "gtk-select-font";
g_object_class_install_property (object_class, PROP_PANGO_CONTEXT,
g_param_spec_object ("pango-context",
NULL, NULL,
PANGO_TYPE_CONTEXT,
GIMP_PARAM_WRITABLE));
} }
static void static void
@ -622,7 +611,6 @@ gimp_font_finalize (GObject *object)
{ {
GimpFont *font = GIMP_FONT (object); GimpFont *font = GIMP_FONT (object);
g_clear_object (&font->pango_context);
g_clear_object (&font->popup_layout); g_clear_object (&font->popup_layout);
g_free (font->lookup_name); g_free (font->lookup_name);
g_free (font->hash); g_free (font->hash);
@ -637,28 +625,6 @@ gimp_font_finalize (GObject *object)
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
static void
gimp_font_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpFont *font = GIMP_FONT (object);
switch (property_id)
{
case PROP_PANGO_CONTEXT:
if (font->pango_context)
g_object_unref (font->pango_context);
font->pango_context = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static gint64 static gint64
gimp_font_get_memsize (GimpObject *object, gimp_font_get_memsize (GimpObject *object,
gint64 *gui_size) gint64 *gui_size)
@ -701,12 +667,15 @@ gimp_font_get_popup_size (GimpViewable *viewable,
gint *popup_height) gint *popup_height)
{ {
GimpFont *font = GIMP_FONT (viewable); GimpFont *font = GIMP_FONT (viewable);
PangoContext *pango_context;
PangoFontDescription *font_desc; PangoFontDescription *font_desc;
PangoRectangle ink; PangoRectangle ink;
PangoRectangle logical; PangoRectangle logical;
const gchar *name; const gchar *name;
if (! font->pango_context) pango_context = gimp_font_factory_get_pango_context (GIMP_FONT_CLASS (g_type_class_peek (GIMP_TYPE_FONT))->font_factory);
if (! pango_context)
return FALSE; return FALSE;
name = font->lookup_name; name = font->lookup_name;
@ -719,7 +688,7 @@ gimp_font_get_popup_size (GimpViewable *viewable,
if (font->popup_layout) if (font->popup_layout)
g_object_unref (font->popup_layout); g_object_unref (font->popup_layout);
font->popup_layout = pango_layout_new (font->pango_context); font->popup_layout = pango_layout_new (pango_context);
pango_layout_set_font_description (font->popup_layout, font_desc); pango_layout_set_font_description (font->popup_layout, font_desc);
pango_font_description_free (font_desc); pango_font_description_free (font_desc);
@ -744,6 +713,7 @@ gimp_font_get_new_preview (GimpViewable *viewable,
gint height) gint height)
{ {
GimpFont *font = GIMP_FONT (viewable); GimpFont *font = GIMP_FONT (viewable);
PangoContext *pango_context;
PangoLayout *layout; PangoLayout *layout;
PangoRectangle ink; PangoRectangle ink;
PangoRectangle logical; PangoRectangle logical;
@ -755,7 +725,9 @@ gimp_font_get_new_preview (GimpViewable *viewable,
cairo_t *cr; cairo_t *cr;
cairo_surface_t *surface; cairo_surface_t *surface;
if (! font->pango_context) pango_context = gimp_font_factory_get_pango_context (GIMP_FONT_CLASS (g_type_class_peek (GIMP_TYPE_FONT))->font_factory);
if (! pango_context)
return NULL; return NULL;
if (! font->popup_layout || if (! font->popup_layout ||
@ -774,11 +746,11 @@ gimp_font_get_new_preview (GimpViewable *viewable,
pango_font_description_set_size (font_desc, pango_font_description_set_size (font_desc,
PANGO_SCALE * height * 2.0 / 3.0); PANGO_SCALE * height * 2.0 / 3.0);
layout = pango_layout_new (font->pango_context); layout = pango_layout_new (pango_context);
pango_layout_set_font_description (layout, font_desc); pango_layout_set_font_description (layout, font_desc);
pango_layout_set_text (layout, pango_layout_set_text (layout,
gimp_font_get_sample_string (font->pango_context, gimp_font_get_sample_string (pango_context,
font_desc), font_desc),
-1); -1);
@ -1370,7 +1342,9 @@ gimp_font_get_hash (GimpFont *font)
if (font->hash == NULL) if (font->hash == NULL)
{ {
PangoFontDescription *pfd = pango_font_description_from_string (font->lookup_name); PangoFontDescription *pfd = pango_font_description_from_string (font->lookup_name);
PangoFcFont *pango_font = PANGO_FC_FONT (pango_context_load_font (font->pango_context, pfd)); GimpFontFactory *font_factory = GIMP_FONT_CLASS (g_type_class_peek (GIMP_TYPE_FONT))->font_factory;
PangoContext *pango_context = gimp_font_factory_get_pango_context (font_factory);
PangoFcFont *pango_font = PANGO_FC_FONT (pango_context_load_font (pango_context, pfd));
GChecksum *checksum = g_checksum_new (G_CHECKSUM_SHA256); GChecksum *checksum = g_checksum_new (G_CHECKSUM_SHA256);
gchar *file; gchar *file;
hb_blob_t *hb_blob; hb_blob_t *hb_blob;

View file

@ -55,7 +55,10 @@
struct _GimpFontFactoryPrivate struct _GimpFontFactoryPrivate
{ {
gpointer foo; /* can't have an empty struct */ GSList *fonts_renaming_config;
gchar *conf;
gchar *sysconf;
PangoContext *pango_context;
}; };
#define GET_PRIVATE(obj) (((GimpFontFactory *) (obj))->priv) #define GET_PRIVATE(obj) (((GimpFontFactory *) (obj))->priv)
@ -87,11 +90,10 @@ static void gimp_font_factory_recursive_add_fontdir
(FcConfig *config, (FcConfig *config,
GFile *file, GFile *file,
GError **error); GError **error);
static void gimp_font_factory_load_names (GimpFontFactory *container, static int gimp_font_factory_load_names (GimpFontFactory *container);
PangoFontMap *fontmap, static void gimp_font_factory_load_aliases (GimpContainer *container,
PangoContext *context); PangoContext *context);
G_DEFINE_TYPE_WITH_PRIVATE (GimpFontFactory, gimp_font_factory, G_DEFINE_TYPE_WITH_PRIVATE (GimpFontFactory, gimp_font_factory,
GIMP_TYPE_DATA_FACTORY) GIMP_TYPE_DATA_FACTORY)
@ -207,9 +209,11 @@ gimp_font_factory_finalize (GObject *object)
{ {
GimpFontFactory *font_factory = GIMP_FONT_FACTORY(object); GimpFontFactory *font_factory = GIMP_FONT_FACTORY(object);
g_free (font_factory->fonts_renaming_config); g_slist_free_full (GET_PRIVATE (font_factory)->fonts_renaming_config, (GDestroyNotify) g_free);
g_free (font_factory->sysconf); g_free (GET_PRIVATE (font_factory)->sysconf);
g_free (font_factory->conf); g_free (GET_PRIVATE (font_factory)->conf);
g_object_unref (GET_PRIVATE (font_factory)->pango_context);
FcConfigDestroy (FcConfigGetCurrent ());
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
@ -244,29 +248,35 @@ gimp_font_factory_get_custom_config_path (GimpFontFactory *factory,
gchar **conf, gchar **conf,
gchar **sysconf) gchar **sysconf)
{ {
*conf = factory->conf; *conf = GET_PRIVATE (factory)->conf;
*sysconf = factory->sysconf; *sysconf = GET_PRIVATE (factory)->sysconf;
} }
gchar * GSList *
gimp_font_factory_get_fonts_renaming_config (GimpFontFactory *factory) gimp_font_factory_get_fonts_renaming_config (GimpFontFactory *factory)
{ {
return factory->fonts_renaming_config; return (GET_PRIVATE (factory))->fonts_renaming_config;
}
PangoContext *
gimp_font_factory_get_pango_context (GimpFontFactory *factory)
{
return GET_PRIVATE (factory)->pango_context;
} }
/* private functions */ /* private functions */
static void static void
gimp_font_factory_load_async (GimpAsync *async, gimp_font_factory_load_async (GimpAsync *async,
FcConfig *config) GimpFontFactory *factory)
{ {
if (FcConfigBuildFonts (config)) if (FcConfigBuildFonts (NULL))
{ {
gimp_async_finish (async, config); gimp_async_finish (async, GINT_TO_POINTER (gimp_font_factory_load_names (factory)));
} }
else else
{ {
FcConfigDestroy (config); FcConfigDestroy (FcConfigGetCurrent ());
gimp_async_abort (async); gimp_async_abort (async);
} }
@ -288,12 +298,10 @@ gimp_font_factory_load_async_callback (GimpAsync *async,
if (gimp_async_is_finished (async)) if (gimp_async_is_finished (async))
{ {
FcConfig *config = gimp_async_get_result (async); gint num_fonts = GPOINTER_TO_INT (gimp_async_get_result (async));
PangoFontMap *fontmap; PangoFontMap *fontmap;
PangoContext *context; PangoContext *context;
FcConfigSetCurrent (config);
fontmap = pango_cairo_font_map_new_for_font_type (CAIRO_FONT_TYPE_FT); fontmap = pango_cairo_font_map_new_for_font_type (CAIRO_FONT_TYPE_FT);
if (! fontmap) if (! fontmap)
g_error ("You are using a Pango that has been built against a cairo " g_error ("You are using a Pango that has been built against a cairo "
@ -302,11 +310,12 @@ gimp_font_factory_load_async_callback (GimpAsync *async,
pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (fontmap), pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (fontmap),
72.0 /* FIXME */); 72.0 /* FIXME */);
context = pango_font_map_create_context (fontmap); context = pango_font_map_create_context (fontmap);
GET_PRIVATE (factory)->pango_context = context;
g_object_unref (fontmap); g_object_unref (fontmap);
gimp_font_factory_load_names (factory, PANGO_FONT_MAP (fontmap), context); /* only create aliases if there is at least one font available */
g_object_unref (context); if (num_fonts > 0)
FcConfigDestroy (config); gimp_font_factory_load_aliases (container, context);
} }
gimp_container_thaw (container); gimp_container_thaw (container);
@ -352,8 +361,8 @@ gimp_font_factory_load (GimpFontFactory *factory,
} }
else else
{ {
g_free (factory->conf); g_free (GET_PRIVATE (factory)->conf);
factory->conf = g_file_get_path (fonts_conf); GET_PRIVATE (factory)->conf = g_file_get_path (fonts_conf);
} }
g_object_unref (fonts_conf); g_object_unref (fonts_conf);
@ -366,8 +375,8 @@ gimp_font_factory_load (GimpFontFactory *factory,
} }
else else
{ {
g_free (factory->sysconf); g_free (GET_PRIVATE (factory)->sysconf);
factory->sysconf = g_file_get_path (fonts_conf); GET_PRIVATE (factory)->sysconf = g_file_get_path (fonts_conf);
} }
g_object_unref (fonts_conf); g_object_unref (fonts_conf);
@ -382,6 +391,7 @@ gimp_font_factory_load (GimpFontFactory *factory,
gimp_font_factory_add_directories (factory, config, path, error); gimp_font_factory_add_directories (factory, config, path, error);
g_list_free_full (path, (GDestroyNotify) g_object_unref); g_list_free_full (path, (GDestroyNotify) g_object_unref);
FcConfigSetCurrent (config);
/* We perform font cache initialization in a separate thread, so /* We perform font cache initialization in a separate thread, so
* in the case a cache rebuild is to be done it will not block * in the case a cache rebuild is to be done it will not block
* the UI. * the UI.
@ -389,7 +399,7 @@ gimp_font_factory_load (GimpFontFactory *factory,
async = gimp_parallel_run_async_independent_full ( async = gimp_parallel_run_async_independent_full (
+10, +10,
(GimpRunAsyncFunc) gimp_font_factory_load_async, (GimpRunAsyncFunc) gimp_font_factory_load_async,
config); factory);
gimp_async_add_callback_for_object ( gimp_async_add_callback_for_object (
async, async,
@ -591,7 +601,6 @@ gimp_font_factory_recursive_add_fontdir (FcConfig *config,
static void static void
gimp_font_factory_add_font (GimpContainer *container, gimp_font_factory_add_font (GimpContainer *container,
PangoContext *context,
PangoFontDescription *desc, PangoFontDescription *desc,
const gchar *full_name, const gchar *full_name,
const gchar *path, const gchar *path,
@ -616,7 +625,6 @@ gimp_font_factory_add_font (GimpContainer *container,
font = g_object_new (GIMP_TYPE_FONT, font = g_object_new (GIMP_TYPE_FONT,
"name", name, "name", name,
"pango-context", context,
NULL); NULL);
gimp_font_set_lookup_name (font, pango_font_description_to_string (desc)); gimp_font_set_lookup_name (font, pango_font_description_to_string (desc));
@ -717,7 +725,7 @@ gimp_font_factory_make_alias (GimpContainer *container,
* are the best way to have differing text renders over time (and that's not * are the best way to have differing text renders over time (and that's not
* something to be wished for). XXX * something to be wished for). XXX
*/ */
gimp_font_factory_add_font (container, context, desc, NULL, NULL, font_info); gimp_font_factory_add_font (container, desc, NULL, NULL, font_info);
g_free (desc_str); g_free (desc_str);
pango_font_description_free (desc); pango_font_description_free (desc);
@ -743,10 +751,8 @@ gimp_font_factory_load_aliases (GimpContainer *container,
} }
} }
static void static gint
gimp_font_factory_load_names (GimpFontFactory *factory, gimp_font_factory_load_names (GimpFontFactory *factory)
PangoFontMap *fontmap,
PangoContext *context)
{ {
GimpContainer *container; GimpContainer *container;
FcObjectSet *os; FcObjectSet *os;
@ -761,6 +767,8 @@ gimp_font_factory_load_names (GimpFontFactory *factory,
GString *ignored_fonts; GString *ignored_fonts;
gint n_ignored = 0; gint n_ignored = 0;
gint i; gint i;
gint num_fonts_in_current_config = 0;
gint n_loaded_fonts = 0;
container = gimp_data_factory_get_container (GIMP_DATA_FACTORY (factory)); container = gimp_data_factory_get_container (GIMP_DATA_FACTORY (factory));
@ -775,17 +783,17 @@ gimp_font_factory_load_names (GimpFontFactory *factory,
FC_INDEX, FC_INDEX,
FC_FONTVERSION, FC_FONTVERSION,
NULL); NULL);
g_return_if_fail (os); g_return_val_if_fail (os, -1);
pat = FcPatternCreate (); pat = FcPatternCreate ();
if (! pat) if (! pat)
{ {
FcObjectSetDestroy (os); FcObjectSetDestroy (os);
g_critical ("%s: FcPatternCreate() returned NULL.", G_STRFUNC); g_critical ("%s: FcPatternCreate() returned NULL.", G_STRFUNC);
return; return -1;
} }
if (FT_Init_FreeType(&ft)) if (FT_Init_FreeType (&ft))
{ {
g_critical ("%s: FreeType Initialization Failed.", G_STRFUNC); g_critical ("%s: FreeType Initialization Failed.", G_STRFUNC);
return -1; return -1;
@ -796,7 +804,7 @@ gimp_font_factory_load_names (GimpFontFactory *factory,
FcPatternDestroy (pat); FcPatternDestroy (pat);
FcObjectSetDestroy (os); FcObjectSetDestroy (os);
g_return_if_fail (fontset); g_return_val_if_fail (fontset, -1);
xml_configs_list = NULL; xml_configs_list = NULL;
xml = g_string_new (NULL); xml = g_string_new (NULL);
@ -805,6 +813,8 @@ gimp_font_factory_load_names (GimpFontFactory *factory,
xml_bold_italic_variant_and_global = g_string_new ("<fontconfig>"); xml_bold_italic_variant_and_global = g_string_new ("<fontconfig>");
ignored_fonts = g_string_new (NULL); ignored_fonts = g_string_new (NULL);
#define MAX_NUM_FONTS_PER_CONFIG 1000
for (i = 0; i < fontset->nfont; i++) for (i = 0; i < fontset->nfont; i++)
{ {
PangoFontDescription *pfd; PangoFontDescription *pfd;
@ -836,7 +846,7 @@ gimp_font_factory_load_names (GimpFontFactory *factory,
continue; continue;
} }
if (FT_New_Face(ft, file, 0, &face)) if (FT_New_Face (ft, file, 0, &face))
{ {
g_string_append_printf (ignored_fonts, "- %s (Failed To Create A FreeType Face)\n", file); g_string_append_printf (ignored_fonts, "- %s (Failed To Create A FreeType Face)\n", file);
n_ignored++; n_ignored++;
@ -852,8 +862,7 @@ gimp_font_factory_load_names (GimpFontFactory *factory,
*/ */
if (face->face_flags & FT_FACE_FLAG_SFNT) if (face->face_flags & FT_FACE_FLAG_SFNT)
{ {
/* If this is an SFNT wrapper, try to sniff the SFNT tag which is the /* If this is an SFNT wrapper, read the first 4 bytes to see if it is a WOFF[2] font. */
* first 4 bytes, to see if it is a WOFF or WOFF2 wrapper. */
char buf[4] = {0}; char buf[4] = {0};
int fd = g_open ((gchar *) file, O_RDONLY, 0); int fd = g_open ((gchar *) file, O_RDONLY, 0);
@ -861,7 +870,7 @@ gimp_font_factory_load_names (GimpFontFactory *factory,
g_close (fd, NULL); g_close (fd, NULL);
FT_Done_Face (face); FT_Done_Face (face);
if (buf[0] == 'w' && buf[1] == 'O' && buf[2] == 'F') if (buf[0] == 'w' && buf[1] == 'O' && buf[2] == 'F' && (buf[3] == 'F' || buf[3] == '2'))
{ {
g_string_append_printf (ignored_fonts, "- %s (WOFF[2] font)\n", file); g_string_append_printf (ignored_fonts, "- %s (WOFF[2] font)\n", file);
n_ignored++; n_ignored++;
@ -914,8 +923,31 @@ gimp_font_factory_load_names (GimpFontFactory *factory,
newname = g_strdup_printf ("gimpfont%i", i); newname = g_strdup_printf ("gimpfont%i", i);
xml = g_string_append (xml, "<match>"); if (num_fonts_in_current_config == MAX_NUM_FONTS_PER_CONFIG)
{
xml_bold_italic_variant_and_global = g_string_append (xml_bold_italic_variant_and_global, xml_italic_variant->str);
xml_bold_italic_variant_and_global = g_string_append (xml_bold_italic_variant_and_global, xml_bold_variant->str);
xml_bold_italic_variant_and_global = g_string_append (xml_bold_italic_variant_and_global, xml->str);
xml_bold_italic_variant_and_global = g_string_append (xml_bold_italic_variant_and_global, "</fontconfig>");
xml_configs_list = g_slist_append (xml_configs_list, xml_bold_italic_variant_and_global->str);
FcConfigParseAndLoadFromMemory (FcConfigGetCurrent (), (const FcChar8 *) xml_bold_italic_variant_and_global->str, FcTrue);
g_string_free (xml, TRUE);
g_string_free (xml_italic_variant, TRUE);
g_string_free (xml_bold_variant, TRUE);
g_string_free (xml_bold_italic_variant_and_global, FALSE);
xml = g_string_new (NULL);
xml_italic_variant = g_string_new (NULL);
xml_bold_variant = g_string_new (NULL);
xml_bold_italic_variant_and_global = g_string_new ("<fontconfig>");
num_fonts_in_current_config = 0;
}
xml = g_string_append (xml, "<match>");
/*We can't use faux bold (sometimes real bold) unless it is specified in fontconfig*/ /*We can't use faux bold (sometimes real bold) unless it is specified in fontconfig*/
xml_bold_variant = g_string_append (xml_bold_variant, "<match>"); xml_bold_variant = g_string_append (xml_bold_variant, "<match>");
xml_italic_variant = g_string_append (xml_italic_variant, "<match>"); xml_italic_variant = g_string_append (xml_italic_variant, "<match>");
@ -1072,34 +1104,43 @@ gimp_font_factory_load_names (GimpFontFactory *factory,
if (display_name != NULL) if (display_name != NULL)
{ {
gimp_font_factory_add_font (container, context, pfd, display_name, (const gchar *) file, font_info); gimp_font_factory_add_font (container, pfd, display_name, (const gchar *) file, font_info);
g_free (display_name); g_free (display_name);
} }
else else
{ {
gimp_font_factory_add_font (container, context, pfd, fullname, (const gchar *) file, font_info); gimp_font_factory_add_font (container, pfd, fullname, (const gchar *) file, font_info);
} }
pango_font_description_free (pattern_pfd); pango_font_description_free (pattern_pfd);
g_free (pattern_pfd_desc); g_free (pattern_pfd_desc);
pango_font_description_free (pfd); pango_font_description_free (pfd);
g_free (newname); g_free (newname);
num_fonts_in_current_config++;
} }
g_string_append (xml_bold_italic_variant_and_global, xml_italic_variant->str); #undef MAX_NUM_FONTS_PER_CONFIG
g_string_append (xml_bold_italic_variant_and_global, xml_bold_variant->str);
g_string_append (xml_bold_italic_variant_and_global, xml->str);
g_string_append (xml_bold_italic_variant_and_global, "</fontconfig>");
g_free (factory->fonts_renaming_config); if (num_fonts_in_current_config > 0)
{
xml_bold_italic_variant_and_global = g_string_append (xml_bold_italic_variant_and_global, xml_italic_variant->str);
xml_bold_italic_variant_and_global = g_string_append (xml_bold_italic_variant_and_global, xml_bold_variant->str);
xml_bold_italic_variant_and_global = g_string_append (xml_bold_italic_variant_and_global, xml->str);
xml_bold_italic_variant_and_global = g_string_append (xml_bold_italic_variant_and_global, "</fontconfig>");
xml_configs_list = g_slist_append (xml_configs_list, xml_bold_italic_variant_and_global->str);
FcConfigParseAndLoadFromMemory (FcConfigGetCurrent (), (const FcChar8 *) xml_bold_italic_variant_and_global->str, FcTrue); FcConfigParseAndLoadFromMemory (FcConfigGetCurrent (), (const FcChar8 *) xml_bold_italic_variant_and_global->str, FcTrue);
factory->fonts_renaming_config = xml_bold_italic_variant_and_global->str; g_string_free (xml, TRUE);
g_string_free (xml_italic_variant, TRUE);
g_string_free (xml_bold_variant, TRUE);
g_string_free (xml_bold_italic_variant_and_global, FALSE);
}
/* only create aliases if there is at least one font available */ g_slist_free_full (GET_PRIVATE (factory)->fonts_renaming_config, (GDestroyNotify) g_free);
if (fontset->nfont > 0)
gimp_font_factory_load_aliases (container, context); GET_PRIVATE (factory)->fonts_renaming_config = xml_configs_list;
if (n_ignored > 0) if (n_ignored > 0)
{ {
@ -1111,11 +1152,11 @@ gimp_font_factory_load_names (GimpFontFactory *factory,
#endif #endif
} }
n_loaded_fonts = fontset->nfont - n_ignored;
g_string_free (ignored_fonts, TRUE); g_string_free (ignored_fonts, TRUE);
g_string_free (xml, TRUE); FT_Done_FreeType (ft);
g_string_free (xml_italic_variant, TRUE);
g_string_free (xml_bold_variant, TRUE);
g_string_free (xml_bold_italic_variant_and_global, FALSE);
FT_Done_FreeType(ft);
FcFontSetDestroy (fontset); FcFontSetDestroy (fontset);
return n_loaded_fonts;
} }

View file

@ -22,6 +22,7 @@
#define __GIMP_FONT_FACTORY_H__ #define __GIMP_FONT_FACTORY_H__
#include <pango/pango.h>
#include "core/gimpdatafactory.h" #include "core/gimpdatafactory.h"
@ -40,10 +41,6 @@ struct _GimpFontFactory
{ {
GimpDataFactory parent_instance; GimpDataFactory parent_instance;
gchar *fonts_renaming_config;
gchar *conf;
gchar *sysconf;
GimpFontFactoryPrivate *priv; GimpFontFactoryPrivate *priv;
}; };
@ -61,7 +58,8 @@ GList * gimp_font_factory_get_custom_fonts_dirs (GimpFontFactory
void gimp_font_factory_get_custom_config_path (GimpFontFactory *factory, void gimp_font_factory_get_custom_config_path (GimpFontFactory *factory,
gchar **conf, gchar **conf,
gchar **sysconf); gchar **sysconf);
gchar * gimp_font_factory_get_fonts_renaming_config (GimpFontFactory *factory); GSList * gimp_font_factory_get_fonts_renaming_config (GimpFontFactory *factory);
PangoContext * gimp_font_factory_get_pango_context (GimpFontFactory *factory);
#endif /* __GIMP_FONT_FACTORY_H__ */ #endif /* __GIMP_FONT_FACTORY_H__ */

View file

@ -63,7 +63,7 @@ gimp_font_get_pango_font_description (GimpFont *font)
{ {
gchar *config; gchar *config;
gchar *sysconfig; gchar *sysconfig;
gchar *fonts_renaming_config; gchar **fonts_renaming_config;
gchar **dirs; gchar **dirs;
FcConfigSetCurrent (FcInitLoadConfig ()); FcConfigSetCurrent (FcInitLoadConfig ());
@ -82,11 +82,11 @@ gimp_font_get_pango_font_description (GimpFont *font)
if (dirs[i]) if (dirs[i])
FcConfigAppFontAddDir (FcConfigGetCurrent (), (const FcChar8 *)dirs[i]); FcConfigAppFontAddDir (FcConfigGetCurrent (), (const FcChar8 *)dirs[i]);
FcConfigParseAndLoadFromMemory (FcConfigGetCurrent (), for (int i = 0; fonts_renaming_config[i] != NULL; ++i)
(const FcChar8 *) fonts_renaming_config, if (fonts_renaming_config[i])
FcTrue); FcConfigParseAndLoadFromMemory (FcConfigGetCurrent (), (const FcChar8 *)fonts_renaming_config[i], FcTrue);
g_free (fonts_renaming_config); g_strfreev (fonts_renaming_config);
g_free (sysconfig); g_free (sysconfig);
g_free (config); g_free (config);
g_strfreev (dirs); g_strfreev (dirs);

View file

@ -72,7 +72,7 @@ gimp_fonts_refresh (void)
/** /**
* _gimp_fonts_get_custom_configs: * _gimp_fonts_get_custom_configs:
* @sysconfig: (out) (transfer full): sysconfig path. * @sysconfig: (out) (transfer full): sysconfig path.
* @renaming_config: (out) (transfer full): fonts renaming config. * @renaming_config: (out) (array zero-terminated=1) (transfer full): fonts renaming config.
* @dirs: (out) (array zero-terminated=1) (transfer full): custom fonts directories. * @dirs: (out) (array zero-terminated=1) (transfer full): custom fonts directories.
* *
* Retrieve custom configs. * Retrieve custom configs.
@ -87,7 +87,7 @@ gimp_fonts_refresh (void)
**/ **/
gchar * gchar *
_gimp_fonts_get_custom_configs (gchar **sysconfig, _gimp_fonts_get_custom_configs (gchar **sysconfig,
gchar **renaming_config, gchar ***renaming_config,
gchar ***dirs) gchar ***dirs)
{ {
GimpValueArray *args; GimpValueArray *args;
@ -106,7 +106,7 @@ _gimp_fonts_get_custom_configs (gchar **sysconfig,
{ {
config = GIMP_VALUES_DUP_STRING (return_vals, 1); config = GIMP_VALUES_DUP_STRING (return_vals, 1);
*sysconfig = GIMP_VALUES_DUP_STRING (return_vals, 2); *sysconfig = GIMP_VALUES_DUP_STRING (return_vals, 2);
*renaming_config = GIMP_VALUES_DUP_STRING (return_vals, 3); *renaming_config = GIMP_VALUES_DUP_STRV (return_vals, 3);
*dirs = GIMP_VALUES_DUP_STRV (return_vals, 4); *dirs = GIMP_VALUES_DUP_STRV (return_vals, 4);
} }

View file

@ -34,7 +34,7 @@ G_BEGIN_DECLS
gboolean gimp_fonts_refresh (void); gboolean gimp_fonts_refresh (void);
G_GNUC_INTERNAL gchar* _gimp_fonts_get_custom_configs (gchar **sysconfig, G_GNUC_INTERNAL gchar* _gimp_fonts_get_custom_configs (gchar **sysconfig,
gchar **renaming_config, gchar ***renaming_config,
gchar ***dirs); gchar ***dirs);
GimpFont** gimp_fonts_get_list (const gchar *filter); GimpFont** gimp_fonts_get_list (const gchar *filter);

View file

@ -137,7 +137,7 @@ HELP
desc => 'config path' }, desc => 'config path' },
{ name => 'sysconfig', type => 'string', { name => 'sysconfig', type => 'string',
desc => 'sysconfig path' }, desc => 'sysconfig path' },
{ name => 'renaming_config', type => 'string', { name => 'renaming_config', type => 'strv',
desc => 'fonts renaming config' }, desc => 'fonts renaming config' },
{ name => 'dirs', type => 'strv', { name => 'dirs', type => 'strv',
desc => 'custom fonts directories' } desc => 'custom fonts directories' }
@ -153,6 +153,7 @@ HELP
if (success) if (success)
{ {
GList *list = gimp_font_factory_get_custom_fonts_dirs (GIMP_FONT_FACTORY (gimp->font_factory)); GList *list = gimp_font_factory_get_custom_fonts_dirs (GIMP_FONT_FACTORY (gimp->font_factory));
GSList *fonts_renaming_config = gimp_font_factory_get_fonts_renaming_config (GIMP_FONT_FACTORY (gimp->font_factory));
guint length = g_list_length (list); guint length = g_list_length (list);
gint i; gint i;
@ -163,14 +164,19 @@ HELP
config = g_strdup (config); config = g_strdup (config);
sysconfig = g_strdup (sysconfig); sysconfig = g_strdup (sysconfig);
renaming_config = g_strdup (gimp_font_factory_get_fonts_renaming_config (GIMP_FONT_FACTORY (gimp->font_factory)));
dirs = g_new0 (gchar *, length + 1); dirs = g_new0 (gchar *, length + 1);
for (i = 0; list; list = g_list_next (list), i++) for (i = 0; list; list = g_list_next (list), i++)
dirs[i] = g_file_get_path (list->data); dirs[i] = g_file_get_path (list->data);
g_list_free_full (list, (GDestroyNotify) g_object_unref); g_list_free_full (list, (GDestroyNotify) g_object_unref);
length = g_slist_length (fonts_renaming_config);
renaming_config = g_new0 (gchar *, length + 1);
for (i = 0; fonts_renaming_config; fonts_renaming_config = g_slist_next (fonts_renaming_config), i++)
renaming_config[i] = g_strdup (fonts_renaming_config->data);
} }
} }
CODE CODE