Re: how to detect `fontconfig needs a long time'

Masamichi Hosoda <[email protected]>
Newsgroups gmane.comp.fonts.fontconfig
Message-ID <[email protected]>
>>> 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.

_______________________________________________
Fontconfig mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/fontconfig
0001-Export-FcDirCacheValidConfig.patch (text/x-patch, 2 KB)
From b46df92964e9b3c225c59efb6c1aa81dad28c874 Mon Sep 17 00:00:00 2001
From: Masamichi Hosoda <[email protected]>
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
is_neccesary_update.cc (text/plain, 1.9 KB)
#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;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.