fontconfig: Branch 'main' - 8 commits
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Thu May 22 12:16:37 UTC 2025
conf.d/50-user.conf | 3 -
doc/fclangset.fncs | 13 ++++
doc/fcpattern.fncs | 25 +++++++++
fc-match/fc-match.c | 2
fc-pattern/fc-pattern.c | 2
fontconfig/fontconfig.h | 7 ++
src/fccache.c | 14 +++--
src/fccfg.c | 46 ++++++++++++++---
src/fcdefault.c | 124 +++++++++++++++++++++++++++--------------------
src/fcinit.c | 3 -
src/fcint.h | 19 ++++++-
src/fclist.c | 2
src/fcobjs.c | 23 ++++++++
src/fcxml.c | 116 +++----------------------------------------
test/meson.build | 1
test/test-bz106618.c | 4 -
test/test-bz106632.c | 1
test/test-conf.c | 2
test/test-crbug1004254.c | 2
test/test-mt-fccfg.c | 74 ++++++++++++++++++++++++++++
test/test-pthread.c | 2
21 files changed, 295 insertions(+), 190 deletions(-)
New commits:
commit 61e603f2a5096f7557f0f41c20d250770e893851
Merge: 1c63ed3 dbead4c
Author: Akira TAGOH <akira at tagoh.org>
Date: Thu May 22 12:16:34 2025 +0000
Merge branch 'issues/448' into 'main'
Fix some memory leaks around FcFini()
Closes #448
See merge request fontconfig/fontconfig!410
commit dbead4c954f6d2146cfb23542aa40183165456fb
Author: Akira TAGOH <akira at tagoh.org>
Date: Thu May 22 20:32:00 2025 +0900
Increase a reference count for default FcConfig instance with FcInit()
This allows us to decrease a reference count with FcFini
without explicit FcConfigReference.
FcFini() needs to be brought up as many as a number of call
of FcInit().
Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/448
Changelog: changed
diff --git a/src/fccfg.c b/src/fccfg.c
index 9d94b7a..0d3d573 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -117,7 +117,13 @@ FcDestroyAsRuleSet (void *data)
FcBool
FcConfigInit (void)
{
- return FcConfigEnsure() ? FcTrue : FcFalse;
+ FcBool is_new = !!(_fcConfig == NULL);
+ FcBool ret;
+
+ ret = FcConfigEnsure() ? FcTrue : FcFalse;
+ if (ret && !is_new)
+ FcConfigReference (_fcConfig);
+ return ret;
}
void
diff --git a/test/test-mt-fccfg.c b/test/test-mt-fccfg.c
index da1569a..24ad758 100644
--- a/test/test-mt-fccfg.c
+++ b/test/test-mt-fccfg.c
@@ -10,8 +10,7 @@
#define NTHR 100
struct thr_arg_s {
- int thr_num;
- FcConfig *config;
+ int thr_num;
};
static void *
@@ -20,6 +19,7 @@ run_test_in_thread (void *arg)
FcPattern *pat, *m;
FcResult result;
+ FcInit();
pat = FcNameParse ((const FcChar8 *)"sans-serif");
FcConfigSubstitute (NULL, pat, FcMatchPattern);
FcConfigSetDefaultSubstitute (NULL, pat);
@@ -43,7 +43,6 @@ test (void)
for (i = 0; i < NTHR; i++) {
int result;
thr_args[i].thr_num = i;
- thr_args[i].config = FcConfigReference (c1);
result = pthread_create (&threads[i], NULL, run_test_in_thread, (void *)&thr_args[i]);
if (result != 0) {
commit 76ba00801447a4c50bba3a3539402aa450cffd50
Author: Akira TAGOH <akira at tagoh.org>
Date: Thu May 22 15:43:30 2025 +0900
Free the mutex object only when there are no references to the default FcConfig instance
Changelog: changed
diff --git a/src/fccfg.c b/src/fccfg.c
index 0d52101..9d94b7a 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -123,10 +123,21 @@ FcConfigInit (void)
void
FcConfigFini (void)
{
- FcConfig *cfg = fc_atomic_ptr_get (&_fcConfig);
- if (cfg && fc_atomic_ptr_cmpexch (&_fcConfig, cfg, NULL))
- FcConfigDestroy (cfg);
- free_lock();
+ FcConfig *cfg;
+
+retry:
+ cfg = fc_atomic_ptr_get (&_fcConfig);
+ if (cfg) {
+ if (cfg->ref.count > 1)
+ FcConfigDestroy (cfg);
+ else {
+ if (fc_atomic_ptr_cmpexch (&_fcConfig, cfg, NULL))
+ FcConfigDestroy (cfg);
+ else
+ goto retry;
+ free_lock();
+ }
+ }
}
FcConfig *
diff --git a/test/meson.build b/test/meson.build
index bd958a6..05a6932 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -34,6 +34,7 @@ if host_machine.system() != 'windows'
tests_not_parallel += [
# FIXME: this needs NotoSans-hinted.zip font downloaded and unpacked into test build directory! see run-test.sh
['test-crbug1004254.c', {'dependencies': dependency('threads')}], # for pthread
+ ['test-mt-fccfg.c', {'include_directories': include_directories('../src'), 'dependencies': dependency('threads')}],
]
if get_option('default_library') == 'static'
diff --git a/test/test-mt-fccfg.c b/test/test-mt-fccfg.c
new file mode 100644
index 0000000..da1569a
--- /dev/null
+++ b/test/test-mt-fccfg.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 2025 fontconfig Authors */
+/* SPDX-License-Identifier: HPND */
+#include <fontconfig/fontconfig.h>
+
+#include <stdio.h>
+#define __USE_XOPEN
+#include <pthread.h>
+#include <stdlib.h>
+
+#define NTHR 100
+
+struct thr_arg_s {
+ int thr_num;
+ FcConfig *config;
+};
+
+static void *
+run_test_in_thread (void *arg)
+{
+ FcPattern *pat, *m;
+ FcResult result;
+
+ pat = FcNameParse ((const FcChar8 *)"sans-serif");
+ FcConfigSubstitute (NULL, pat, FcMatchPattern);
+ FcConfigSetDefaultSubstitute (NULL, pat);
+ m = FcFontMatch (NULL, pat, &result);
+ FcPatternDestroy (pat);
+ FcPatternDestroy (m);
+ FcFini();
+
+ return NULL;
+}
+
+int
+test (void)
+{
+ pthread_t threads[NTHR];
+ struct thr_arg_s thr_args[NTHR];
+ FcConfig *c1, *c2, *c3;
+ int i, j;
+
+ c1 = FcConfigGetCurrent();
+ for (i = 0; i < NTHR; i++) {
+ int result;
+ thr_args[i].thr_num = i;
+ thr_args[i].config = FcConfigReference (c1);
+
+ result = pthread_create (&threads[i], NULL, run_test_in_thread, (void *)&thr_args[i]);
+ if (result != 0) {
+ fprintf (stderr, "Cannot create thread %d\n", i);
+ break;
+ }
+ }
+ for (j = 0; j < i; j++) {
+ pthread_join (threads[j], NULL);
+ }
+ FcFini();
+ c3 = FcConfigCreate(); /* To avoid allocation at the same place */
+ c2 = FcConfigGetCurrent();
+ FcConfigDestroy (c3);
+ printf ("cur: %p\n", c2);
+ if (c1 == c2)
+ return 1;
+ /* To make visible if we have any references */
+ putenv ("FC_DEBUG=16");
+ FcFini();
+
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ return test();
+}
commit e0f39a6f027877fd917ab993d89d2cfc17dbcc8b
Author: Akira TAGOH <akira at tagoh.org>
Date: Thu May 22 15:18:59 2025 +0900
Free the mutex object only when all cache objects isn't referenced
Changelog: changed
diff --git a/src/fccache.c b/src/fccache.c
index f3e4320..c63976e 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -754,18 +754,20 @@ FcCacheAllocate (FcCache *cache, size_t len)
void
FcCacheFini (void)
{
- int i;
+ int i;
+ FcBool res = FcTrue;
- if (FcDebug() & FC_DBG_CACHE) {
- for (i = 0; i < FC_CACHE_MAX_LEVEL; i++) {
- if (fcCacheChains[i] != NULL) {
+ for (i = 0; i < FC_CACHE_MAX_LEVEL; i++) {
+ if (fcCacheChains[i] != NULL) {
+ res = FcFalse;
+ if (FcDebug() & FC_DBG_CACHE) {
FcCacheSkip *s = fcCacheChains[i];
fprintf (stderr, "Fontconfig error: not freed %p (dir: %s, refcount %" FC_ATOMIC_INT_FORMAT ")\n", s->cache, FcCacheDir (s->cache), s->ref.count);
}
}
}
-
- free_lock();
+ if (res)
+ free_lock();
}
static FcBool
commit dbbb46207e243d07d2e4c4d35547fc7521c9c62f
Author: Akira TAGOH <akira at tagoh.org>
Date: Fri May 16 19:45:41 2025 +0900
Drop FcObjectFini() from FcFini() to fix memory leaks
Initialization around FcObject has been integrated into
FcConfig instance. they are freed once all FcConfig instances
has been destroyed. So we don't need to call FcObjectFini()
from FcFini() anymore.
Changelog: fixed
diff --git a/src/fccfg.c b/src/fccfg.c
index 0756698..0d52101 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -210,6 +210,7 @@ FcConfigCreate (void)
config->prefer_app_fonts = FcFalse;
FcRefInit (&config->ref, 1);
+ FcObjectInit();
return config;
@@ -356,6 +357,7 @@ FcConfigDestroy (FcConfig *config)
if (FcRefDec (&config->ref) != 1)
return;
+ FcObjectFini();
(void)fc_atomic_ptr_cmpexch (&_fcConfig, config, NULL);
FcStrSetDestroy (config->configDirs);
diff --git a/src/fcinit.c b/src/fcinit.c
index 33e1d6e..9c66515 100644
--- a/src/fcinit.c
+++ b/src/fcinit.c
@@ -214,7 +214,6 @@ void
FcFini (void)
{
FcConfigFini();
- FcObjectFini();
FcCacheFini();
}
diff --git a/src/fcint.h b/src/fcint.h
index 2dd0bf5..67a1604 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -1413,6 +1413,8 @@ FcPrivate FcChar8 *
FcStrSerialize (FcSerialize *serialize, const FcChar8 *str);
/* fcobjs.c */
+FcPrivate void
+FcObjectInit (void);
FcPrivate void
FcObjectFini (void);
diff --git a/src/fcobjs.c b/src/fcobjs.c
index e21d7a3..c7bcb0c 100644
--- a/src/fcobjs.c
+++ b/src/fcobjs.c
@@ -43,6 +43,13 @@ struct FcObjectOtherTypeInfo {
FcObjectType object;
FcObject id;
} *other_types;
+static FcRef obj_ref = { .count = 0 };
+
+void
+FcObjectInit (void)
+{
+ FcRefInc (&obj_ref);
+}
void
FcObjectFini (void)
@@ -50,11 +57,17 @@ FcObjectFini (void)
struct FcObjectOtherTypeInfo *ots, *ot;
retry:
+ if (obj_ref.count < 1)
+ fprintf (stderr, "Fontconfig warning: too many caller of FcObjectFini()\n");
+ if (obj_ref.count >= 1 && FcRefDec (&obj_ref) != 1)
+ return;
ots = fc_atomic_ptr_get (&other_types);
if (!ots)
return;
- if (!fc_atomic_ptr_cmpexch (&other_types, ots, NULL))
+ if (!fc_atomic_ptr_cmpexch (&other_types, ots, NULL)) {
+ FcRefInc (&obj_ref);
goto retry;
+ }
while (ots) {
ot = ots->next;
@@ -69,9 +82,17 @@ static FcObjectType *
_FcObjectLookupOtherTypeByName (const char *str, FcObject *id)
{
struct FcObjectOtherTypeInfo *ots, *ot;
+ static FcBool warn = FcFalse;
retry:
ots = fc_atomic_ptr_get (&other_types);
+ if (obj_ref.count < 1) {
+ if (!warn) {
+ fprintf (stderr, "Fontconfig warning: using without calling FcInit()\n");
+ warn = FcTrue;
+ }
+ FcObjectInit();
+ }
for (ot = ots; ot; ot = ot->next)
if (0 == strcmp (ot->object.object, str))
diff --git a/test/test-bz106632.c b/test/test-bz106632.c
index 3c56cb7..1e18d5c 100644
--- a/test/test-bz106632.c
+++ b/test/test-bz106632.c
@@ -305,6 +305,7 @@ bail:
FcStrFree (fontdir);
if (cachedir)
FcStrFree (cachedir);
+ FcFini();
return ret;
}
commit aaa8aca60993ae635dba4ed9fa8bd06ad0b52128
Author: Akira TAGOH <akira at tagoh.org>
Date: Fri May 16 17:56:33 2025 +0900
Drop the configuration path migration code
We have added a code to encourage users to migrate
user configuration file/directory to XDG-based one over
10 years ago.
I think it served a function enough and we don't need
to keep it furthermore for that purpose.
So let's just drop them.
Changelog: changed
diff --git a/conf.d/50-user.conf b/conf.d/50-user.conf
index d019f4d..f38d651 100644
--- a/conf.d/50-user.conf
+++ b/conf.d/50-user.conf
@@ -10,7 +10,4 @@
-->
<include ignore_missing="yes" prefix="xdg">fontconfig/conf.d</include>
<include ignore_missing="yes" prefix="xdg">fontconfig/fonts.conf</include>
- <!-- the following elements will be removed in the future -->
- <include ignore_missing="yes" deprecated="yes">~/.fonts.conf.d</include>
- <include ignore_missing="yes" deprecated="yes">~/.fonts.conf</include>
</fontconfig>
diff --git a/src/fcinit.c b/src/fcinit.c
index 361f80d..33e1d6e 100644
--- a/src/fcinit.c
+++ b/src/fcinit.c
@@ -214,7 +214,6 @@ void
FcFini (void)
{
FcConfigFini();
- FcConfigPathFini();
FcObjectFini();
FcCacheFini();
}
diff --git a/src/fcxml.c b/src/fcxml.c
index 328e109..a84fdcd 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -66,9 +66,6 @@ static void
_ensureWin32GettersReady ();
#endif
-static FcChar8 *__fc_userdir = NULL;
-static FcChar8 *__fc_userconf = NULL;
-
static void
FcExprDestroy (FcExpr *e);
static FcBool
@@ -2309,37 +2306,15 @@ bail:
FcStrFree (data);
}
-void
-FcConfigPathFini (void)
-{
- FcChar8 *s;
-
-retry_dir:
- s = fc_atomic_ptr_get (&__fc_userdir);
- if (!fc_atomic_ptr_cmpexch (&__fc_userdir, s, NULL))
- goto retry_dir;
- free (s);
-
-retry_conf:
- s = fc_atomic_ptr_get (&__fc_userconf);
- if (!fc_atomic_ptr_cmpexch (&__fc_userconf, s, NULL))
- goto retry_conf;
- free (s);
-}
-
static void
FcParseInclude (FcConfigParse *parse)
{
FcChar8 *s;
const FcChar8 *attr;
FcBool ignore_missing = FcFalse;
-#ifndef _WIN32
- FcBool deprecated = FcFalse;
-#endif
- FcChar8 *prefix = NULL, *p;
- FcChar8 *userdir = NULL, *userconf = NULL;
- FcRuleSet *ruleset;
- FcMatchKind k;
+ FcChar8 *prefix = NULL, *p;
+ FcRuleSet *ruleset;
+ FcMatchKind k;
s = FcStrBufDoneStatic (&parse->pstack->str);
if (!s) {
@@ -2349,11 +2324,12 @@ FcParseInclude (FcConfigParse *parse)
attr = FcConfigGetAttribute (parse, "ignore_missing");
if (attr && FcConfigLexBool (parse, (FcChar8 *)attr) == FcTrue)
ignore_missing = FcTrue;
+ /* deprecated attribute has ever been used to mark
+ * old configuration path as deprecated.
+ * We don't have any code for it but just keep it for
+ * backward compatibility.
+ */
attr = FcConfigGetAttribute (parse, "deprecated");
-#ifndef _WIN32
- if (attr && FcConfigLexBool (parse, (FcChar8 *)attr) == FcTrue)
- deprecated = FcTrue;
-#endif
attr = FcConfigGetAttribute (parse, "prefix");
if (attr && FcStrCmp (attr, (const FcChar8 *)"xdg") == 0) {
prefix = FcConfigXdgConfigHome();
@@ -2366,7 +2342,6 @@ FcParseInclude (FcConfigParse *parse)
if (prefix) {
size_t plen = strlen ((const char *)prefix);
size_t dlen = strlen ((const char *)s);
- FcChar8 *u;
p = realloc (prefix, plen + 1 + dlen + 1);
if (!p) {
@@ -2378,37 +2353,6 @@ FcParseInclude (FcConfigParse *parse)
memcpy (&prefix[plen + 1], s, dlen);
prefix[plen + 1 + dlen] = 0;
s = prefix;
- if (FcFileIsDir (s)) {
- userdir:
- userdir = fc_atomic_ptr_get (&__fc_userdir);
- if (!userdir) {
- u = FcStrdup (s);
- if (!fc_atomic_ptr_cmpexch (&__fc_userdir, userdir, u)) {
- free (u);
- goto userdir;
- }
- userdir = u;
- }
- } else if (FcFileIsFile (s)) {
- userconf:
- userconf = fc_atomic_ptr_get (&__fc_userconf);
- if (!userconf) {
- u = FcStrdup (s);
- if (!fc_atomic_ptr_cmpexch (&__fc_userconf, userconf, u)) {
- free (u);
- goto userconf;
- }
- userconf = u;
- }
- } else {
- /* No config dir nor file on the XDG directory spec compliant place
- * so need to guess what it is supposed to be.
- */
- if (FcStrStr (s, (const FcChar8 *)"conf.d") != NULL)
- goto userdir;
- else
- goto userconf;
- }
}
/* flush the ruleset into the queue */
ruleset = parse->ruleset;
@@ -2428,50 +2372,6 @@ FcParseInclude (FcConfigParse *parse)
FcRuleSetDestroy (ruleset);
if (!_FcConfigParse (parse->config, s, !ignore_missing, !parse->scanOnly))
parse->error = FcTrue;
-#ifndef _WIN32
- else {
- FcChar8 *filename;
- static FcBool warn_conf = FcFalse, warn_confd = FcFalse;
-
- filename = FcConfigGetFilename (parse->config, s);
- if (deprecated == FcTrue &&
- filename != NULL &&
- userdir != NULL &&
- !FcFileIsLink (filename)) {
- if (FcFileIsDir (filename)) {
- FcChar8 *parent = FcStrDirname (userdir);
-
- if (!FcFileIsDir (parent))
- FcMakeDirectory (parent);
- FcStrFree (parent);
- if (FcFileIsDir (userdir) ||
- rename ((const char *)filename, (const char *)userdir) != 0 ||
- symlink ((const char *)userdir, (const char *)filename) != 0) {
- if (!warn_confd) {
- FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userdir);
- warn_confd = FcTrue;
- }
- }
- } else {
- FcChar8 *parent = FcStrDirname (userconf);
-
- if (!FcFileIsDir (parent))
- FcMakeDirectory (parent);
- FcStrFree (parent);
- if (FcFileIsFile (userconf) ||
- rename ((const char *)filename, (const char *)userconf) != 0 ||
- symlink ((const char *)userconf, (const char *)filename) != 0) {
- if (!warn_conf) {
- FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userconf);
- warn_conf = FcTrue;
- }
- }
- }
- }
- if (filename)
- FcStrFree (filename);
- }
-#endif
FcStrBufDestroy (&parse->pstack->str);
bail:
commit d547d2cc11a7f38f5a8609a49aa8abb7cb46357b
Author: Akira TAGOH <akira at tagoh.org>
Date: Thu May 8 16:20:21 2025 +0900
test: do not free FcFontSet From FcConfigGetFonts
diff --git a/test/test-bz106618.c b/test/test-bz106618.c
index 575d9c8..14e7e87 100644
--- a/test/test-bz106618.c
+++ b/test/test-bz106618.c
@@ -28,7 +28,7 @@
int
main (int argc, char **argv)
{
- FcFontSet *fs = FcConfigGetFonts (NULL, FcSetSystem);
+ const FcFontSet *fs = FcConfigGetFonts (NULL, FcSetSystem);
int i;
if (!fs)
@@ -41,7 +41,7 @@ main (int argc, char **argv)
return 1;
printf ("%s\n", file);
}
- FcFontSetDestroy (fs);
+ FcFini();
return 0;
}
commit 90a84c477c4006b5539973a5487f28b3ed09711d
Author: Akira TAGOH <akira at tagoh.org>
Date: Wed May 7 16:08:50 2025 +0900
Drop FcDefaultFini() from FcFini() to fix memory leaks
All relevant variables has been moved into FcConfig instance and
to deal with this change, new APIs, FcConfigGetDefaultLangs(),
FcConfigSetDefaultSubstitute() has been added. FcGetDefaultLangs()
and FcDefaultSubstitute() still works and keep available for backward
compatibility though, they are referring the default FcConfig instance
from FcConfigGetCurrent() from now on.
If a code creates multiple FcConfig instances, this change may affects.
Changelog: changed
diff --git a/doc/fclangset.fncs b/doc/fclangset.fncs
index 401abc0..2839a53 100644
--- a/doc/fclangset.fncs
+++ b/doc/fclangset.fncs
@@ -164,9 +164,22 @@ has no matching language, this function returns FcLangDifferentLang.
Returns a string set of the default languages according to the environment variables on the system.
This function looks for them in order of FC_LANG, LC_ALL, LC_CTYPE and LANG then.
If there are no valid values in those environment variables, "en" will be set as fallback.
+ </para><para>
+This function has been replaced by <function>FcConfigGetDefaultLangs</function> and will be deprecated.
@SINCE@ 2.9.91
@@
+ at RET@ FcStrSet *
+ at FUNC@ FcConfigGetDefaultLangs
+ at TYPE1@ FcConfig * @ARG1@ config
+ at PURPOSE@ Get the default languages list
+ at DESC@
+Returns a string set of the default languages according to the environment variables on the system.
+This function looks for them in order of FC_LANG, LC_ALL, LC_CTYPE and LANG then.
+If there are no valid values in those environment variables, "en" will be set as fallback.
+ at SINCE@ 2.17.0
+@@
+
@RET@ FcStrSet *
@FUNC@ FcLangSetGetLangs
@TYPE1@ const FcLangSet * @ARG1@ ls
diff --git a/doc/fcpattern.fncs b/doc/fcpattern.fncs
index d32f3dc..294562a 100644
--- a/doc/fcpattern.fncs
+++ b/doc/fcpattern.fncs
@@ -521,6 +521,31 @@ Patterns without a specified pixel size are given one computed from any
specified point size (default 12), dpi (default 75) and scale (default 1).
</para></listitem>
</itemizedlist>
+ </para><para>
+This function has been replaced by <function>FcConfigSetDefaultSubstitute</function>
+and will be deprecated.
+@@
+
+ at RET@ void
+ at FUNC@ FcConfigSetDefaultSubstitute
+ at TYPE1@ FcConfig * @ARG1@ config
+ at TYPE2@ FcPattern * @ARG2@ pattern
+ at PURPOSE@ Perform default substitutions in a pattern
+ at DESC@
+Supplies default values for underspecified font patterns:
+<itemizedlist>
+<listitem><para>
+Patterns without a specified style or weight are set to Medium
+</para></listitem>
+<listitem><para>
+Patterns without a specified style or slant are set to Roman
+</para></listitem>
+<listitem><para>
+Patterns without a specified pixel size are given one computed from any
+specified point size (default 12), dpi (default 75) and scale (default 1).
+</para></listitem>
+</itemizedlist>
+ at SINCE@ 2.17.0
@@
@RET@ FcPattern *
diff --git a/fc-match/fc-match.c b/fc-match/fc-match.c
index ceced5f..268b34c 100644
--- a/fc-match/fc-match.c
+++ b/fc-match/fc-match.c
@@ -183,7 +183,7 @@ main (int argc, char **argv)
return 1;
FcConfigSubstitute (0, pat, FcMatchPattern);
- FcDefaultSubstitute (pat);
+ FcConfigSetDefaultSubstitute (0, pat);
fs = FcFontSetCreate();
diff --git a/fc-pattern/fc-pattern.c b/fc-pattern/fc-pattern.c
index 792d7da..8de2722 100644
--- a/fc-pattern/fc-pattern.c
+++ b/fc-pattern/fc-pattern.c
@@ -168,7 +168,7 @@ main (int argc, char **argv)
if (do_config)
FcConfigSubstitute (0, pat, FcMatchPattern);
if (do_default)
- FcDefaultSubstitute (pat);
+ FcConfigSetDefaultSubstitute (0, pat);
if (os) {
FcPattern *new;
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index 6326636..891b6d4 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -608,9 +608,16 @@ FcPublic void
FcFontSetPrint (const FcFontSet *s);
/* fcdefault.c */
+FcPublic FcStrSet *
+FcConfigGetDefaultLangs (FcConfig *config);
+
FcPublic FcStrSet *
FcGetDefaultLangs (void);
+FcPublic void
+FcConfigSetDefaultSubstitute (FcConfig *config,
+ FcPattern *pattern);
+
FcPublic void
FcDefaultSubstitute (FcPattern *pattern);
diff --git a/src/fccfg.c b/src/fccfg.c
index 16deaf2..0756698 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -202,6 +202,10 @@ FcConfigCreate (void)
config->filter_func = NULL;
config->filter_data = NULL;
config->destroy_data_func = NULL;
+ config->default_lang = NULL;
+ config->default_langs = NULL;
+ config->prgname = NULL;
+ config->desktop_name = NULL;
config->prefer_app_fonts = FcFalse;
@@ -383,6 +387,15 @@ FcConfigDestroy (FcConfig *config)
if (config->filter_data && config->destroy_data_func)
config->destroy_data_func (config->filter_data);
+ if (config->default_lang)
+ FcStrFree (config->default_lang);
+ if (config->default_langs)
+ FcStrSetDestroy (config->default_langs);
+ if (config->prgname)
+ FcStrFree (config->prgname);
+ if (config->desktop_name)
+ FcStrFree (config->desktop_name);
+
free (config);
}
}
@@ -1935,7 +1948,7 @@ FcConfigSubstituteWithPat (FcConfig *config,
s = config->subst[kind];
if (kind == FcMatchPattern) {
- strs = FcGetDefaultLangs();
+ strs = FcConfigGetDefaultLangs (config);
if (strs) {
FcStrList *l = FcStrListCreate (strs);
FcChar8 *lang;
@@ -1982,7 +1995,7 @@ FcConfigSubstituteWithPat (FcConfig *config,
FcLangSetDestroy (lsund);
}
if (FcPatternObjectGet (p, FC_PRGNAME_OBJECT, 0, &v) == FcResultNoMatch) {
- FcChar8 *prgname = FcGetPrgname();
+ FcChar8 *prgname = FcConfigGetPrgname (config);
if (prgname)
FcPatternObjectAddString (p, FC_PRGNAME_OBJECT, prgname);
}
diff --git a/src/fcdefault.c b/src/fcdefault.c
index b3aed4d..f742fc1 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -48,11 +48,16 @@ static const struct {
FcStrSet *default_langs;
FcStrSet *
-FcGetDefaultLangs (void)
+FcConfigGetDefaultLangs (FcConfig *config)
{
FcStrSet *result;
+
+ if (!config) {
+ config = FcConfigGetCurrent();
+ }
+ FcConfigReference (config);
retry:
- result = (FcStrSet *)fc_atomic_ptr_get (&default_langs);
+ result = (FcStrSet *)fc_atomic_ptr_get (&config->default_langs);
if (!result) {
char *langs;
@@ -80,45 +85,65 @@ retry:
FcStrSetAdd (result, (const FcChar8 *)"en");
FcRefSetConst (&result->ref);
- if (!fc_atomic_ptr_cmpexch (&default_langs, NULL, result)) {
+ if (!fc_atomic_ptr_cmpexch (&config->default_langs, NULL, result)) {
FcRefInit (&result->ref, 1);
FcStrSetDestroy (result);
goto retry;
}
}
+ FcConfigDestroy (config);
return result;
}
-static FcChar8 *default_lang; /* MT-safe */
+FcStrSet *
+FcGetDefaultLangs (void)
+{
+ return FcConfigGetDefaultLangs (NULL);
+}
FcChar8 *
-FcGetDefaultLang (void)
+FcConfigGetDefaultLang (FcConfig *config)
{
FcChar8 *lang;
+
+ if (!config) {
+ config = FcConfigGetCurrent();
+ }
+ FcConfigReference (config);
retry:
- lang = fc_atomic_ptr_get (&default_lang);
+ lang = fc_atomic_ptr_get (&config->default_lang);
if (!lang) {
- FcStrSet *langs = FcGetDefaultLangs();
+ FcStrSet *langs = FcConfigGetDefaultLangs (config);
lang = FcStrdup (langs->strs[0]);
- if (!fc_atomic_ptr_cmpexch (&default_lang, NULL, lang)) {
+ if (!fc_atomic_ptr_cmpexch (&config->default_lang, NULL, lang)) {
free (lang);
goto retry;
}
}
+ FcConfigDestroy (config);
return lang;
}
-static FcChar8 *default_prgname;
+FcChar8 *
+FcGetDefaultLang (void)
+{
+ return FcConfigGetDefaultLang (NULL);
+}
FcChar8 *
-FcGetPrgname (void)
+FcConfigGetPrgname (FcConfig *config)
{
FcChar8 *prgname;
+
+ if (!config) {
+ config = FcConfigGetCurrent();
+ }
+ FcConfigReference (config);
retry:
- prgname = fc_atomic_ptr_get (&default_prgname);
+ prgname = fc_atomic_ptr_get (&config->prgname);
if (!prgname) {
#ifdef _WIN32
char buf[MAX_PATH + 1];
@@ -197,26 +222,38 @@ retry:
free (p);
#endif
- if (!fc_atomic_ptr_cmpexch (&default_prgname, NULL, prgname)) {
+ if (!fc_atomic_ptr_cmpexch (&config->prgname, NULL, prgname)) {
free (prgname);
goto retry;
}
}
- if (prgname && !prgname[0])
- return NULL;
+ if (prgname && !prgname[0]) {
+ free (prgname);
+ prgname = NULL;
+ }
+ FcConfigDestroy (config);
return prgname;
}
-static FcChar8 *default_desktop_name;
+FcChar8 *
+FcGetPrgname (void)
+{
+ return FcConfigGetPrgname (NULL);
+}
FcChar8 *
-FcGetDesktopName (void)
+FcConfigGetDesktopName (FcConfig *config)
{
FcChar8 *desktop_name;
+
+ if (!config) {
+ config = FcConfigGetCurrent();
+ }
+ FcConfigReference (config);
retry:
- desktop_name = fc_atomic_ptr_get (&default_desktop_name);
+ desktop_name = fc_atomic_ptr_get (&config->desktop_name);
if (!desktop_name) {
char *s = getenv ("XDG_CURRENT_DESKTOP");
@@ -230,49 +267,28 @@ retry:
return NULL;
}
- if (!fc_atomic_ptr_cmpexch (&default_desktop_name, NULL, desktop_name)) {
+ if (!fc_atomic_ptr_cmpexch (&config->desktop_name, NULL, desktop_name)) {
free (desktop_name);
goto retry;
}
}
- if (desktop_name && !desktop_name[0])
- return NULL;
+ if (desktop_name && !desktop_name[0]) {
+ desktop_name = NULL;
+ }
+ FcConfigDestroy (config);
return desktop_name;
}
-void
-FcDefaultFini (void)
+FcChar8 *
+FcGetDesktopName (void)
{
- FcChar8 *lang;
- FcStrSet *langs;
- FcChar8 *prgname;
- FcChar8 *desktop;
-
- lang = fc_atomic_ptr_get (&default_lang);
- if (lang && fc_atomic_ptr_cmpexch (&default_lang, lang, NULL)) {
- free (lang);
- }
-
- langs = fc_atomic_ptr_get (&default_langs);
- if (langs && fc_atomic_ptr_cmpexch (&default_langs, langs, NULL)) {
- FcRefInit (&langs->ref, 1);
- FcStrSetDestroy (langs);
- }
-
- prgname = fc_atomic_ptr_get (&default_prgname);
- if (prgname && fc_atomic_ptr_cmpexch (&default_prgname, prgname, NULL)) {
- free (prgname);
- }
-
- desktop = fc_atomic_ptr_get (&default_desktop_name);
- if (desktop && fc_atomic_ptr_cmpexch (&default_desktop_name, desktop, NULL)) {
- free (desktop);
- }
+ return FcConfigGetDesktopName (NULL);
}
void
-FcDefaultSubstitute (FcPattern *pattern)
+FcConfigSetDefaultSubstitute (FcConfig *config,
+ FcPattern *pattern)
{
FcPatternIter iter;
FcValue v, namelang, v2;
@@ -331,7 +347,7 @@ FcDefaultSubstitute (FcPattern *pattern)
FcPatternObjectAddInteger (pattern, FC_HINT_STYLE_OBJECT, FC_HINT_FULL);
if (!FcPatternFindObjectIter (pattern, &iter, FC_NAMELANG_OBJECT))
- FcPatternObjectAddString (pattern, FC_NAMELANG_OBJECT, FcGetDefaultLang());
+ FcPatternObjectAddString (pattern, FC_NAMELANG_OBJECT, FcConfigGetDefaultLang (config));
/* shouldn't be failed. */
FcPatternObjectGet (pattern, FC_NAMELANG_OBJECT, 0, &namelang);
@@ -362,13 +378,13 @@ FcDefaultSubstitute (FcPattern *pattern)
}
if (FcPatternObjectGet (pattern, FC_PRGNAME_OBJECT, 0, &v) == FcResultNoMatch) {
- FcChar8 *prgname = FcGetPrgname();
+ FcChar8 *prgname = FcConfigGetPrgname (config);
if (prgname)
FcPatternObjectAddString (pattern, FC_PRGNAME_OBJECT, prgname);
}
if (FcPatternObjectGet (pattern, FC_DESKTOP_NAME_OBJECT, 0, &v) == FcResultNoMatch) {
- FcChar8 *desktop = FcGetDesktopName();
+ FcChar8 *desktop = FcConfigGetDesktopName (config);
if (desktop)
FcPatternObjectAddString (pattern, FC_DESKTOP_NAME_OBJECT, desktop);
}
@@ -376,6 +392,12 @@ FcDefaultSubstitute (FcPattern *pattern)
if (!FcPatternFindObjectIter (pattern, &iter, FC_ORDER_OBJECT))
FcPatternObjectAddInteger (pattern, FC_ORDER_OBJECT, 0);
}
+
+void
+FcDefaultSubstitute (FcPattern *pattern)
+{
+ FcConfigSetDefaultSubstitute (NULL, pattern);
+}
#define __fcdefault__
#include "fcaliastail.h"
#undef __fcdefault__
diff --git a/src/fcinit.c b/src/fcinit.c
index 11afa28..361f80d 100644
--- a/src/fcinit.c
+++ b/src/fcinit.c
@@ -215,7 +215,6 @@ FcFini (void)
{
FcConfigFini();
FcConfigPathFini();
- FcDefaultFini();
FcObjectFini();
FcCacheFini();
}
diff --git a/src/fcint.h b/src/fcint.h
index d3c2c5a..2dd0bf5 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -620,6 +620,11 @@ struct _FcConfig {
FcBool prefer_app_fonts; /* Whether FcSetApplication has a priority than
FcSetSystem for lookup */
+
+ FcChar8 *default_lang; /* Primary language in default_langs */
+ FcStrSet *default_langs; /* String sets of the default languages */
+ FcChar8 *prgname; /* Program name of current process */
+ FcChar8 *desktop_name; /* Current desktop name */
};
typedef struct _FcFileTime {
@@ -943,17 +948,23 @@ FcPrivate void
FcInitDebug (void);
/* fcdefault.c */
+FcPrivate FcChar8 *
+FcConfigGetDefaultLang (FcConfig *config);
+
FcPrivate FcChar8 *
FcGetDefaultLang (void);
+FcPrivate FcChar8 *
+FcConfigGetPrgname (FcConfig *config);
+
FcPrivate FcChar8 *
FcGetPrgname (void);
FcPrivate FcChar8 *
-FcGetDesktopName (void);
+FcConfigGetDesktopName (FcConfig *config);
-FcPrivate void
-FcDefaultFini (void);
+FcPrivate FcChar8 *
+FcGetDesktopName (void);
/* fcdir.c */
diff --git a/src/fclist.c b/src/fclist.c
index bd672b8..c369ea9 100644
--- a/src/fclist.c
+++ b/src/fclist.c
@@ -491,7 +491,7 @@ FcFontSetList (FcConfig *config,
FcChar8 *lang;
if (FcPatternObjectGetString (p, FC_NAMELANG_OBJECT, 0, &lang) != FcResultMatch) {
- lang = FcGetDefaultLang();
+ lang = FcConfigGetDefaultLang (config);
}
if (!FcListAppend (&table, s->fonts[f], os, lang))
goto bail1;
diff --git a/test/test-conf.c b/test/test-conf.c
index 54e5d70..725cd7f 100644
--- a/test/test-conf.c
+++ b/test/test-conf.c
@@ -455,7 +455,7 @@ run_test (FcConfig *config, json_object *root)
goto bail;
}
FcConfigSubstitute (config, query, FcMatchPattern);
- FcDefaultSubstitute (query);
+ FcConfigSetDefaultSubstitute (config, query);
match = FcFontMatch (config, query, &res);
if (match) {
FcPatternIter iter;
diff --git a/test/test-crbug1004254.c b/test/test-crbug1004254.c
index 6970c4c..e14c2a4 100644
--- a/test/test-crbug1004254.c
+++ b/test/test-crbug1004254.c
@@ -42,7 +42,7 @@ run_query (void)
FcPatternAddString (pat, FC_FAMILY, (const FcChar8 *)"sans-serif");
FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
FcConfigSubstitute (NULL, pat, FcMatchPattern);
- FcDefaultSubstitute (pat);
+ FcConfigSetDefaultSubstitute (NULL, pat);
match = FcFontMatch (NULL, pat, &result);
if (result != FcResultMatch || !match) {
fprintf (stderr, "ERROR: No matches found\n");
diff --git a/test/test-pthread.c b/test/test-pthread.c
index 41debad..6628d83 100644
--- a/test/test-pthread.c
+++ b/test/test-pthread.c
@@ -48,7 +48,7 @@ test_match (int thr_num, int test_num)
pat = FcNameParse ((const FcChar8 *)"New Century Schoolbook");
FcConfigSubstitute (0, pat, FcMatchPattern);
- FcDefaultSubstitute (pat);
+ FcConfigSetDefaultSubstitute (0, pat);
match = FcFontMatch (0, pat, &result);
More information about the Fontconfig
mailing list