FcStrSet *FcGetDefaultLangs(void) { FcStrSet *result; retry: result = (FcStrSet *)fc_atomic_ptr_get(&default_langs); if (!result) { 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; } } return result; }
void FcConfigFini (void) { FcConfig *cfg = fc_atomic_ptr_get (&_fcConfig); if (cfg && fc_atomic_ptr_cmpexch (&_fcConfig, cfg, NULL)) FcConfigDestroy (cfg); }
static FcObjectType *_FcObjectLookupOtherTypeByName(const char *str, FcObject *id) { struct FcObjectOtherTypeInfo *ots, *ot; retry: ots = fc_atomic_ptr_get(&other_types); for (ot = ots; ot; ot = ot->next) if (0 == strcmp(ot->object.object, str)) break; if (!ot) { ot = malloc(sizeof(*ot)); if (!ot) return NULL; ot->object.object = (const char *)FcStrdup(str); ot->object.type = FcTypeUnknown; ot->id = fc_atomic_int_add(next_id, +1); ot->next = ots; if (!fc_atomic_ptr_cmpexch(&other_types, ots, ot)) { free(ot); goto retry; } } if (id) *id = ot->id; return &ot->object; }
static FcBool FcCacheIsMmapSafe (int fd) { enum { MMAP_NOT_INITIALIZED = 0, MMAP_USE, MMAP_DONT_USE, MMAP_CHECK_FS, } status; static void *static_status; status = (intptr_t) fc_atomic_ptr_get (&static_status); if (status == MMAP_NOT_INITIALIZED) { const char *env = getenv ("FONTCONFIG_USE_MMAP"); FcBool use; if (env && FcNameBool ((const FcChar8 *) env, &use)) status = use ? MMAP_USE : MMAP_DONT_USE; else status = MMAP_CHECK_FS; (void) fc_atomic_ptr_cmpexch (&static_status, NULL, (void *) status); } if (status == MMAP_CHECK_FS) return FcIsFsMmapSafe (fd); else return status == MMAP_USE; }
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); } }
const char *FcObjectLookupOtherNameById(FcObject id) { struct FcObjectOtherTypeInfo *ot; for (ot = fc_atomic_ptr_get(&other_types); ot; ot = ot->next) if (ot->id == id) return ot->object.object; return NULL; }
FcPrivate const FcObjectType *FcObjectLookupOtherTypeById(FcObject id) { struct FcObjectOtherTypeInfo *ot; for (ot = fc_atomic_ptr_get(&other_types); ot; ot = ot->next) if (ot->id == id) return &ot->object; return NULL; }
static void free_lock (void) { FcMutex *lock; lock = fc_atomic_ptr_get (&cache_lock); if (lock && fc_atomic_ptr_cmpexch (&cache_lock, lock, NULL)) { FcMutexFinish (lock); free (lock); } }
static FcConfig * FcConfigEnsure (void) { FcConfig *config; retry: config = fc_atomic_ptr_get (&_fcConfig); if (!config) { config = FcInitLoadConfigAndFonts (); if (!fc_atomic_ptr_cmpexch (&_fcConfig, NULL, config)) { FcConfigDestroy (config); goto retry; } } return config; }
FcChar8 *FcGetDefaultLang(void) { FcChar8 *lang; retry: lang = fc_atomic_ptr_get(&default_lang); if (!lang) { 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; }
static void lock_cache (void) { FcMutex *lock; retry: lock = fc_atomic_ptr_get (&cache_lock); if (!lock) { lock = (FcMutex *) malloc (sizeof (FcMutex)); FcMutexInit (lock); if (!fc_atomic_ptr_cmpexch (&cache_lock, NULL, lock)) { FcMutexFinish (lock); goto retry; } FcMutexLock (lock); /* Initialize random state */ FcRandom (); return; } FcMutexLock (lock); }
FcBool FcConfigSetCurrent (FcConfig *config) { FcConfig *cfg; retry: cfg = fc_atomic_ptr_get (&_fcConfig); if (config == cfg) return FcTrue; if (config && !config->fonts[FcSetSystem]) if (!FcConfigBuildFonts (config)) return FcFalse; if (!fc_atomic_ptr_cmpexch (&_fcConfig, cfg, config)) goto retry; if (cfg) FcConfigDestroy (cfg); return FcTrue; }
FcChar8 *FcGetPrgname(void) { FcChar8 *prgname; retry: prgname = fc_atomic_ptr_get(&default_prgname); if (!prgname) { #ifdef _WIN32 char buf[MAX_PATH + 1]; /* TODO This is ASCII-only; fix it. */ if (GetModuleFileNameA(GetModuleHandle(NULL), buf, sizeof(buf) / sizeof(buf[0])) > 0) { char *p; unsigned int len; p = strrchr(buf, '\\'); if (p) p++; else p = buf; len = strlen(p); if (len > 4 && 0 == strcmp(p + len - 4, ".exe")) { len -= 4; buf[len] = '\0'; } prgname = FcStrdup(p); } #elif defined(HAVE_GETPROGNAME) const char *q = getprogname(); if (q) prgname = FcStrdup(q); else prgname = FcStrdup(""); #else #if defined(HAVE_GETEXECNAME) const char *p = getexecname(); #elif defined(HAVE_READLINK) char buf[PATH_MAX + 1]; int len; char *p = NULL; len = readlink("/proc/self/exe", buf, sizeof(buf) - 1); if (len != -1) { buf[len] = '\0'; p = buf; } #else char *p = NULL; #endif if (p) { char *r = strrchr(p, '/'); if (r) r++; else r = p; prgname = FcStrdup(r); } if (!prgname) prgname = FcStrdup(""); #endif if (!fc_atomic_ptr_cmpexch(&default_prgname, NULL, prgname)) { free(prgname); goto retry; } } if (prgname && !prgname[0]) return NULL; return prgname; }