static FcBool FcCacheDirsValid (FcConfig *config, FcCache *cache) { FcStrSet *dirs = FcStrSetCreateEx (FCSS_GROW_BY_64); FcBool ret = FcFalse; const FcChar8 *sysroot = FcConfigGetSysRoot (config); FcChar8 *d; if (!dirs) goto bail; if (sysroot) d = FcStrBuildFilename (sysroot, FcCacheDir (cache), NULL); else d = FcStrdup (FcCacheDir (cache)); if (!FcDirScanOnly (dirs, d, config)) goto bail1; ret = cache->dirs_count == dirs->num; if (FcDebug () & FC_DBG_CACHE) printf ("%s: cache: %d, fs: %d\n", d, cache->dirs_count, dirs->num); bail1: FcStrSetDestroy (dirs); FcStrFree (d); bail: return ret; }
/* * Look for a cache file for the specified dir. Attempt * to use each one we find, stopping when the callback * indicates success */ static FcBool FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, FcBool (*callback) (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure), void *closure, FcChar8 **cache_file_ret) { int fd = -1; FcChar8 cache_base[CACHEBASE_LEN]; FcStrList *list; FcChar8 *cache_dir, *d; struct stat file_stat, dir_stat; FcBool ret = FcFalse; const FcChar8 *sysroot = FcConfigGetSysRoot (config); if (sysroot) d = FcStrBuildFilename (sysroot, dir, NULL); else d = FcStrdup (dir); if (FcStatChecksum (d, &dir_stat) < 0) { FcStrFree (d); return FcFalse; } FcStrFree (d); FcDirCacheBasename (dir, cache_base); list = FcStrListCreate (config->cacheDirs); if (!list) return FcFalse; while ((cache_dir = FcStrListNext (list))) { FcChar8 *cache_hashed; if (sysroot) cache_hashed = FcStrBuildFilename (sysroot, cache_dir, cache_base, NULL); else cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL); if (!cache_hashed) break; fd = FcDirCacheOpenFile (cache_hashed, &file_stat); if (fd >= 0) { ret = (*callback) (config, fd, &file_stat, &dir_stat, closure); close (fd); if (ret) { if (cache_file_ret) *cache_file_ret = cache_hashed; else FcStrFree (cache_hashed); break; } } FcStrFree (cache_hashed); } FcStrListDone (list); return ret; }
static FcValue FcNameConvert (FcType type, FcChar8 *string) { FcValue v; FcMatrix m; double b, e; char *p; v.type = type; switch ((int) v.type) { case FcTypeInteger: if (!FcNameConstant (string, &v.u.i)) v.u.i = atoi ((char *) string); break; case FcTypeString: v.u.s = FcStrdup (string); if (!v.u.s) v.type = FcTypeVoid; break; case FcTypeBool: if (!FcNameBool (string, &v.u.b)) v.u.b = FcFalse; break; case FcTypeDouble: v.u.d = strtod ((char *) string, 0); break; case FcTypeMatrix: FcMatrixInit (&m); sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy); v.u.m = FcMatrixCopy (&m); break; case FcTypeCharSet: v.u.c = FcNameParseCharSet (string); if (!v.u.c) v.type = FcTypeVoid; break; case FcTypeLangSet: v.u.l = FcNameParseLangSet (string); if (!v.u.l) v.type = FcTypeVoid; break; case FcTypeRange: if (sscanf ((char *) string, "(%lg %lg)", &b, &e) != 2) { v.u.d = strtod ((char *) string, &p); if (p != NULL && p[0] != 0) { v.type = FcTypeVoid; break; } v.type = FcTypeDouble; } else v.u.r = FcRangeCreateDouble (b, e); break; default: break; } return v; }
static FcBool FcCacheTimeValid (FcConfig *config, FcCache *cache, struct stat *dir_stat) { struct stat dir_static; if (!dir_stat) { const FcChar8 *sysroot = FcConfigGetSysRoot (config); FcChar8 *d; if (sysroot) d = FcStrBuildFilename (sysroot, FcCacheDir (cache), NULL); else d = FcStrdup (FcCacheDir (cache)); if (FcStatChecksum (d, &dir_static) < 0) { FcStrFree (d); return FcFalse; } FcStrFree (d); dir_stat = &dir_static; } if (FcDebug () & FC_DBG_CACHE) printf ("FcCacheTimeValid dir \"%s\" cache checksum %d dir checksum %d\n", FcCacheDir (cache), cache->checksum, (int) dir_stat->st_mtime); return cache->checksum == (int) dir_stat->st_mtime; }
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; }
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 FcValue FcNameConvert (FcType type, FcChar8 *string) { FcValue v; FcMatrix m; v.type = type; switch ((int) v.type) { case FcTypeInteger: if (!FcNameConstant (string, &v.u.i)) v.u.i = atoi ((char *) string); break; case FcTypeString: v.u.s = FcStrdup (string); if (!v.u.s) v.type = FcTypeVoid; break; case FcTypeBool: if (!FcNameBool (string, &v.u.b)) v.u.b = FcFalse; break; case FcTypeDouble: v.u.d = strtod ((char *) string, 0); break; case FcTypeMatrix: FcMatrixInit (&m); sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy); v.u.m = FcMatrixCopy (&m); break; case FcTypeCharSet: v.u.c = FcNameParseCharSet (string); if (!v.u.c) v.type = FcTypeVoid; break; case FcTypeLangSet: v.u.l = FcNameParseLangSet (string); if (!v.u.l) v.type = FcTypeVoid; break; default: break; } return v; }
static FcBool FcCacheTimeValid (FcConfig *config, FcCache *cache, struct stat *dir_stat) { struct stat dir_static; FcBool fnano = FcTrue; if (!dir_stat) { const FcChar8 *sysroot = FcConfigGetSysRoot (config); FcChar8 *d; if (sysroot) d = FcStrBuildFilename (sysroot, FcCacheDir (cache), NULL); else d = FcStrdup (FcCacheDir (cache)); if (FcStatChecksum (d, &dir_static) < 0) { FcStrFree (d); return FcFalse; } FcStrFree (d); dir_stat = &dir_static; } #ifdef HAVE_STRUCT_STAT_ST_MTIM fnano = (cache->checksum_nano == dir_stat->st_mtim.tv_nsec); if (FcDebug () & FC_DBG_CACHE) printf ("FcCacheTimeValid dir \"%s\" cache checksum %d.%ld dir checksum %d.%ld\n", FcCacheDir (cache), cache->checksum, (long)cache->checksum_nano, (int) dir_stat->st_mtime, dir_stat->st_mtim.tv_nsec); #else if (FcDebug () & FC_DBG_CACHE) printf ("FcCacheTimeValid dir \"%s\" cache checksum %d dir checksum %d\n", FcCacheDir (cache), cache->checksum, (int) dir_stat->st_mtime); #endif return cache->checksum == (int) dir_stat->st_mtime && fnano; }
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; }
FcChar8 * FcStrCopy (const FcChar8 *s) { return FcStrdup (s); }
void FcDefaultSubstitute (FcPattern *pattern) { FcValue v, namelang, v2; int i; if (FcPatternObjectGet (pattern, FC_WEIGHT_OBJECT, 0, &v) == FcResultNoMatch ) FcPatternObjectAddInteger (pattern, FC_WEIGHT_OBJECT, FC_WEIGHT_MEDIUM); if (FcPatternObjectGet (pattern, FC_SLANT_OBJECT, 0, &v) == FcResultNoMatch) FcPatternObjectAddInteger (pattern, FC_SLANT_OBJECT, FC_SLANT_ROMAN); if (FcPatternObjectGet (pattern, FC_WIDTH_OBJECT, 0, &v) == FcResultNoMatch) FcPatternObjectAddInteger (pattern, FC_WIDTH_OBJECT, FC_WIDTH_NORMAL); for (i = 0; i < NUM_FC_BOOL_DEFAULTS; i++) if (FcPatternObjectGet (pattern, FcBoolDefaults[i].field, 0, &v) == FcResultNoMatch) FcPatternObjectAddBool (pattern, FcBoolDefaults[i].field, FcBoolDefaults[i].value); if (FcPatternObjectGet (pattern, FC_PIXEL_SIZE_OBJECT, 0, &v) == FcResultNoMatch) { double dpi, size, scale; if (FcPatternObjectGetDouble (pattern, FC_SIZE_OBJECT, 0, &size) != FcResultMatch) { size = 12.0; (void) FcPatternObjectDel (pattern, FC_SIZE_OBJECT); FcPatternObjectAddDouble (pattern, FC_SIZE_OBJECT, size); } if (FcPatternObjectGetDouble (pattern, FC_SCALE_OBJECT, 0, &scale) != FcResultMatch) { scale = 1.0; (void) FcPatternObjectDel (pattern, FC_SCALE_OBJECT); FcPatternObjectAddDouble (pattern, FC_SCALE_OBJECT, scale); } size *= scale; if (FcPatternObjectGetDouble (pattern, FC_DPI_OBJECT, 0, &dpi) != FcResultMatch) { dpi = 75.0; (void) FcPatternObjectDel (pattern, FC_DPI_OBJECT); FcPatternObjectAddDouble (pattern, FC_DPI_OBJECT, dpi); } size *= dpi / 72.0; FcPatternObjectAddDouble (pattern, FC_PIXEL_SIZE_OBJECT, size); } if (FcPatternObjectGet (pattern, FC_FONTVERSION_OBJECT, 0, &v) == FcResultNoMatch) { FcPatternObjectAddInteger (pattern, FC_FONTVERSION_OBJECT, 0x7fffffff); } if (FcPatternObjectGet (pattern, FC_HINT_STYLE_OBJECT, 0, &v) == FcResultNoMatch) { FcPatternObjectAddInteger (pattern, FC_HINT_STYLE_OBJECT, FC_HINT_FULL); } if (FcPatternObjectGet (pattern, FC_NAMELANG_OBJECT, 0, &v) == FcResultNoMatch) { FcPatternObjectAddString (pattern, FC_NAMELANG_OBJECT, FcGetDefaultLang ()); } /* shouldn't be failed. */ FcPatternObjectGet (pattern, FC_NAMELANG_OBJECT, 0, &namelang); /* Add a fallback to ensure the english name when the requested language * isn't available. this would helps for the fonts that have non-English * name at the beginning. */ /* Set "en-us" instead of "en" to avoid giving higher score to "en". * This is a hack for the case that the orth is not like ll-cc, because, * if no namelang isn't explicitly set, it will has something like ll-cc * according to current locale. which may causes FcLangDifferentTerritory * at FcLangCompare(). thus, the English name is selected so that * exact matched "en" has higher score than ll-cc. */ v2.type = FcTypeString; v2.u.s = FcStrdup ("en-us"); if (FcPatternObjectGet (pattern, FC_FAMILYLANG_OBJECT, 0, &v) == FcResultNoMatch) { FcPatternObjectAdd (pattern, FC_FAMILYLANG_OBJECT, namelang, FcTrue); FcPatternObjectAddWithBinding (pattern, FC_FAMILYLANG_OBJECT, v2, FcValueBindingWeak, FcTrue); } if (FcPatternObjectGet (pattern, FC_STYLELANG_OBJECT, 0, &v) == FcResultNoMatch) { FcPatternObjectAdd (pattern, FC_STYLELANG_OBJECT, namelang, FcTrue); FcPatternObjectAddWithBinding (pattern, FC_STYLELANG_OBJECT, v2, FcValueBindingWeak, FcTrue); } if (FcPatternObjectGet (pattern, FC_FULLNAMELANG_OBJECT, 0, &v) == FcResultNoMatch) { FcPatternObjectAdd (pattern, FC_FULLNAMELANG_OBJECT, namelang, FcTrue); FcPatternObjectAddWithBinding (pattern, FC_FULLNAMELANG_OBJECT, v2, FcValueBindingWeak, FcTrue); } FcFree (v2.u.s); }