FcBool FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config) { FcChar8 *cache_hashed = NULL; FcChar8 cache_base[CACHEBASE_LEN]; FcStrList *list; FcChar8 *cache_dir; const FcChar8 *sysroot = FcConfigGetSysRoot (config); FcDirCacheBasename (dir, cache_base); list = FcStrListCreate (config->cacheDirs); if (!list) return FcFalse; while ((cache_dir = FcStrListNext (list))) { if (sysroot) cache_hashed = FcStrBuildFilename (sysroot, cache_dir, cache_base, NULL); else cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL); if (!cache_hashed) break; (void) unlink ((char *) cache_hashed); FcStrFree (cache_hashed); } FcStrListDone (list); /* return FcFalse if something went wrong */ if (cache_dir) return FcFalse; return FcTrue; }
static void xfce_xsettings_helper_fc_monitor (XfceXSettingsHelper *helper, FcStrList *files) { const gchar *path; GFile *file; GFileMonitor *monitor; if (G_UNLIKELY (files == NULL)) return; for (;;) { path = (const gchar *) FcStrListNext (files); if (G_UNLIKELY (path == NULL)) break; file = g_file_new_for_path (path); monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL); g_object_unref (G_OBJECT (file)); if (G_LIKELY (monitor != NULL)) { g_ptr_array_add (helper->fc_monitors, monitor); g_signal_connect_swapped (G_OBJECT (monitor), "changed", G_CALLBACK (xfce_xsettings_helper_fc_changed), helper); xfsettings_dbg_filtered (XFSD_DEBUG_FONTCONFIG, "monitoring \"%s\"", path); } } FcStrListDone (files); }
/* * 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 void create_file_monitors (FontViewModel *self) { FcConfig *config; FcStrList *str_list; FcChar8 *path; GFile *file; GFileMonitor *monitor; config = FcConfigGetCurrent (); str_list = FcConfigGetFontDirs (config); while ((path = FcStrListNext (str_list)) != NULL) { file = g_file_new_for_path ((const gchar *) path); monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL); if (monitor != NULL) { self->priv->monitors = g_list_prepend (self->priv->monitors, monitor); g_signal_connect (monitor, "changed", G_CALLBACK (file_monitor_changed_cb), self); } g_object_unref (file); } FcStrListDone (str_list); }
static void monitor_files (GPtrArray *monitors, FcStrList *list, gpointer data) { const char *str; while ((str = (const char *) FcStrListNext (list))) { GFile *file; GFileMonitor *monitor; file = g_file_new_for_path (str); monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL); g_object_unref (file); if (!monitor) continue; g_signal_connect (monitor, "changed", G_CALLBACK (stuff_changed), data); g_ptr_array_add (monitors, monitor); } FcStrListDone (list); }
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 cache_print_set (FcFontSet *set, FcStrSet *dirs, const FcChar8 *base_name, FcBool verbose) { FcChar8 *dir; const FcChar8 *base; int n; int ndir = 0; FcStrList *list; list = FcStrListCreate (dirs); if (!list) goto bail2; while ((dir = FcStrListNext (list))) { base = file_base_name (base_name, dir); if (!write_string (stdout, base)) goto bail3; if (PUTC (' ', stdout) == EOF) goto bail3; if (!write_int (stdout, 0)) goto bail3; if (PUTC (' ', stdout) == EOF) goto bail3; if (!write_string (stdout, FC_FONT_FILE_DIR)) goto bail3; if (PUTC ('\n', stdout) == EOF) goto bail3; ndir++; } for (n = 0; n < set->nfont; n++) { FcPattern *font = set->fonts[n]; FcChar8 *s; s = FcPatternFormat (font, (const FcChar8 *) "%{=fccat}\n"); if (s) { printf ("%s", s); FcStrFree (s); } } if (verbose && !set->nfont && !ndir) printf ("<empty>\n"); FcStrListDone (list); return FcTrue; bail3: FcStrListDone (list); bail2: return FcFalse; }
GeeArrayList * FcListUserDirs(void) { FcChar8 * directory; FcStrList * fdlist; GeeArrayList * dirlist = gee_array_list_new(G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free0, NULL, NULL, NULL); g_assert(FcInit()); fdlist = FcConfigGetConfigDirs(NULL); while ((directory = FcStrListNext(fdlist))) if (get_file_owner((const gchar *) directory) == 0) gee_abstract_collection_add((GeeAbstractCollection *) dirlist, directory); FcStrListDone(fdlist); return dirlist; }
// // Obtain location of config file to use. // // For system, prefer the following: // // <...>/config.d/00kde.conf = preferred method from FCConfig >= 2.3 // <...>/local.conf // // Non-system, prefer: // // $HOME/<...>/.fonts.conf // $HOME/<...>/fonts.conf // QString getConfigFile(bool system) { #if (FC_VERSION>=20300) static const char constKdeRootFcFile[] = "00kde.conf"; #endif FcStrList *list=FcConfigGetConfigFiles(FcConfigGetCurrent()); QStringList files; FcChar8 *file; QString home(Misc::dirSyntax(QDir::homePath())); while((file=FcStrListNext(list))) { QString f((const char *)file); if(Misc::fExists(f)) { // For nonsystem, only consider file within $HOME if(system || 0==Misc::fileSyntax(f).indexOf(home)) files.append(f); } #if (FC_VERSION>=20300) if(system && Misc::dExists(f) && (f.contains(QRegExp("/conf\\.d/?$")) || f.contains(QRegExp("/conf\\.d?$"))) ) return Misc::dirSyntax(f)+constKdeRootFcFile; // This ones good enough for me! #endif } // // Go through list of files, looking for the preferred one... if(files.count()) { QStringList::const_iterator it(files.begin()), end(files.end()); for(; it!=end; ++it) if(-1!=(*it).indexOf(QRegExp(system ? "/local\\.conf$" : "/\\.?fonts\\.conf$"))) return *it; return files.front(); // Just return the 1st one... } else // Hmmm... no known files? return system ? "/etc/fonts/local.conf" : Misc::fileSyntax(home+"/.fonts.conf"); }
static FcBool cleanCacheDirectories (FcConfig *config, FcBool verbose) { FcStrList *cache_dirs = FcConfigGetCacheDirs (config); FcChar8 *cache_dir; FcBool ret = FcTrue; if (!cache_dirs) return FcFalse; while ((cache_dir = FcStrListNext (cache_dirs))) { if (!FcDirCacheClean (cache_dir, verbose)) { ret = FcFalse; break; } } FcStrListDone (cache_dirs); return ret; }
GeeArrayList * FcListDirs(gboolean recursive) { FcChar8 * directory; FcStrList * fdlist; GeeArrayList * dirlist = gee_array_list_new(G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free0, NULL, NULL, NULL); g_assert(FcInit()); if (recursive) fdlist = FcConfigGetFontDirs(NULL); else fdlist = FcConfigGetConfigDirs(NULL); while ((directory = FcStrListNext(fdlist))) gee_abstract_collection_add((GeeAbstractCollection *) dirlist, directory); FcStrListDone(fdlist); return dirlist; }
static FcFileTime FcConfigNewestFile (FcStrSet *files) { FcStrList *list = FcStrListCreate (files); FcFileTime newest = { 0, FcFalse }; FcChar8 *file; struct stat statb; if (list) { while ((file = FcStrListNext (list))) if (FcStat (file, &statb) == 0) if (!newest.set || statb.st_mtime - newest.time > 0) { newest.set = FcTrue; newest.time = statb.st_mtime; } FcStrListDone (list); } return newest; }
FcStrSet *fcinfo_languages(const FcPattern *filter) { FcObjectSet *objectset; FcFontSet *fontset; FcLangSet *union_langset; FcStrSet *result; int f; FcInit(); objectset = FcObjectSetBuild(FC_LANG, NULL); fontset = FcFontList(NULL, (FcPattern *)filter, objectset); FcObjectSetDestroy(objectset); union_langset = FcLangSetCreate(); for (f = 0; f < fontset->nfont; f++) { FcLangSet *langset; FcStrList *strlist; FcChar8 *lang; if (FcPatternGetLangSet(fontset->fonts[f], FC_LANG, 0, &langset) != FcResultMatch) continue; if (! langset) continue; strlist = FcStrListCreate(FcLangSetGetLangs(langset)); while ((lang = FcStrListNext(strlist))) if (FcLangSetHasLang(union_langset, lang)) FcLangSetAdd(union_langset, FcStrCopy(lang)); } result = FcLangSetGetLangs(union_langset); FcFontSetDestroy(fontset); FcLangSetDestroy(union_langset); return result; }
int main(int argc, char *argv[]) { #ifdef HAVE_GETOPT_H static struct option options[]= { { "configure_x", 0, 0, 'x' }, { "configure_gs", 0, 0, 'g' }, { "add_to_fc_cfg", 0, 0, 'f' }, { "add_to_x_cfg", 0, 0, 'a' }, { "refresh_x", 0, 0, 'r' }, { "refresh_xfs", 0, 0, 's' }, { 0, 0, 0, 0 } }; #endif int c=0, rv=0; bool doX=false, doGs=false, addToX=false, addToFc=false, refreshX=false, refreshXfs=false, root=KFI::Misc::root(); #ifdef HAVE_GETOPT_H int optIndex; while(-1!=(c=getopt_long(argc, argv, "xgfars", options, &optIndex))) #else while(-1!=(c=getopt(argc, argv, "xgfars"))) #endif switch(c) { case 'x': doX=true; break; case 'g': doGs=true; break; case 'f': addToFc=true; break; case 'a': addToX=true; break; case 'r': refreshX=true; break; case 's': refreshXfs=true; break; case '?': usage(argv[0]); break; } int left=argc-optind; bool folderRequired=doX || addToX || addToFc || (!root && doGs); if (left>1 || (0==left && folderRequired) || (!doX && !doGs && !addToX && !addToFc)) usage(argv[0]); else { QString folder; if(folderRequired) { folder=argv[optind]; unsigned int len=folder.length(); // Remove quotes... if( (folder[0]==QChar('\'') || folder[0]==QChar('\"')) && (folder[len-1]==QChar('\'') || folder[len-1]==QChar('\"'))) folder=folder.mid(1, len-2); folder=KFI::Misc::dirSyntax(folder); } if(folderRequired && !KFI::Misc::dExists(folder)) { std::cerr << "ERROR: " << QFile::encodeName(folder) << " does not exist!" << std::endl; rv=-2; } else { if(!folder.isEmpty()) { if(0==rv && addToFc) { // // Only add folder to fontconfig's config if its not already there... FcStrList *list=FcConfigGetFontDirs(FcConfigGetCurrent()); FcChar8 *dir; bool found=false; while((dir=FcStrListNext(list))) if(0==KFI::Misc::dirSyntax((const char *)dir).find(folder)) found=true; if(!found) { KXftConfig *xft=new KXftConfig(KXftConfig::Dirs, root); xft->addDir(folder); rv=xft->apply() ? 0 : -3; delete xft; } } if(0==rv && addToX && root) { KFI::CXConfig *x=NULL; if((x=getXCfg(true))) { x->addPath(folder); rv=x->writeConfig() ? 0 : -4; delete x; } else rv=-5; } } if(0==rv && (doX || doGs)) { if(0==rv && doX) rv=KFI::CXConfig::configureDir(folder) ? 0 : -5; refresh(refreshX, refreshXfs, root); if(0==rv && doGs) { KFI::CFontEngine fe; rv=KFI::Fontmap::create(root ? QString::null : folder, fe) ? 0 : -6; } } else if(0==rv) refresh(refreshX, refreshXfs, root); } } return rv; }
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; }
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; }
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; }
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; } }