aboutsummaryrefslogtreecommitdiff
path: root/fontconfig/src/fcdefault.c
diff options
context:
space:
mode:
Diffstat (limited to 'fontconfig/src/fcdefault.c')
-rw-r--r--fontconfig/src/fcdefault.c91
1 files changed, 66 insertions, 25 deletions
diff --git a/fontconfig/src/fcdefault.c b/fontconfig/src/fcdefault.c
index 8ad1b1e90..6937994b7 100644
--- a/fontconfig/src/fcdefault.c
+++ b/fontconfig/src/fcdefault.c
@@ -25,6 +25,8 @@
#include "fcint.h"
#include <string.h>
+/* MT-safe */
+
static const struct {
FcObject field;
FcBool value;
@@ -32,7 +34,6 @@ static const struct {
{ FC_HINTING_OBJECT, FcTrue }, /* !FT_LOAD_NO_HINTING */
{ FC_VERTICAL_LAYOUT_OBJECT, FcFalse }, /* FC_LOAD_VERTICAL_LAYOUT */
{ FC_AUTOHINT_OBJECT, FcFalse }, /* FC_LOAD_FORCE_AUTOHINT */
- /* XXX: FC_GLOBAL_ADVANCE is deprecated */
{ FC_GLOBAL_ADVANCE_OBJECT, FcTrue }, /* !FC_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */
{ FC_EMBEDDED_BITMAP_OBJECT, FcTrue }, /* !FC_LOAD_NO_BITMAP */
{ FC_DECORATIVE_OBJECT, FcFalse },
@@ -40,45 +41,85 @@ static const struct {
#define NUM_FC_BOOL_DEFAULTS (int) (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0])
+FcStrSet *default_langs;
+
FcStrSet *
FcGetDefaultLangs (void)
{
- FcStrSet *result = FcStrSetCreate ();
- char *langs;
-
- langs = getenv ("FC_LANG");
- if (!langs || !langs[0])
- langs = getenv ("LC_ALL");
- if (!langs || !langs[0])
- langs = getenv ("LC_CTYPE");
- if (!langs || !langs[0])
- langs = getenv ("LANG");
- if (langs && langs[0])
+ FcStrSet *result;
+retry:
+ result = (FcStrSet *) fc_atomic_ptr_get (&default_langs);
+ if (!result)
{
- if (!FcStrSetAddLangs (result, langs))
+ char *langs;
+
+ result = FcStrSetCreate ();
+
+ langs = getenv ("FC_LANG");
+ if (!langs || !langs[0])
+ langs = getenv ("LC_ALL");
+ if (!langs || !langs[0])
+ langs = getenv ("LC_CTYPE");
+ if (!langs || !langs[0])
+ langs = getenv ("LANG");
+ if (langs && langs[0])
+ {
+ if (!FcStrSetAddLangs (result, langs))
+ FcStrSetAdd (result, (const FcChar8 *) "en");
+ }
+ else
FcStrSetAdd (result, (const FcChar8 *) "en");
+
+ FcRefSetConst (&result->ref);
+ if (!fc_atomic_ptr_cmpexch (&default_langs, NULL, result)) {
+ FcRefInit (&result->ref, 1);
+ FcStrSetDestroy (result);
+ goto retry;
+ }
}
- else
- FcStrSetAdd (result, (const FcChar8 *) "en");
return result;
}
+static FcChar8 *default_lang; /* MT-safe */
+
FcChar8 *
FcGetDefaultLang (void)
{
- static FcChar8 lang_local[128] = {0};
- FcStrSet *langs;
-
- if (!lang_local[0])
+ FcChar8 *lang;
+retry:
+ lang = fc_atomic_ptr_get (&default_lang);
+ if (!lang)
{
- langs = FcGetDefaultLangs ();
- strncpy ((char *)lang_local, (const char *)langs->strs[0], 127);
- lang_local[127] = 0;
+ FcStrSet *langs = FcGetDefaultLangs ();
+ lang = FcStrdup (langs->strs[0]);
FcStrSetDestroy (langs);
+
+ if (!fc_atomic_ptr_cmpexch (&default_lang, NULL, lang)) {
+ free (lang);
+ goto retry;
+ }
}
- return lang_local;
+ return lang;
+}
+
+void
+FcDefaultFini (void)
+{
+ FcChar8 *lang;
+ FcStrSet *langs;
+
+ 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);
+ }
}
void
@@ -154,7 +195,7 @@ FcDefaultSubstitute (FcPattern *pattern)
* exact matched "en" has higher score than ll-cc.
*/
v2.type = FcTypeString;
- v2.u.s = FcSharedStr ((FcChar8 *)"en-us");
+ v2.u.s = FcStrdup ("en-us");
if (FcPatternObjectGet (pattern, FC_FAMILYLANG_OBJECT, 0, &v) == FcResultNoMatch)
{
FcPatternObjectAdd (pattern, FC_FAMILYLANG_OBJECT, namelang, FcTrue);
@@ -170,7 +211,7 @@ FcDefaultSubstitute (FcPattern *pattern)
FcPatternObjectAdd (pattern, FC_FULLNAMELANG_OBJECT, namelang, FcTrue);
FcPatternObjectAddWithBinding (pattern, FC_FULLNAMELANG_OBJECT, v2, FcValueBindingWeak, FcTrue);
}
- FcSharedStrFree (v2.u.s);
+ FcFree (v2.u.s);
}
#define __fcdefault__
#include "fcaliastail.h"