static FcBool FcFileScanFontConfig (FcFontSet *set, FcBlanks *blanks, const FcChar8 *file, FcConfig *config) { FcPattern *font; FcBool ret = FcTrue; int id; int count = 0; id = 0; do { font = 0; /* * Nothing in the cache, scan the file */ if (FcDebug () & FC_DBG_SCAN) { printf ("\tScanning file %s...", file); fflush (stdout); } font = FcFreeTypeQuery (file, id, blanks, &count); if (FcDebug () & FC_DBG_SCAN) printf ("done\n"); /* * Edit pattern with user-defined rules */ if (font && config && !FcConfigSubstituteWithPat (config, font, NULL, FcMatchScan)) { FcPatternDestroy (font); font = NULL; ret = FcFalse; } /* * Add the font */ if (font && (!config || FcConfigAcceptFont (config, font))) { if (FcDebug() & FC_DBG_SCANV) { printf ("Final font pattern:\n"); FcPatternPrint (font); } if (!FcFontSetAdd (set, font)) { FcPatternDestroy (font); font = NULL; ret = FcFalse; } } else if (font) FcPatternDestroy (font); id++; } while (font && ret && id < count); return ret; }
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; }
FcBool FcConfigBuildFonts (FcConfig *config) { FcFontSet *fonts; if (!config) { config = FcConfigGetCurrent (); if (!config) return FcFalse; } fonts = FcFontSetCreate (); if (!fonts) return FcFalse; FcConfigSetFonts (config, fonts, FcSetSystem); if (!FcConfigAddDirList (config, FcSetSystem, config->fontDirs)) { if(FcDebug ()) fprintf(stderr,"Failed to get list of available fonts."); return FcFalse; } //if (FcDebug () & FC_DBG_FONTSET) #ifdef DEBUG FcFontSetPrint (fonts); #endif return FcTrue; }
static FcBool FcConfigAddDirList (FcConfig *config, FcSetName set, FcStrSet *dirSet) { FcStrList *dirlist; FcChar8 *dir; FcCache *cache; FcBool ret = FcFalse; dirlist = FcStrListCreate (dirSet); if (!dirlist) return FcFalse; while ((dir = FcStrListNext (dirlist))) { if (FcDebug () & FC_DBG_FONTSET) printf ("adding fonts from %s\n", dir); cache = FcDirCacheRead (dir, FcFalse, config); if (!cache) continue; FcConfigAddCache (config, cache, set, dirSet); FcDirCacheUnload (cache); ret = FcTrue; } FcStrListDone (dirlist); return ret; }
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; }
/* * Free all library-allocated data structures. */ void FcFini (void) { if (_fcConfig) FcConfigDestroy (_fcConfig); FcPatternFini (); FcCacheFini (); if (FcDebug() & FC_DBG_MEMORY) FcMemReport (); }
void FcMemAlloc (int kind, int size) { if (FcDebug() & FC_DBG_MEMORY) { FcInUse[kind].alloc_count++; FcInUse[kind].alloc_mem += size; FcAllocCount++; FcAllocMem += size; FcAllocNotify += size; if (FcAllocNotify > FcMemNotice) FcMemReport (); } }
void FcMemFree (int kind, int size) { if (FcDebug() & FC_DBG_MEMORY) { FcInUse[kind].free_count++; FcInUse[kind].free_mem += size; FcFreeCount++; FcFreeMem += size; FcFreeNotify += size; if (FcFreeNotify > FcMemNotice) FcMemReport (); } }
/* * Initialize the default library configuration */ FcBool FcInit (void) { FcConfig *config; if (_fcConfig) return FcTrue; config = FcInitLoadConfigAndFonts (); if (!config) return FcTrue; FcConfigSetCurrent (config); if (FcDebug() & FC_DBG_MEMORY) FcMemReport (); return FcTrue; }
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; }
FcBool FcConfigAddEdit (FcConfig *config, FcTest *test, FcEdit *edit, FcMatchKind kind) { FcSubst *subst, **prev; FcTest *t; int num; switch (kind) { case FcMatchPattern: prev = &config->substPattern; break; case FcMatchFont: prev = &config->substFont; break; case FcMatchScan: prev = &config->substScan; break; default: return FcFalse; } subst = (FcSubst *) malloc (sizeof (FcSubst)); if (!subst) return FcFalse; FcMemAlloc (FC_MEM_SUBST, sizeof (FcSubst)); for (; *prev; prev = &(*prev)->next); *prev = subst; subst->next = 0; subst->test = test; subst->edit = edit; num = 0; for (t = test; t; t = t->next) { if (t->kind == FcMatchDefault) t->kind = kind; num++; } if (config->maxObjects < num) config->maxObjects = num; if (FcDebug () & FC_DBG_EDIT) { printf ("Add Subst "); FcSubstPrint (subst); } return FcTrue; }
static FcBool FcCacheTimeValid (FcCache *cache, struct stat *dir_stat) { struct stat dir_static; if (!dir_stat) { if (FcStatChecksum (FcCacheDir (cache), &dir_static) < 0) return FcFalse; 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; }
FcBool FcConfigBuildFonts (FcConfig *config) { FcFontSet *fonts; if (!config) { config = FcConfigGetCurrent (); if (!config) return FcFalse; } fonts = FcFontSetCreate (); if (!fonts) return FcFalse; FcConfigSetFonts (config, fonts, FcSetSystem); if (!FcConfigAddDirList (config, FcSetSystem, config->fontDirs)) return FcFalse; if (FcDebug () & FC_DBG_FONTSET) FcFontSetPrint (fonts); return FcTrue; }
static FcBool FcCompareValueList (const char *object, FcValueList *v1orig, /* pattern */ FcValueList *v2orig, /* target */ FcValue *bestValue, double *value, FcResult *result) { FcValueList *v1, *v2; double v, best, bestStrong, bestWeak; int i; int j; /* * Locate the possible matching entry by examining the * first few characters in object */ i = -1; switch (FcToLower (object[0])) { case 'f': switch (FcToLower (object[1])) { case 'o': switch (FcToLower (object[2])) { case 'u': i = MATCH_FOUNDRY; break; case 'n': i = MATCH_FONTVERSION; break; } break; case 'a': i = MATCH_FAMILY; break; } break; case 'c': i = MATCH_CHARSET; break; case 'a': i = MATCH_ANTIALIAS; break; case 'l': i = MATCH_LANG; break; case 's': switch (FcToLower (object[1])) { case 'p': i = MATCH_SPACING; break; case 't': i = MATCH_STYLE; break; case 'l': i = MATCH_SLANT; break; } break; case 'p': i = MATCH_PIXEL_SIZE; break; case 'w': switch (FcToLower (object[1])) { case 'i': i = MATCH_WIDTH; break; case 'e': i = MATCH_WEIGHT; break; } break; case 'r': i = MATCH_RASTERIZER; break; case 'o': i = MATCH_OUTLINE; break; } if (i == -1 || FcStrCmpIgnoreCase ((FcChar8 *) _FcMatchers[i].object, (FcChar8 *) object) != 0) { if (bestValue) *bestValue = v2orig->value; return FcTrue; } #if 0 for (i = 0; i < NUM_MATCHER; i++) { if (!FcStrCmpIgnoreCase ((FcChar8 *) _FcMatchers[i].object, (FcChar8 *) object)) break; } if (i == NUM_MATCHER) { if (bestValue) *bestValue = v2orig->value; return FcTrue; } #endif best = 1e99; bestStrong = 1e99; bestWeak = 1e99; j = 0; for (v1 = v1orig; v1; v1 = v1->next) { for (v2 = v2orig; v2; v2 = v2->next) { v = (*_FcMatchers[i].compare) (_FcMatchers[i].object, v1->value, v2->value); if (v < 0) { *result = FcResultTypeMismatch; return FcFalse; } if (FcDebug () & FC_DBG_MATCHV) printf (" v %g j %d ", v, j); v = v * 100 + j; if (v < best) { if (bestValue) *bestValue = v2->value; best = v; } if (v1->binding == FcValueBindingStrong) { if (v < bestStrong) bestStrong = v; } else { if (v < bestWeak) bestWeak = v; } } j++; } if (FcDebug () & FC_DBG_MATCHV) { printf (" %s: %g ", object, best); FcValueListPrint (v1orig); printf (", "); FcValueListPrint (v2orig); printf ("\n"); } if (value) { int weak = _FcMatchers[i].weak; int strong = _FcMatchers[i].strong; if (weak == strong) value[strong] += best; else { value[weak] += bestWeak; value[strong] += bestStrong; } } return FcTrue; }
/* * Scan the specified directory and construct a cache of its contents */ FcCache * FcDirCacheScan (const FcChar8 *dir, FcConfig *config) { FcStrSet *dirs; FcBool ret = FcTrue; FcFontSet *set; FcCache *cache = NULL; struct stat dir_stat; if (FcDebug () & FC_DBG_FONTSET) printf ("cache scan dir %s\n", dir); if (FcStatChecksum ((char *) dir, &dir_stat) < 0) { if (errno != ENOENT) ret = FcFalse; goto bail; } set = FcFontSetCreate(); if (!set) { ret = FcFalse; goto bail; } dirs = FcStrSetCreate (); if (!dirs) { ret = FcFalse; goto bail1; } /* * Scan the dir */ if (!FcDirScanConfig (set, dirs, NULL, dir, FcTrue, config)) { ret = FcFalse; goto bail2; } /* * Build the cache object */ cache = FcDirCacheBuild (set, dir, &dir_stat, dirs); if (!cache) { ret = FcFalse; goto bail2; } /* * Write out the cache file, ignoring any troubles */ FcDirCacheWrite (cache, config); bail2: FcStrSetDestroy (dirs); bail1: FcFontSetDestroy (set); bail: return cache; }
FcBool FcDirScanConfig (FcFontSet *set, FcStrSet *dirs, FcBlanks *blanks, const FcChar8 *dir, FcBool force, /* XXX unused */ FcConfig *config) { DIR *d; struct dirent *e; FcStrSet *files; FcChar8 *file; FcChar8 *base; FcBool ret = FcTrue; int i; if (!force) return FcFalse; if (!set && !dirs) return FcTrue; if (!blanks) blanks = FcConfigGetBlanks (config); /* freed below */ file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1); if (!file) { ret = FcFalse; goto bail; } strcpy ((char *) file, (char *) dir); strcat ((char *) file, "/"); base = file + strlen ((char *) file); if (FcDebug () & FC_DBG_SCAN) printf ("\tScanning dir %s\n", dir); d = opendir ((char *) dir); if (!d) { /* Don't complain about missing directories */ if (errno != ENOENT) ret = FcFalse; goto bail; } files = FcStrSetCreate (); if (!files) { ret = FcFalse; goto bail1; } while ((e = readdir (d))) { if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN) { strcpy ((char *) base, (char *) e->d_name); if (!FcStrSetAdd (files, file)) { ret = FcFalse; goto bail2; } } } /* * Sort files to make things prettier */ qsort(files->strs, files->num, sizeof(FcChar8 *), cmpstringp); /* * Scan file files to build font patterns */ for (i = 0; i < files->num; i++) FcFileScanConfig (set, dirs, blanks, files->strs[i], config); bail2: FcStrSetDestroy (files); bail1: closedir (d); bail: return ret; }
static FcBool FcCompareValueList (FcObject object, const FcMatcher *match, FcValueListPtr v1orig, /* pattern */ FcValueListPtr v2orig, /* target */ FcValue *bestValue, double *value, int *n, FcResult *result) { FcValueListPtr v1, v2; double v, best, bestStrong, bestWeak; int j, k, pos = 0; if (!match) { if (bestValue) *bestValue = FcValueCanonicalize(&v2orig->value); if (n) *n = 0; return FcTrue; } best = 1e99; bestStrong = 1e99; bestWeak = 1e99; j = 1; for (v1 = v1orig; v1; v1 = FcValueListNext(v1)) { for (v2 = v2orig, k = 0; v2; v2 = FcValueListNext(v2), k++) { v = (match->compare) (&v1->value, &v2->value); if (v < 0) { *result = FcResultTypeMismatch; return FcFalse; } v = v * 1000 + j; if (v < best) { if (bestValue) *bestValue = FcValueCanonicalize(&v2->value); best = v; pos = k; } if (v1->binding == FcValueBindingStrong) { if (v < bestStrong) bestStrong = v; } else { if (v < bestWeak) bestWeak = v; } } j++; } if (FcDebug () & FC_DBG_MATCHV) { printf (" %s: %g ", FcObjectName (object), best); FcValueListPrint (v1orig); printf (", "); FcValueListPrint (v2orig); printf ("\n"); } if (value) { int weak = match->weak; int strong = match->strong; if (weak == strong) value[strong] += best; else { value[weak] += bestWeak; value[strong] += bestStrong; } } if (n) *n = pos; return FcTrue; }
FcLangSet * FcFreeTypeLangSet (const FcCharSet *charset, const FcChar8 *exclusiveLang) { int i, j; FcChar32 missing; const FcCharSet *exclusiveCharset = 0; FcLangSet *ls; if (exclusiveLang) exclusiveCharset = FcLangGetCharSet (exclusiveLang); ls = FcLangSetCreate (); if (!ls) return 0; if (FcDebug() & FC_DBG_LANGSET) { printf ("font charset\n"); FcCharSetPrint (charset); printf ("\n"); } for (i = 0; i < NUM_LANG_CHAR_SET; i++) { if (FcDebug() & FC_DBG_LANGSET) { printf ("%s charset\n", fcLangCharSets[i].lang); FcCharSetPrint (&fcLangCharSets[i].charset); printf ("\n"); } /* * Check for Han charsets to make fonts * which advertise support for a single language * not support other Han languages */ if (exclusiveCharset && FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang)) { if (fcLangCharSets[i].charset.num != exclusiveCharset->num) continue; for (j = 0; j < fcLangCharSets[i].charset.num; j++) if (FcCharSetLeaf(&fcLangCharSets[i].charset, j) != FcCharSetLeaf(exclusiveCharset, j)) continue; } missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset); if (FcDebug() & FC_DBG_SCANV) { if (missing && missing < 10) { FcCharSet *missed = FcCharSetSubtract (&fcLangCharSets[i].charset, charset); FcChar32 ucs4; FcChar32 map[FC_CHARSET_MAP_SIZE]; FcChar32 next; printf ("\n%s(%u) ", fcLangCharSets[i].lang, missing); printf ("{"); for (ucs4 = FcCharSetFirstPage (missed, map, &next); ucs4 != FC_CHARSET_DONE; ucs4 = FcCharSetNextPage (missed, map, &next)) { int i, j; for (i = 0; i < FC_CHARSET_MAP_SIZE; i++) if (map[i]) { for (j = 0; j < 32; j++) if (map[i] & (1 << j)) printf (" %04x", ucs4 + i * 32 + j); } } printf (" }\n\t"); FcCharSetDestroy (missed); } else printf ("%s(%u) ", fcLangCharSets[i].lang, missing); } if (!missing) FcLangSetBitSet (ls, i); } if (FcDebug() & FC_DBG_SCANV) printf ("\n"); return ls; }