>>> OK. So how can an application find out that the font cache >>> creation (or update) is very time consuming? Is it at least >>> possible to catch the situation of a first run? >> >> current implementation assumes the users will runs fc-cache to >> create caches before running. as such APIs isn't available at this >> point, so no, it isn't. though we discussed a bit these days, if it >> is wrong assumption, we may need to think about another way IMHO. > > Given that many applications that use fontconfig are ported to Windows > today, the assumption of running `fc-cache' in advance is becoming > much weaker IMHO – there is no longer a global fontconfig cache, since > every program comes with its own stuff.[*] I hate this approach a lot, > but we have to face the reality on this platform... I propose to export an inner API, FcDirCacheValidConfig (). I've attached the patch `0001-Export-FcDirCacheValidConfig'. Currently there is no way for applications to detect `fontconfig needs a long time' for cache updating. There is also no way for applications to find out whether font cache updating is necessary or not, in a short time. The already exported FcDirCacheValid () API updates all caches. In other words, it takes a long time when updating is necessary. I've investigated the point where FcDirCacheValid () takes a long time. As a result, I noticed that inner API, FcDirCacheValidConfig () does not take a long time, that is, it does not update the cache. So applications can find out whether updating caches are necessary or not by this function, in a short time. I've attached `is_neccesary_update.cc' as a sample application using this function. It can display directories that require cache updates. An application may be able to estimate `fontconfig needs a long time' for cache updating, since it become to be able to find out the directories that requires cache updates.
>From b46df92964e9b3c225c59efb6c1aa81dad28c874 Mon Sep 17 00:00:00 2001 From: Masamichi Hosoda <trueroad@xxxxxxxxxxx> Date: Wed, 23 Nov 2016 20:57:49 +0900 Subject: [PATCH] Export FcDirCacheValidConfig () FcDirCacheValidConfig () does not update caches. So applications can find out whether updating caches are necessary or not by this function. --- doc/fcdircache.fncs | 11 +++++++++++ fontconfig/fontconfig.h | 3 +++ src/fccache.c | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/doc/fcdircache.fncs b/doc/fcdircache.fncs index faeba29..6b1fe6c 100644 --- a/doc/fcdircache.fncs +++ b/doc/fcdircache.fncs @@ -41,6 +41,17 @@ Returns FcTrue if <parameter>dir</parameter> has an associated valid cache file, else returns FcFalse @@ +@RET@ FcBool +@FUNC@ FcDirCacheValidConfig +@TYPE1@ const FcChar8 * @ARG1@ dir +@TYPE2@ FcConfig * @ARG2@ config +@PURPOSE@ check directory cache without cache updating +@DESC@ +Returns FcTrue if <parameter>dir</parameter> has an associated valid cache +file, else returns FcFalse. This function does not update caches. +@SINCE@ 2.12.2 +@@ + @RET@ FcCache * @FUNC@ FcDirCacheLoad @TYPE1@ const FcChar8 * @ARG1@ dir diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h index 5c72b22..6598a27 100644 --- a/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig.h @@ -347,6 +347,9 @@ FcPublic FcBool FcDirCacheValid (const FcChar8 *cache_file); FcPublic FcBool +FcDirCacheValidConfig (const FcChar8 *cache_file, FcConfig *config); + +FcPublic FcBool FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose); FcPublic void diff --git a/src/fccache.c b/src/fccache.c index 6f3c68a..0948482 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -844,7 +844,7 @@ FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct return ret; } -static FcBool +FcBool FcDirCacheValidConfig (const FcChar8 *dir, FcConfig *config) { return FcDirCacheProcess (config, dir, -- 2.8.3
#include <cstdio> #include <iostream> #include <dirent.h> #include <errno.h> #include <sys/stat.h> #include <fontconfig/fontconfig.h> int check_cache (FcConfig *config); int scan_dirs (FcStrList *list, FcConfig *config); int scan_dir (const FcChar8 *dir, FcConfig *config); int main () { FcInitLoadConfig (); FcConfig *config = FcConfigCreate (); FcChar8 *default_conf = FcConfigFilename (NULL); FcConfigParseAndLoad (config, default_conf, FcTrue); FcStrFree (default_conf); int ret = check_cache (config); std::cout << std::endl << "font cache updating is "; if (ret) std::cout << "neccesary (" << ret << " dirs) " << std::endl; else std::cout << "not neccesary" << std::endl; return 0; } int check_cache (FcConfig *config) { FcStrList *list = FcConfigGetConfigDirs (config); int ret = scan_dirs (list, config); FcStrListDone (list); return ret; } int scan_dirs (FcStrList *list, FcConfig *config) { int ret = 0; const FcChar8 *dir; while ((dir = FcStrListNext (list))) ret += scan_dir (dir, config); return ret; } int scan_dir (const FcChar8 *dir, FcConfig *config) { std::cout << dir << " - " << std::flush; struct stat statb; if (stat ((char *)dir, &statb) == -1) { switch (errno) { case ENOENT: case ENOTDIR: std::cout << "no such directory" << std::endl; return 0; default: perror (""); return 0; } } int ret = 0; if (FcDirCacheValidConfig (dir, config)) { std::cout << "valid" << std::endl; } else { std::cout << "***INVALID*** - neccesary updating" << std::endl; ret++; } DIR *dp = opendir ((char*)dir); struct dirent *dent; while ((dent = readdir (dp)) != NULL) { if (dent->d_type == DT_DIR && dent->d_name[0] != '.') { std::string subdir ((char*)dir); subdir += "/"; subdir += dent->d_name; ret += scan_dir ((FcChar8*)subdir.c_str (), config); } } closedir (dp); return ret; }
_______________________________________________ Fontconfig mailing list Fontconfig@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/fontconfig