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; }
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; }
void FcLangSetDestroy (FcLangSet *ls) { if (ls->extra) FcStrSetDestroy (ls->extra); FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet)); free (ls); }
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; }
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 FcConfigDestroy (FcConfig *config) { FcSetName set; FcExprPage *page; if (--config->ref > 0) return; if (config == _fcConfig) _fcConfig = 0; FcStrSetDestroy (config->configDirs); FcStrSetDestroy (config->fontDirs); FcStrSetDestroy (config->cacheDirs); FcStrSetDestroy (config->configFiles); FcStrSetDestroy (config->acceptGlobs); FcStrSetDestroy (config->rejectGlobs); FcFontSetDestroy (config->acceptPatterns); FcFontSetDestroy (config->rejectPatterns); if (config->blanks) FcBlanksDestroy (config->blanks); FcSubstDestroy (config->substPattern); FcSubstDestroy (config->substFont); FcSubstDestroy (config->substScan); for (set = FcSetSystem; set <= FcSetApplication; set++) if (config->fonts[set]) FcFontSetDestroy (config->fonts[set]); page = config->expr_pool; while (page) { FcExprPage *next = page->next_page; FcMemFree (FC_MEM_EXPR, sizeof (FcExprPage)); free (page); page = next; } free (config); FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig)); }
void FcConfigDestroy (FcConfig *config) { FcSetName set; FcExprPage *page; if (FcRefDec (&config->ref) != 1) return; (void) fc_atomic_ptr_cmpexch (&_fcConfig, config, NULL); FcStrSetDestroy (config->configDirs); FcStrSetDestroy (config->fontDirs); FcStrSetDestroy (config->cacheDirs); FcStrSetDestroy (config->configFiles); FcStrSetDestroy (config->acceptGlobs); FcStrSetDestroy (config->rejectGlobs); FcFontSetDestroy (config->acceptPatterns); FcFontSetDestroy (config->rejectPatterns); if (config->blanks) FcBlanksDestroy (config->blanks); FcSubstDestroy (config->substPattern); FcSubstDestroy (config->substFont); FcSubstDestroy (config->substScan); for (set = FcSetSystem; set <= FcSetApplication; set++) if (config->fonts[set]) FcFontSetDestroy (config->fonts[set]); page = config->expr_pool; while (page) { FcExprPage *next = page->next_page; free (page); page = next; } if (config->sysRoot) FcStrFree (config->sysRoot); free (config); }
int main (int argc, char **argv) { int brief = 0; FcChar8 *format = NULL; int i; FcFontSet *fs; #if HAVE_GETOPT_LONG || HAVE_GETOPT int c; setlocale (LC_ALL, ""); #if HAVE_GETOPT_LONG while ((c = getopt_long (argc, argv, "bf:Vh", longopts, NULL)) != -1) #else while ((c = getopt (argc, argv, "bf:Vh")) != -1) #endif { switch (c) { case 'b': brief = 1; break; case 'f': format = (FcChar8 *) strdup (optarg); break; case 'V': fprintf (stderr, "fontconfig version %d.%d.%d\n", FC_MAJOR, FC_MINOR, FC_REVISION); exit (0); case 'h': usage (argv[0], 0); default: usage (argv[0], 1); } } i = optind; #else i = 1; #endif if (i == argc) usage (argv[0], 1); fs = FcFontSetCreate (); for (; i < argc; i++) { const FcChar8 *file = (FcChar8*) argv[i]; if (!FcFileIsDir (file)) FcFileScan (fs, NULL, NULL, NULL, file, FcTrue); else { FcStrSet *dirs = FcStrSetCreate (); FcStrList *strlist = FcStrListCreate (dirs); do { FcDirScan (fs, dirs, NULL, NULL, file, FcTrue); } while ((file = FcStrListNext (strlist))); FcStrListDone (strlist); FcStrSetDestroy (dirs); } } for (i = 0; i < fs->nfont; i++) { FcPattern *pat = fs->fonts[i]; if (brief) { FcPatternDel (pat, FC_CHARSET); FcPatternDel (pat, FC_LANG); } if (format) { FcChar8 *s; s = FcPatternFormat (pat, format); if (s) { printf ("%s", s); FcStrFree (s); } } else { FcPatternPrint (pat); } } FcFontSetDestroy (fs); FcFini (); return i > 0 ? 0 : 1; }
int main (int argc, char **argv) { int i; int ret = 0; FcFontSet *fs; FcStrSet *dirs; FcStrSet *args = NULL; FcStrList *arglist; FcCache *cache; FcConfig *config; FcChar8 *arg; int verbose = 0; int recurse = 0; FcBool first = FcTrue; #if HAVE_GETOPT_LONG || HAVE_GETOPT int c; #if HAVE_GETOPT_LONG while ((c = getopt_long (argc, argv, "Vvrh", longopts, NULL)) != -1) #else while ((c = getopt (argc, argv, "Vvrh")) != -1) #endif { switch (c) { case 'V': fprintf (stderr, "fontconfig version %d.%d.%d\n", FC_MAJOR, FC_MINOR, FC_REVISION); exit (0); case 'v': verbose++; break; case 'r': recurse++; break; case 'h': usage (argv[0], 0); default: usage (argv[0], 1); } } i = optind; #else i = 1; #endif config = FcInitLoadConfig (); if (!config) { fprintf (stderr, "%s: Can't init font config library\n", argv[0]); return 1; } FcConfigSetCurrent (config); args = FcStrSetCreate (); if (!args) { fprintf (stderr, "%s: malloc failure\n", argv[0]); return 1; } if (i < argc) { for (; i < argc; i++) { if (!FcStrSetAddFilename (args, (const FcChar8 *) argv[i])) { fprintf (stderr, "%s: malloc failure\n", argv[0]); return 1; } } arglist = FcStrListCreate (args); if (!arglist) { fprintf (stderr, "%s: malloc failure\n", argv[0]); return 1; } } else { recurse++; arglist = FcConfigGetFontDirs (config); while ((arg = FcStrListNext (arglist))) if (!FcStrSetAdd (args, arg)) { fprintf (stderr, "%s: malloc failure\n", argv[0]); return 1; } FcStrListDone (arglist); } arglist = FcStrListCreate (args); if (!arglist) { fprintf (stderr, "%s: malloc failure\n", argv[0]); return 1; } while ((arg = FcStrListNext (arglist))) { int j; FcChar8 *cache_file = NULL; struct stat file_stat; if (FcFileIsDir (arg)) cache = FcDirCacheLoad (arg, config, &cache_file); else cache = FcDirCacheLoadFile (arg, &file_stat); if (!cache) { perror ((char *) arg); ret++; continue; } dirs = FcStrSetCreate (); fs = FcCacheCopySet (cache); for (j = 0; j < FcCacheNumSubdir (cache); j++) { FcStrSetAdd (dirs, FcCacheSubdir (cache, j)); if (recurse) FcStrSetAdd (args, FcCacheSubdir (cache, j)); } if (verbose) { if (!first) printf ("\n"); printf ("Directory: %s\nCache: %s\n--------\n", FcCacheDir(cache), cache_file ? cache_file : arg); first = FcFalse; } cache_print_set (fs, dirs, FcCacheDir (cache), verbose); FcStrSetDestroy (dirs); FcFontSetDestroy (fs); FcDirCacheUnload (cache); if (cache_file) FcStrFree (cache_file); } FcFini (); return 0; }
FcConfig * FcConfigCreate (void) { FcSetName set; FcConfig *config; config = malloc (sizeof (FcConfig)); if (!config) goto bail0; config->configDirs = FcStrSetCreate (); if (!config->configDirs) goto bail1; config->configFiles = FcStrSetCreate (); if (!config->configFiles) goto bail2; config->fontDirs = FcStrSetCreate (); if (!config->fontDirs) goto bail3; config->acceptGlobs = FcStrSetCreate (); if (!config->acceptGlobs) goto bail4; config->rejectGlobs = FcStrSetCreate (); if (!config->rejectGlobs) goto bail5; config->acceptPatterns = FcFontSetCreate (); if (!config->acceptPatterns) goto bail6; config->rejectPatterns = FcFontSetCreate (); if (!config->rejectPatterns) goto bail7; config->cacheDirs = FcStrSetCreate (); if (!config->cacheDirs) goto bail8; config->blanks = 0; config->substPattern = 0; config->substFont = 0; config->substScan = 0; config->maxObjects = 0; for (set = FcSetSystem; set <= FcSetApplication; set++) config->fonts[set] = 0; config->rescanTime = time(0); config->rescanInterval = 30; config->expr_pool = NULL; config->sysRoot = NULL; FcRefInit (&config->ref, 1); return config; bail8: FcFontSetDestroy (config->rejectPatterns); bail7: FcFontSetDestroy (config->acceptPatterns); bail6: FcStrSetDestroy (config->rejectGlobs); bail5: FcStrSetDestroy (config->acceptGlobs); bail4: FcStrSetDestroy (config->fontDirs); bail3: FcStrSetDestroy (config->configFiles); bail2: FcStrSetDestroy (config->configDirs); bail1: free (config); bail0: return 0; }
int main (int argc, char **argv) { FcStrSet *dirs; FcStrList *list; FcBool verbose = FcFalse; FcBool force = FcFalse; FcBool really_force = FcFalse; FcBool systemOnly = FcFalse; FcConfig *config; int i; int changed; int ret; #if HAVE_GETOPT_LONG || HAVE_GETOPT int c; #if HAVE_GETOPT_LONG while ((c = getopt_long (argc, argv, "frsVvh", longopts, NULL)) != -1) #else while ((c = getopt (argc, argv, "frsVvh")) != -1) #endif { switch (c) { case 'r': really_force = FcTrue; /* fall through */ case 'f': force = FcTrue; break; case 's': systemOnly = FcTrue; break; case 'V': fprintf (stderr, "fontconfig version %d.%d.%d\n", FC_MAJOR, FC_MINOR, FC_REVISION); exit (0); case 'v': verbose = FcTrue; break; case 'h': usage (argv[0], 0); default: usage (argv[0], 1); } } i = optind; #else i = 1; #endif if (systemOnly) FcConfigEnableHome (FcFalse); config = FcInitLoadConfig (); if (!config) { fprintf (stderr, "%s: Can't init font config library\n", argv[0]); return 1; } FcConfigSetCurrent (config); if (argv[i]) { dirs = FcStrSetCreate (); if (!dirs) { fprintf (stderr, "%s: Can't create list of directories\n", argv[0]); return 1; } while (argv[i]) { if (!FcStrSetAddFilename (dirs, (FcChar8 *) argv[i])) { fprintf (stderr, "%s: Can't add directory\n", argv[0]); return 1; } i++; } list = FcStrListCreate (dirs); FcStrSetDestroy (dirs); } else list = FcConfigGetConfigDirs (config); if ((processed_dirs = FcStrSetCreate()) == NULL) { fprintf(stderr, "Cannot malloc\n"); return 1; } changed = 0; ret = scanDirs (list, config, force, really_force, verbose, &changed); /* * Try to create CACHEDIR.TAG anyway. * This expects the fontconfig cache directory already exists. * If it doesn't, it won't be simply created. */ FcCacheCreateTagFile (config); FcStrSetDestroy (processed_dirs); cleanCacheDirectories (config, verbose); /* * Now we need to sleep a second (or two, to be extra sure), to make * sure that timestamps for changes after this run of fc-cache are later * then any timestamps we wrote. We don't use gettimeofday() because * sleep(3) can't be interrupted by a signal here -- this isn't in the * library, and there aren't any signals flying around here. */ FcConfigDestroy (config); FcFini (); if (changed) sleep (2); if (verbose) printf ("%s: %s\n", argv[0], ret ? "failed" : "succeeded"); return ret; }
static int scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force, FcBool verbose, int *changed) { int ret = 0; const FcChar8 *dir; FcStrSet *subdirs; FcStrList *sublist; FcCache *cache; struct stat statb; FcBool was_valid; int i; /* * Now scan all of the directories into separate databases * and write out the results */ while ((dir = FcStrListNext (list))) { if (verbose) { printf ("%s: ", dir); fflush (stdout); } if (!dir) { if (verbose) printf ("skipping, no such directory\n"); continue; } if (FcStrSetMember (processed_dirs, dir)) { if (verbose) printf ("skipping, looped directory detected\n"); continue; } if (stat ((char *) dir, &statb) == -1) { switch (errno) { case ENOENT: case ENOTDIR: if (verbose) printf ("skipping, no such directory\n"); break; default: fprintf (stderr, "\"%s\": ", dir); perror (""); ret++; break; } continue; } if (!S_ISDIR (statb.st_mode)) { fprintf (stderr, "\"%s\": not a directory, skipping\n", dir); continue; } if (really_force) FcDirCacheUnlink (dir, config); cache = NULL; was_valid = FcFalse; if (!force) { cache = FcDirCacheLoad (dir, config, NULL); if (cache) was_valid = FcTrue; } if (!cache) { (*changed)++; cache = FcDirCacheRead (dir, FcTrue, config); if (!cache) { fprintf (stderr, "%s: error scanning\n", dir); ret++; continue; } } if (was_valid) { if (verbose) printf ("skipping, existing cache is valid: %d fonts, %d dirs\n", FcCacheNumFont (cache), FcCacheNumSubdir (cache)); } else { if (verbose) printf ("caching, new cache contents: %d fonts, %d dirs\n", FcCacheNumFont (cache), FcCacheNumSubdir (cache)); if (!FcDirCacheValid (dir)) { fprintf (stderr, "%s: failed to write cache\n", dir); (void) FcDirCacheUnlink (dir, config); ret++; } } subdirs = FcStrSetCreate (); if (!subdirs) { fprintf (stderr, "%s: Can't create subdir set\n", dir); ret++; FcDirCacheUnload (cache); continue; } for (i = 0; i < FcCacheNumSubdir (cache); i++) FcStrSetAdd (subdirs, FcCacheSubdir (cache, i)); FcDirCacheUnload (cache); sublist = FcStrListCreate (subdirs); FcStrSetDestroy (subdirs); if (!sublist) { fprintf (stderr, "%s: Can't create subdir list\n", dir); ret++; continue; } FcStrSetAdd (processed_dirs, dir); ret += scanDirs (sublist, config, force, really_force, verbose, changed); } FcStrListDone (list); return ret; }
/* * 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; }
void font_config_magic_class:: add_entry(FcPattern *p) { FcMagicValue<FcChar8*> family_name, file_name, foundary_name, font_style; FcMagicValue<int> font_index, font_weight, font_slant; FcMagicValue<FcLangSet*> lang; FcGetMagicValue(p, FC_FILE, file_name); if(file_name.m_exists) { FontEntry entry_key; WRATHFontConfig::FontSpecification entry; GetPairFromFcMagicValue(entry_key.m_filename, file_name); FcGetMagicValue(p, FC_INDEX, font_index); GetPairFromFcMagicValue(entry_key.m_face_index, font_index); entry.font()=WRATHFontDatabase::fetch_font_entry(entry_key.m_filename, entry_key.m_face_index); FcGetMagicValue(p, FC_FAMILY, family_name); GetPairFromFcMagicValue(entry.m_fontconfig_details.m_family_name, family_name); FcGetMagicValue(p, FC_FOUNDRY, foundary_name); GetPairFromFcMagicValue(entry.m_fontconfig_details.m_foundary_name, foundary_name); FcGetMagicValue(p, FC_WEIGHT, font_weight); GetPairFromFcMagicValue(entry.m_fontconfig_details.m_weight, font_weight); FcGetMagicValue(p, FC_SLANT, font_slant); GetPairFromFcMagicValue(entry.m_fontconfig_details.m_slant, font_slant); FcGetMagicValue(p, FC_STYLE, font_style); GetPairFromFcMagicValue(entry.m_fontconfig_details.m_style, font_style); #if (FC_MAJOR>=2 && FC_MINOR>=7) || (FC_MAJOR>=3) { FcGetMagicValue(p, FC_LANG, lang); if(lang.m_exists) { FcStrSet *langs_as_strs; FcStrList *iter; FcChar8 *current; langs_as_strs=FcLangSetGetLangs(lang.m_value); //do we need to free this thing?? iter=FcStrListCreate(langs_as_strs); for(current=FcStrListNext(iter); current; current=FcStrListNext(iter)) { const char *str(reinterpret_cast<const char*>(current)); entry.m_fontconfig_details.m_languages.insert(std::string(str)); } FcStrListDone(iter); FcStrSetDestroy(langs_as_strs); } } #endif WRATHassert(m_font_list.find(entry.font())==m_font_list.end()); m_font_list[entry.font()]=entry; } }