Module Name:    xsrc
Committed By:   mrg
Date:           Tue Aug 29 08:38:50 UTC 2017

Modified Files:
        xsrc/external/mit/fontconfig/dist/doc: FcLangSetGetLangs.3
        xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel:
            fclangsetgetlangs.html
        xsrc/external/mit/fontconfig/dist/fc-cache: fc-cache.c
        xsrc/external/mit/fontconfig/dist/src: fccache.c fccfg.c fcinit.c
            fcint.h fcmatch.c fcname.c fcstat.c
        xsrc/external/mit/fontconfig/include: config.h
Removed Files:
        xsrc/external/mit/fontconfig/dist/src: fchash.c
        xsrc/external/mit/fontconfig/include: fcalias.h fcaliastail.h
            fcftalias.h fcftaliastail.h

Log Message:
merge fontconfig 2.12.4.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 \
    xsrc/external/mit/fontconfig/dist/doc/FcLangSetGetLangs.3
cvs rdiff -u -r1.3 -r1.4 \
    
xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel/fclangsetgetlangs.html
cvs rdiff -u -r1.6 -r1.7 \
    xsrc/external/mit/fontconfig/dist/fc-cache/fc-cache.c
cvs rdiff -u -r1.8 -r1.9 xsrc/external/mit/fontconfig/dist/src/fccache.c
cvs rdiff -u -r1.2 -r1.3 xsrc/external/mit/fontconfig/dist/src/fccfg.c \
    xsrc/external/mit/fontconfig/dist/src/fcinit.c
cvs rdiff -u -r1.3 -r0 xsrc/external/mit/fontconfig/dist/src/fchash.c
cvs rdiff -u -r1.7 -r1.8 xsrc/external/mit/fontconfig/dist/src/fcint.h \
    xsrc/external/mit/fontconfig/dist/src/fcmatch.c \
    xsrc/external/mit/fontconfig/dist/src/fcname.c
cvs rdiff -u -r1.6 -r1.7 xsrc/external/mit/fontconfig/dist/src/fcstat.c
cvs rdiff -u -r1.6 -r1.7 xsrc/external/mit/fontconfig/include/config.h
cvs rdiff -u -r1.5 -r0 xsrc/external/mit/fontconfig/include/fcalias.h \
    xsrc/external/mit/fontconfig/include/fcaliastail.h
cvs rdiff -u -r1.1 -r0 xsrc/external/mit/fontconfig/include/fcftalias.h
cvs rdiff -u -r1.2 -r0 xsrc/external/mit/fontconfig/include/fcftaliastail.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: xsrc/external/mit/fontconfig/dist/doc/FcLangSetGetLangs.3
diff -u xsrc/external/mit/fontconfig/dist/doc/FcLangSetGetLangs.3:1.3 xsrc/external/mit/fontconfig/dist/doc/FcLangSetGetLangs.3:1.4
--- xsrc/external/mit/fontconfig/dist/doc/FcLangSetGetLangs.3:1.3	Sat Jul 12 04:11:34 2014
+++ xsrc/external/mit/fontconfig/dist/doc/FcLangSetGetLangs.3	Tue Aug 29 08:38:50 2017
@@ -1,5 +1,5 @@
 .\" auto-generated by docbook2man-spec from docbook-utils package
-.TH "FcLangSetGetLangs" "3" "24 3月 2014" "Fontconfig 2.11.1" ""
+.TH "FcLangSetGetLangs" "3" "05 7月 2017" "Fontconfig 2.12.4" ""
 .SH NAME
 FcLangSetGetLangs \- get the list of languages in the langset
 .SH SYNOPSIS

Index: xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel/fclangsetgetlangs.html
diff -u xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel/fclangsetgetlangs.html:1.3 xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel/fclangsetgetlangs.html:1.4
--- xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel/fclangsetgetlangs.html:1.3	Sat Jul 12 04:11:34 2014
+++ xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel/fclangsetgetlangs.html	Tue Aug 29 08:38:50 2017
@@ -10,7 +10,7 @@ REL="HOME"
 HREF="t1.html"><LINK
 REL="UP"
 TITLE="FcLangSet"
-HREF="x102.html#AEN1988"><LINK
+HREF="x102.html#AEN2016"><LINK
 REL="PREVIOUS"
 TITLE="FcGetDefaultLangs"
 HREF="fcgetdefaultlangs.html"><LINK
@@ -75,7 +75,7 @@ NAME="FCLANGSETGETLANGS"
 ><DIV
 CLASS="REFNAMEDIV"
 ><A
-NAME="AEN2306"
+NAME="AEN2334"
 ></A
 ><H2
 >Name</H2
@@ -83,7 +83,7 @@ NAME="AEN2306"
 ><DIV
 CLASS="REFSYNOPSISDIV"
 ><A
-NAME="AEN2309"
+NAME="AEN2337"
 ></A
 ><H2
 >Synopsis</H2
@@ -92,7 +92,7 @@ CLASS="FUNCSYNOPSIS"
 ><P
 ></P
 ><A
-NAME="AEN2310"
+NAME="AEN2338"
 ></A
 ><TABLE
 BORDER="0"
@@ -129,7 +129,7 @@ CLASS="PARAMETER"
 ><DIV
 CLASS="REFSECT1"
 ><A
-NAME="AEN2317"
+NAME="AEN2345"
 ></A
 ><H2
 >Description</H2
@@ -192,7 +192,7 @@ WIDTH="34%"
 ALIGN="center"
 VALIGN="top"
 ><A
-HREF="x102.html#AEN1988"
+HREF="x102.html#AEN2016"
 ACCESSKEY="U"
 >Up</A
 ></TD

Index: xsrc/external/mit/fontconfig/dist/fc-cache/fc-cache.c
diff -u xsrc/external/mit/fontconfig/dist/fc-cache/fc-cache.c:1.6 xsrc/external/mit/fontconfig/dist/fc-cache/fc-cache.c:1.7
--- xsrc/external/mit/fontconfig/dist/fc-cache/fc-cache.c:1.6	Sat Jul 12 04:11:34 2014
+++ xsrc/external/mit/fontconfig/dist/fc-cache/fc-cache.c	Tue Aug 29 08:38:50 2017
@@ -65,6 +65,7 @@
 #define _GNU_SOURCE
 #include <getopt.h>
 const struct option longopts[] = {
+    {"error-on-no-fonts", 0, 0, 'E'},
     {"force", 0, 0, 'f'},
     {"quick", 0, 0, 'q'},
     {"really-force", 0, 0, 'r'},
@@ -87,16 +88,17 @@ usage (char *program, int error)
 {
     FILE *file = error ? stderr : stdout;
 #if HAVE_GETOPT_LONG
-    fprintf (file, "usage: %s [-fqrsvVh] [--quick] [-y SYSROOT] [--force|--really-force] [--sysroot=SYSROOT] [--system-only] [--verbose] [--version] [--help] [dirs]\n",
+    fprintf (file, "usage: %s [-EfqrsvVh] [--quick] [-y SYSROOT] [--error-on-no-fonts] [--force|--really-force] [--sysroot=SYSROOT] [--system-only] [--verbose] [--version] [--help] [dirs]\n",
 	     program);
 #else
-    fprintf (file, "usage: %s [-fqrsvVh] [-y SYSROOT] [dirs]\n",
+    fprintf (file, "usage: %s [-EfqrsvVh] [-y SYSROOT] [dirs]\n",
 	     program);
 #endif
     fprintf (file, "Build font information caches in [dirs]\n"
 	     "(all directories in font configuration by default).\n");
     fprintf (file, "\n");
 #if HAVE_GETOPT_LONG
+    fprintf (file, "  -E, --error-on-no-fonts  raise an error if no fonts in a directory\n");
     fprintf (file, "  -f, --force              scan directories with apparently valid caches\n");
     fprintf (file, "  -q, --quick              don't sleep before exiting\n");
     fprintf (file, "  -r, --really-force       erase all existing caches, then rescan\n");
@@ -106,6 +108,8 @@ usage (char *program, int error)
     fprintf (file, "  -V, --version            display font config version and exit\n");
     fprintf (file, "  -h, --help               display this help and exit\n");
 #else
+    fprintf (file, "  -E         (error-on-no-fonts)\n");
+    fprintf (file, "                       raise an error if no fonts in a directory\n");
     fprintf (file, "  -f         (force)   scan directories with apparently valid caches\n");
     fprintf (file, "  -q         (quick)   don't sleep before exiting\n");
     fprintf (file, "  -r,   (really force) erase all existing caches, then rescan\n");
@@ -121,7 +125,7 @@ usage (char *program, int error)
 static FcStrSet *processed_dirs;
 
 static int
-scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force, FcBool verbose, FcBool recursive, int *changed, FcStrSet *updateDirs)
+scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force, FcBool verbose, FcBool error_on_no_fonts, int *changed)
 {
     int		    ret = 0;
     const FcChar8   *dir;
@@ -129,9 +133,10 @@ scanDirs (FcStrList *list, FcConfig *con
     FcStrList	    *sublist;
     FcCache	    *cache;
     struct stat	    statb;
-    FcBool	    was_valid;
+    FcBool	    was_valid, was_processed = FcFalse;
     int		    i;
-    
+    const FcChar8   *sysroot = FcConfigGetSysRoot (config);
+
     /*
      * Now scan all of the directories into separate databases
      * and write out the results
@@ -140,14 +145,13 @@ scanDirs (FcStrList *list, FcConfig *con
     {
 	if (verbose)
 	{
-	    if (!recursive)
-		printf ("Re-scanning %s: ", dir);
-	    else
-		printf ("%s: ", dir);
+	    if (sysroot)
+		printf ("[%s]", sysroot);
+	    printf ("%s: ", dir);
 	    fflush (stdout);
 	}
 	
-	if (recursive && FcStrSetMember (processed_dirs, dir))
+	if (FcStrSetMember (processed_dirs, dir))
 	{
 	    if (verbose)
 		printf ("skipping, looped directory detected\n");
@@ -176,6 +180,7 @@ scanDirs (FcStrList *list, FcConfig *con
 	    fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
 	    continue;
 	}
+	was_processed = FcTrue;
 
 	if (really_force)
 	    FcDirCacheUnlink (dir, config);
@@ -190,13 +195,8 @@ scanDirs (FcStrList *list, FcConfig *con
 	
 	if (!cache)
 	{
-	    if (!recursive)
-		cache = FcDirCacheRescan (dir, config);
-	    else
-	    {
-		(*changed)++;
-		cache = FcDirCacheRead (dir, FcTrue, config);
-	    }
+	    (*changed)++;
+	    cache = FcDirCacheRead (dir, FcTrue, config);
 	    if (!cache)
 	    {
 		fprintf (stderr, "%s: error scanning\n", dir);
@@ -225,38 +225,33 @@ scanDirs (FcStrList *list, FcConfig *con
 	    }
 	}
 
-	if (recursive)
+	subdirs = FcStrSetCreate ();
+	if (!subdirs)
 	{
-	    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));
-	    if (updateDirs && FcCacheNumSubdir (cache) > 0)
-		FcStrSetAdd (updateDirs, dir);
-	
+	    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));
 	
-	    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, recursive, changed, updateDirs);
-	    FcStrListDone (sublist);
+	FcDirCacheUnload (cache);
+
+	sublist = FcStrListCreate (subdirs);
+	FcStrSetDestroy (subdirs);
+	if (!sublist)
+	{
+	    fprintf (stderr, "%s: Can't create subdir list\n", dir);
+	    ret++;
+	    continue;
 	}
-	else
-	    FcDirCacheUnload (cache);
+	FcStrSetAdd (processed_dirs, dir);
+	ret += scanDirs (sublist, config, force, really_force, verbose, error_on_no_fonts, changed);
+	FcStrListDone (sublist);
     }
+    if (error_on_no_fonts && !was_processed)
+	ret++;
     return ret;
 }
 
@@ -284,13 +279,14 @@ cleanCacheDirectories (FcConfig *config,
 int
 main (int argc, char **argv)
 {
-    FcStrSet	*dirs, *updateDirs;
+    FcStrSet	*dirs;
     FcStrList	*list;
     FcBool    	verbose = FcFalse;
     FcBool      quick = FcFalse;
     FcBool	force = FcFalse;
     FcBool	really_force = FcFalse;
     FcBool	systemOnly = FcFalse;
+    FcBool	error_on_no_fonts = FcFalse;
     FcConfig	*config;
     FcChar8     *sysroot = NULL;
     int		i;
@@ -300,12 +296,15 @@ main (int argc, char **argv)
     int		c;
 
 #if HAVE_GETOPT_LONG
-    while ((c = getopt_long (argc, argv, "fqrsy:Vvh", longopts, NULL)) != -1)
+    while ((c = getopt_long (argc, argv, "Efqrsy:Vvh", longopts, NULL)) != -1)
 #else
-    while ((c = getopt (argc, argv, "fqrsy:Vvh")) != -1)
+    while ((c = getopt (argc, argv, "Efqrsy:Vvh")) != -1)
 #endif
     {
 	switch (c) {
+	case 'E':
+	    error_on_no_fonts = FcTrue;
+	    break;
 	case 'r':
 	    really_force = FcTrue;
 	    /* fall through */
@@ -387,18 +386,9 @@ main (int argc, char **argv)
 	return 1;
     }
 
-    updateDirs = FcStrSetCreate ();
     changed = 0;
-    ret = scanDirs (list, config, force, really_force, verbose, FcTrue, &changed, updateDirs);
-    /* Update the directory cache again to avoid the race condition as much as possible */
+    ret = scanDirs (list, config, force, really_force, verbose, error_on_no_fonts, &changed);
     FcStrListDone (list);
-    list = FcStrListCreate (updateDirs);
-    if (list)
-    {
-	ret += scanDirs (list, config, FcTrue, really_force, verbose, FcFalse, &changed, NULL);
-	FcStrListDone (list);
-    }
-    FcStrSetDestroy (updateDirs);
 
     /*
      * Try to create CACHEDIR.TAG anyway.

Index: xsrc/external/mit/fontconfig/dist/src/fccache.c
diff -u xsrc/external/mit/fontconfig/dist/src/fccache.c:1.8 xsrc/external/mit/fontconfig/dist/src/fccache.c:1.9
--- xsrc/external/mit/fontconfig/dist/src/fccache.c:1.8	Sun Jan  4 18:08:34 2015
+++ xsrc/external/mit/fontconfig/dist/src/fccache.c	Tue Aug 29 08:38:50 2017
@@ -27,6 +27,7 @@
 #include <fcntl.h>
 #include <dirent.h>
 #include <string.h>
+#include <limits.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <assert.h>
@@ -34,6 +35,9 @@
 #  include <unistd.h>
 #  include <sys/mman.h>
 #endif
+#if defined(_WIN32)
+#include <sys/locking.h>
+#endif
 
 #ifndef O_BINARY
 #define O_BINARY 0
@@ -177,19 +181,28 @@ FcDirCacheOpenFile (const FcChar8 *cache
  */
 static FcBool
 FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
-		   FcBool (*callback) (int fd, struct stat *fd_stat,
+		   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;
+    FcChar8	*cache_dir, *d;
     struct stat file_stat, dir_stat;
     FcBool	ret = FcFalse;
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
 
-    if (FcStatChecksum (dir, &dir_stat) < 0)
+    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);
 
@@ -199,7 +212,6 @@ FcDirCacheProcess (FcConfig *config, con
 	
     while ((cache_dir = FcStrListNext (list)))
     {
-	const FcChar8 *sysroot = FcConfigGetSysRoot (config);
         FcChar8	*cache_hashed;
 
 	if (sysroot)
@@ -210,7 +222,7 @@ FcDirCacheProcess (FcConfig *config, con
 	    break;
         fd = FcDirCacheOpenFile (cache_hashed, &file_stat);
         if (fd >= 0) {
-	    ret = (*callback) (fd, &file_stat, &dir_stat, closure);
+	    ret = (*callback) (config, fd, &file_stat, &dir_stat, closure);
 	    close (fd);
 	    if (ret)
 	    {
@@ -245,6 +257,7 @@ struct _FcCacheSkip {
     dev_t	    cache_dev;
     ino_t	    cache_ino;
     time_t	    cache_mtime;
+    long	    cache_mtime_nano;
     FcCacheSkip	    *next[1];
 };
 
@@ -372,12 +385,18 @@ FcCacheInsert (FcCache *cache, struct st
 	s->cache_dev = cache_stat->st_dev;
 	s->cache_ino = cache_stat->st_ino;
 	s->cache_mtime = cache_stat->st_mtime;
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+	s->cache_mtime_nano = cache_stat->st_mtim.tv_nsec;
+#else
+	s->cache_mtime_nano = 0;
+#endif
     }
     else
     {
 	s->cache_dev = 0;
 	s->cache_ino = 0;
 	s->cache_mtime = 0;
+	s->cache_mtime_nano = 0;
     }
 
     /*
@@ -465,6 +484,10 @@ FcCacheFindByStat (struct stat *cache_st
 	    s->cache_ino == cache_stat->st_ino &&
 	    s->cache_mtime == cache_stat->st_mtime)
 	{
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+	    if (s->cache_mtime != cache_stat->st_mtim.tv_nsec)
+		continue;
+#endif
 	    FcRefInc (&s->ref);
 	    unlock_cache ();
 	    return s->cache;
@@ -529,37 +552,141 @@ FcCacheFini (void)
 }
 
 static FcBool
-FcCacheTimeValid (FcCache *cache, struct stat *dir_stat)
+FcCacheTimeValid (FcConfig *config, FcCache *cache, struct stat *dir_stat)
 {
     struct stat	dir_static;
+    FcBool fnano = FcTrue;
 
     if (!dir_stat)
     {
-	if (FcStatChecksum (FcCacheDir (cache), &dir_static) < 0)
+	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);
-    return cache->checksum == (int) dir_stat->st_mtime;
+#endif
+
+    return cache->checksum == (int) dir_stat->st_mtime && fnano;
+}
+
+static FcBool
+FcCacheOffsetsValid (FcCache *cache)
+{
+    char		*base = (char *)cache;
+    char		*end = base + cache->size;
+    intptr_t		*dirs;
+    FcFontSet		*fs;
+    int			 i, j;
+
+    if (cache->dir < 0 || cache->dir > cache->size - sizeof (intptr_t) ||
+        memchr (base + cache->dir, '\0', cache->size - cache->dir) == NULL)
+        return FcFalse;
+
+    if (cache->dirs < 0 || cache->dirs >= cache->size ||
+        cache->dirs_count < 0 ||
+        cache->dirs_count > (cache->size - cache->dirs) / sizeof (intptr_t))
+        return FcFalse;
+
+    dirs = FcCacheDirs (cache);
+    if (dirs)
+    {
+        for (i = 0; i < cache->dirs_count; i++)
+        {
+            FcChar8	*dir;
+
+            if (dirs[i] < 0 ||
+                dirs[i] > end - (char *) dirs - sizeof (intptr_t))
+                return FcFalse;
+
+            dir = FcOffsetToPtr (dirs, dirs[i], FcChar8);
+            if (memchr (dir, '\0', end - (char *) dir) == NULL)
+                return FcFalse;
+         }
+    }
+
+    if (cache->set < 0 || cache->set > cache->size - sizeof (FcFontSet))
+        return FcFalse;
+
+    fs = FcCacheSet (cache);
+    if (fs)
+    {
+        if (fs->nfont > (end - (char *) fs) / sizeof (FcPattern))
+            return FcFalse;
+
+        if (fs->fonts != 0 && !FcIsEncodedOffset(fs->fonts))
+            return FcFalse;
+
+        for (i = 0; i < fs->nfont; i++)
+        {
+            FcPattern		*font = FcFontSetFont (fs, i);
+            FcPatternElt	*e;
+            FcValueListPtr	 l;
+	    char                *last_offset;
+
+            if ((char *) font < base ||
+                (char *) font > end - sizeof (FcFontSet) ||
+                font->elts_offset < 0 ||
+                font->elts_offset > end - (char *) font ||
+                font->num > (end - (char *) font - font->elts_offset) / sizeof (FcPatternElt))
+                return FcFalse;
+
+
+            e = FcPatternElts(font);
+            if (e->values != 0 && !FcIsEncodedOffset(e->values))
+                return FcFalse;
+
+	    for (j = 0; j < font->num; j++)
+	    {
+		last_offset = (char *) font + font->elts_offset;
+		for (l = FcPatternEltValues(&e[j]); l; l = FcValueListNext(l))
+		{
+		    if ((char *) l < last_offset || (char *) l > end - sizeof (*l) ||
+			(l->next != NULL && !FcIsEncodedOffset(l->next)))
+			return FcFalse;
+		    last_offset = (char *) l + 1;
+		}
+	    }
+        }
+    }
+
+    return FcTrue;
 }
 
 /*
  * Map a cache file into memory
  */
 static FcCache *
-FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat)
+FcDirCacheMapFd (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat)
 {
     FcCache	*cache;
     FcBool	allocated = FcFalse;
 
-    if (fd_stat->st_size < (int) sizeof (FcCache))
+    if (fd_stat->st_size > INTPTR_MAX ||
+        fd_stat->st_size < (int) sizeof (FcCache))
 	return NULL;
     cache = FcCacheFindByStat (fd_stat);
     if (cache)
     {
-	if (FcCacheTimeValid (cache, dir_stat))
+	if (FcCacheTimeValid (config, cache, dir_stat))
 	    return cache;
 	FcDirCacheUnload (cache);
 	cache = NULL;
@@ -608,9 +735,10 @@ FcDirCacheMapFd (int fd, struct stat *fd
 	allocated = FcTrue;
     }
     if (cache->magic != FC_CACHE_MAGIC_MMAP ||
-	cache->version < FC_CACHE_CONTENT_VERSION ||
+	cache->version < FC_CACHE_VERSION_NUMBER ||
 	cache->size != (intptr_t) fd_stat->st_size ||
-	!FcCacheTimeValid (cache, dir_stat) ||
+        !FcCacheOffsetsValid (cache) ||
+	!FcCacheTimeValid (config, cache, dir_stat) ||
 	!FcCacheInsert (cache, fd_stat))
     {
 	if (allocated)
@@ -649,9 +777,9 @@ FcDirCacheUnload (FcCache *cache)
 }
 
 static FcBool
-FcDirCacheMapHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
+FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
 {
-    FcCache *cache = FcDirCacheMapFd (fd, fd_stat, dir_stat);
+    FcCache *cache = FcDirCacheMapFd (config, fd, fd_stat, dir_stat);
 
     if (!cache)
 	return FcFalse;
@@ -668,6 +796,7 @@ FcDirCacheLoad (const FcChar8 *dir, FcCo
 			    FcDirCacheMapHelper,
 			    &cache, cache_file))
 	return NULL;
+
     return cache;
 }
 
@@ -683,7 +812,7 @@ FcDirCacheLoadFile (const FcChar8 *cache
     fd = FcDirCacheOpenFile (cache_file, file_stat);
     if (fd < 0)
 	return NULL;
-    cache = FcDirCacheMapFd (fd, file_stat, NULL);
+    cache = FcDirCacheMapFd (FcConfigGetCurrent (), fd, file_stat, NULL);
     close (fd);
     return cache;
 }
@@ -693,7 +822,7 @@ FcDirCacheLoadFile (const FcChar8 *cache
  * the magic number and the size field
  */
 static FcBool
-FcDirCacheValidateHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure FC_UNUSED)
+FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure FC_UNUSED)
 {
     FcBool  ret = FcTrue;
     FcCache	c;
@@ -702,12 +831,16 @@ FcDirCacheValidateHelper (int fd, struct
 	ret = FcFalse;
     else if (c.magic != FC_CACHE_MAGIC_MMAP)
 	ret = FcFalse;
-    else if (c.version < FC_CACHE_CONTENT_VERSION)
+    else if (c.version < FC_CACHE_VERSION_NUMBER)
 	ret = FcFalse;
     else if (fd_stat->st_size != c.size)
 	ret = FcFalse;
     else if (c.checksum != (int) dir_stat->st_mtime)
 	ret = FcFalse;
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+    else if (c.checksum_nano != dir_stat->st_mtim.tv_nsec)
+	ret = FcFalse;
+#endif
     return ret;
 }
 
@@ -779,9 +912,12 @@ FcDirCacheBuild (FcFontSet *set, const F
     serialize->linear = cache;
 
     cache->magic = FC_CACHE_MAGIC_ALLOC;
-    cache->version = FC_CACHE_CONTENT_VERSION;
+    cache->version = FC_CACHE_VERSION_NUMBER;
     cache->size = serialize->size;
     cache->checksum = (int) dir_stat->st_mtime;
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+    cache->checksum_nano = dir_stat->st_mtim.tv_nsec;
+#endif
 
     /*
      * Serialize directory name
@@ -969,6 +1105,11 @@ FcDirCacheWrite (FcCache *cache, FcConfi
 	    skip->cache_dev = cache_stat.st_dev;
 	    skip->cache_ino = cache_stat.st_ino;
 	    skip->cache_mtime = cache_stat.st_mtime;
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+	    skip->cache_mtime_nano = cache_stat.st_mtim.tv_nsec;
+#else
+	    skip->cache_mtime_nano = 0;
+#endif
 	}
 	unlock_cache ();
     }
@@ -1058,15 +1199,22 @@ FcDirCacheClean (const FcChar8 *cache_di
 	}
 	else
 	{
+	    FcChar8 *s;
+
 	    target_dir = FcCacheDir (cache);
-	    if (stat ((char *) target_dir, &target_stat) < 0)
+	    if (sysroot)
+		s = FcStrBuildFilename (sysroot, target_dir, NULL);
+	    else
+		s = FcStrdup (target_dir);
+	    if (stat ((char *) s, &target_stat) < 0)
 	    {
 		if (verbose || FcDebug () & FC_DBG_CACHE)
 		    printf ("%s: %s: missing directory: %s \n",
-			    dir, ent->d_name, target_dir);
+			    dir, ent->d_name, s);
 		remove = FcTrue;
 	    }
 	    FcDirCacheUnload (cache);
+	    FcStrFree (s);
 	}
 	if (remove)
 	{
@@ -1086,6 +1234,82 @@ FcDirCacheClean (const FcChar8 *cache_di
     return ret;
 }
 
+int
+FcDirCacheLock (const FcChar8 *dir,
+		FcConfig      *config)
+{
+    FcChar8 *cache_hashed = NULL;
+    FcChar8 cache_base[CACHEBASE_LEN];
+    FcStrList *list;
+    FcChar8 *cache_dir;
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+    int fd = -1;
+
+    FcDirCacheBasename (dir, cache_base);
+    list = FcStrListCreate (config->cacheDirs);
+    if (!list)
+	return -1;
+
+    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;
+	fd = FcOpen ((const char *)cache_hashed, O_RDWR);
+	FcStrFree (cache_hashed);
+	/* No caches in that directory. simply retry with another one */
+	if (fd != -1)
+	{
+#if defined(_WIN32)
+	    if (_locking (fd, _LK_LOCK, 1) == -1)
+		goto bail;
+#else
+	    struct flock fl;
+
+	    fl.l_type = F_WRLCK;
+	    fl.l_whence = SEEK_SET;
+	    fl.l_start = 0;
+	    fl.l_len = 0;
+	    fl.l_pid = getpid ();
+	    if (fcntl (fd, F_SETLKW, &fl) == -1)
+		goto bail;
+#endif
+	    break;
+	}
+    }
+    FcStrListDone (list);
+    return fd;
+bail:
+    FcStrListDone (list);
+    if (fd != -1)
+	close (fd);
+    return -1;
+}
+
+void
+FcDirCacheUnlock (int fd)
+{
+    if (fd != -1)
+    {
+#if defined(_WIN32)
+	_locking (fd, _LK_UNLCK, 1);
+#else
+	struct flock fl;
+
+	fl.l_type = F_UNLCK;
+	fl.l_whence = SEEK_SET;
+	fl.l_start = 0;
+	fl.l_len = 0;
+	fl.l_pid = getpid ();
+	fcntl (fd, F_SETLK, &fl);
+#endif
+	close (fd);
+    }
+}
+
 /*
  * Hokey little macro trick to permit the definitions of C functions
  * with the same name as CPP macros

Index: xsrc/external/mit/fontconfig/dist/src/fccfg.c
diff -u xsrc/external/mit/fontconfig/dist/src/fccfg.c:1.2 xsrc/external/mit/fontconfig/dist/src/fccfg.c:1.3
--- xsrc/external/mit/fontconfig/dist/src/fccfg.c:1.2	Thu Mar 20 08:04:41 2014
+++ xsrc/external/mit/fontconfig/dist/src/fccfg.c	Tue Aug 29 08:38:50 2017
@@ -27,6 +27,7 @@
 #include "fcint.h"
 #include <dirent.h>
 #include <sys/types.h>
+#include "../fc-blanks/fcblanks.h"
 
 #if defined (_WIN32) && !defined (R_OK)
 #define R_OK 4
@@ -109,7 +110,7 @@ FcConfigCreate (void)
     if (!config->cacheDirs)
 	goto bail8;
 
-    config->blanks = 0;
+    config->blanks = &fcBlanks;
 
     config->substPattern = 0;
     config->substFont = 0;
@@ -375,7 +376,7 @@ FcConfigAddDirList (FcConfig *config, Fc
     while ((dir = FcStrListNext (dirlist)))
     {
 	if (FcDebug () & FC_DBG_FONTSET)
-	    printf ("adding fonts from%s\n", dir);
+	    printf ("adding fonts from %s\n", dir);
 	cache = FcDirCacheRead (dir, FcFalse, config);
 	if (!cache)
 	    continue;
@@ -434,6 +435,7 @@ retry:
     if (!fc_atomic_ptr_cmpexch (&_fcConfig, cfg, config))
 	goto retry;
 
+    FcConfigReference (config);
     if (cfg)
 	FcConfigDestroy (cfg);
 
@@ -722,6 +724,21 @@ FcConfigPromote (FcValue v, FcValue u, F
 	v.u.l = FcLangSetPromote (v.u.s, buf);
 	v.type = FcTypeLangSet;
     }
+    else if (v.type == FcTypeVoid && u.type == FcTypeLangSet)
+    {
+	v.u.l = FcLangSetPromote (NULL, buf);
+	v.type = FcTypeLangSet;
+    }
+    else if (v.type == FcTypeVoid && u.type == FcTypeCharSet)
+    {
+	v.u.c = FcCharSetPromote (buf);
+	v.type = FcTypeCharSet;
+    }
+    if (buf && v.type == FcTypeDouble && u.type == FcTypeRange)
+    {
+	v.u.r = FcRangePromote (v.u.d, buf);
+	v.type = FcTypeRange;
+    }
     return v;
 }
 
@@ -894,6 +911,9 @@ FcConfigCompareValue (const FcValue	*lef
 		break;
 	    }
 	    break;
+	case FcTypeRange:
+	    ret = FcRangeCompare (op, left.u.r, right.u.r);
+	    break;
 	}
     }
     else
@@ -915,10 +935,11 @@ FcConfigCompareValue (const FcValue	*lef
 static FcValue
 FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e)
 {
-    FcValue	v, vl, vr;
+    FcValue	v, vl, vr, vle, vre;
     FcMatrix	*m;
     FcChar8     *str;
     FcOp	op = FC_OP_GET_OP (e->op);
+    FcValuePromotionBuffer buf1, buf2;
 
     switch ((int) op) {
     case FcOpInteger:
@@ -967,6 +988,11 @@ FcConfigEvaluate (FcPattern *p, FcPatter
 	v.u.l = e->u.lval;
 	v = FcValueSave (v);
 	break;
+    case FcOpRange:
+	v.type = FcTypeRange;
+	v.u.r = e->u.rval;
+	v = FcValueSave (v);
+	break;
     case FcOpBool:
 	v.type = FcTypeBool;
 	v.u.b = e->u.bval;
@@ -1033,28 +1059,28 @@ FcConfigEvaluate (FcPattern *p, FcPatter
     case FcOpDivide:
 	vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
 	vr = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right);
-	vl = FcConfigPromote (vl, vr, NULL);
-	vr = FcConfigPromote (vr, vl, NULL);
-	if (vl.type == vr.type)
+	vle = FcConfigPromote (vl, vr, &buf1);
+	vre = FcConfigPromote (vr, vle, &buf2);
+	if (vle.type == vre.type)
 	{
-	    switch ((int) vl.type) {
+	    switch ((int) vle.type) {
 	    case FcTypeDouble:
 		switch ((int) op) {
 		case FcOpPlus:	
 		    v.type = FcTypeDouble;
-		    v.u.d = vl.u.d + vr.u.d;
+		    v.u.d = vle.u.d + vre.u.d;
 		    break;
 		case FcOpMinus:
 		    v.type = FcTypeDouble;
-		    v.u.d = vl.u.d - vr.u.d;
+		    v.u.d = vle.u.d - vre.u.d;
 		    break;
 		case FcOpTimes:
 		    v.type = FcTypeDouble;
-		    v.u.d = vl.u.d * vr.u.d;
+		    v.u.d = vle.u.d * vre.u.d;
 		    break;
 		case FcOpDivide:
 		    v.type = FcTypeDouble;
-		    v.u.d = vl.u.d / vr.u.d;
+		    v.u.d = vle.u.d / vre.u.d;
 		    break;
 		default:
 		    v.type = FcTypeVoid;
@@ -1071,11 +1097,11 @@ FcConfigEvaluate (FcPattern *p, FcPatter
 		switch ((int) op) {
 		case FcOpOr:
 		    v.type = FcTypeBool;
-		    v.u.b = vl.u.b || vr.u.b;
+		    v.u.b = vle.u.b || vre.u.b;
 		    break;
 		case FcOpAnd:
 		    v.type = FcTypeBool;
-		    v.u.b = vl.u.b && vr.u.b;
+		    v.u.b = vle.u.b && vre.u.b;
 		    break;
 		default:
 		    v.type = FcTypeVoid;
@@ -1086,7 +1112,7 @@ FcConfigEvaluate (FcPattern *p, FcPatter
 		switch ((int) op) {
 		case FcOpPlus:
 		    v.type = FcTypeString;
-		    str = FcStrPlus (vl.u.s, vr.u.s);
+		    str = FcStrPlus (vle.u.s, vre.u.s);
 		    v.u.s = FcStrdup (str);
 		    FcStrFree (str);
 			
@@ -1105,7 +1131,7 @@ FcConfigEvaluate (FcPattern *p, FcPatter
 		    m = malloc (sizeof (FcMatrix));
 		    if (m)
 		    {
-			FcMatrixMultiply (m, vl.u.m, vr.u.m);
+			FcMatrixMultiply (m, vle.u.m, vre.u.m);
 			v.u.m = m;
 		    }
 		    else
@@ -1122,13 +1148,13 @@ FcConfigEvaluate (FcPattern *p, FcPatter
 		switch ((int) op) {
 		case FcOpPlus:
 		    v.type = FcTypeCharSet;
-		    v.u.c = FcCharSetUnion (vl.u.c, vr.u.c);
+		    v.u.c = FcCharSetUnion (vle.u.c, vre.u.c);
 		    if (!v.u.c)
 			v.type = FcTypeVoid;
 		    break;
 		case FcOpMinus:
 		    v.type = FcTypeCharSet;
-		    v.u.c = FcCharSetSubtract (vl.u.c, vr.u.c);
+		    v.u.c = FcCharSetSubtract (vle.u.c, vre.u.c);
 		    if (!v.u.c)
 			v.type = FcTypeVoid;
 		    break;
@@ -1141,13 +1167,13 @@ FcConfigEvaluate (FcPattern *p, FcPatter
 		switch ((int) op) {
 		case FcOpPlus:
 		    v.type = FcTypeLangSet;
-		    v.u.l = FcLangSetUnion (vl.u.l, vr.u.l);
+		    v.u.l = FcLangSetUnion (vle.u.l, vre.u.l);
 		    if (!v.u.l)
 			v.type = FcTypeVoid;
 		    break;
 		case FcOpMinus:
 		    v.type = FcTypeLangSet;
-		    v.u.l = FcLangSetSubtract (vl.u.l, vr.u.l);
+		    v.u.l = FcLangSetSubtract (vle.u.l, vre.u.l);
 		    if (!v.u.l)
 			v.type = FcTypeVoid;
 		    break;
@@ -1518,15 +1544,52 @@ FcConfigSubstituteWithPat (FcConfig    *
 	    FcStrList *l = FcStrListCreate (strs);
 	    FcChar8 *lang;
 	    FcValue v;
+	    FcLangSet *lsund = FcLangSetCreate ();
 
+	    FcLangSetAdd (lsund, (const FcChar8 *)"und");
 	    FcStrSetDestroy (strs);
 	    while (l && (lang = FcStrListNext (l)))
 	    {
+		FcPatternElt *e = FcPatternObjectFindElt (p, FC_LANG_OBJECT);
+
+		if (e)
+		{
+		    FcValueListPtr ll;
+
+		    for (ll = FcPatternEltValues (e); ll; ll = FcValueListNext (ll))
+		    {
+			FcValue vv = FcValueCanonicalize (&ll->value);
+
+			if (vv.type == FcTypeLangSet)
+			{
+			    FcLangSet *ls = FcLangSetCreate ();
+			    FcBool b;
+
+			    FcLangSetAdd (ls, lang);
+			    b = FcLangSetContains (vv.u.l, ls);
+			    FcLangSetDestroy (ls);
+			    if (b)
+				goto bail_lang;
+			    if (FcLangSetContains (vv.u.l, lsund))
+				goto bail_lang;
+			}
+			else
+			{
+			    if (FcStrCmpIgnoreCase (vv.u.s, lang) == 0)
+				goto bail_lang;
+			    if (FcStrCmpIgnoreCase (vv.u.s, (const FcChar8 *)"und") == 0)
+				goto bail_lang;
+			}
+		    }
+		}
 		v.type = FcTypeString;
 		v.u.s = lang;
+
 		FcPatternObjectAddWithBinding (p, FC_LANG_OBJECT, v, FcValueBindingWeak, FcTrue);
 	    }
+	bail_lang:
 	    FcStrListDone (l);
+	    FcLangSetDestroy (lsund);
 	}
 	if (FcPatternObjectGet (p, FC_PRGNAME_OBJECT, 0, &v) == FcResultNoMatch)
 	{
@@ -1778,6 +1841,7 @@ FcConfigSubstitute (FcConfig	*config,
 #if defined (_WIN32)
 
 static FcChar8 fontconfig_path[1000] = ""; /* MT-dontcare */
+FcChar8 fontconfig_instprefix[1000] = ""; /* MT-dontcare */
 
 #  if (defined (PIC) || defined (DLL_EXPORT))
 
@@ -1812,6 +1876,7 @@ DllMain (HINSTANCE hinstDLL,
 	  if (p && (FcStrCmpIgnoreCase (p + 1, (const FcChar8 *) "bin") == 0 ||
 		    FcStrCmpIgnoreCase (p + 1, (const FcChar8 *) "lib") == 0))
 	      *p = '\0';
+	  strcat ((char *) fontconfig_instprefix, (char *) fontconfig_path);
 	  strcat ((char *) fontconfig_path, "\\etc\\fonts");
       }
       else
@@ -1985,6 +2050,8 @@ FcConfigXdgCacheHome (void)
     const char *env = getenv ("XDG_CACHE_HOME");
     FcChar8 *ret = NULL;
 
+    if (!_FcConfigHomeEnabled)
+	return NULL;
     if (env)
 	ret = FcStrCopy ((const FcChar8 *)env);
     else
@@ -2010,6 +2077,8 @@ FcConfigXdgConfigHome (void)
     const char *env = getenv ("XDG_CONFIG_HOME");
     FcChar8 *ret = NULL;
 
+    if (!_FcConfigHomeEnabled)
+	return NULL;
     if (env)
 	ret = FcStrCopy ((const FcChar8 *)env);
     else
@@ -2035,6 +2104,8 @@ FcConfigXdgDataHome (void)
     const char *env = getenv ("XDG_DATA_HOME");
     FcChar8 *ret = NULL;
 
+    if (!_FcConfigHomeEnabled)
+	return NULL;
     if (env)
 	ret = FcStrCopy ((const FcChar8 *)env);
     else
@@ -2134,7 +2205,7 @@ FcConfigAppFontAddFile (FcConfig    *con
 	    return FcFalse;
     }
 
-    subdirs = FcStrSetCreate ();
+    subdirs = FcStrSetCreateEx (FCSS_GROW_BY_64);
     if (!subdirs)
 	return FcFalse;
 
@@ -2181,7 +2252,7 @@ FcConfigAppFontAddDir (FcConfig	    *con
 	    return FcFalse;
     }
 
-    dirs = FcStrSetCreate ();
+    dirs = FcStrSetCreateEx (FCSS_GROW_BY_64);
     if (!dirs)
 	return FcFalse;
 
@@ -2312,7 +2383,7 @@ void
 FcConfigSetSysRoot (FcConfig      *config,
 		    const FcChar8 *sysroot)
 {
-    FcChar8 *s;
+    FcChar8 *s = NULL;
     FcBool init = FcFalse;
 
     if (!config)
@@ -2332,9 +2403,12 @@ FcConfigSetSysRoot (FcConfig      *confi
 	}
     }
 
-    s = FcStrCopyFilename (sysroot);
-    if (!s)
-	return;
+    if (sysroot)
+    {
+	s = FcStrCopyFilename (sysroot);
+	if (!s)
+	    return;
+    }
 
     if (config->sysRoot)
 	FcStrFree (config->sysRoot);
@@ -2344,6 +2418,10 @@ FcConfigSetSysRoot (FcConfig      *confi
     {
 	config = FcInitLoadOwnConfigAndFonts (config);
 	FcConfigSetCurrent (config);
+	/* FcConfigSetCurrent() increases the refcount.
+	 * decrease it here to avoid the memory leak.
+	 */
+	FcConfigDestroy (config);
     }
 }
 
Index: xsrc/external/mit/fontconfig/dist/src/fcinit.c
diff -u xsrc/external/mit/fontconfig/dist/src/fcinit.c:1.2 xsrc/external/mit/fontconfig/dist/src/fcinit.c:1.3
--- xsrc/external/mit/fontconfig/dist/src/fcinit.c:1.2	Wed Apr 29 21:04:52 2015
+++ xsrc/external/mit/fontconfig/dist/src/fcinit.c	Tue Aug 29 08:38:50 2017
@@ -36,13 +36,14 @@
 #endif
 
 static FcConfig *
-FcInitFallbackConfig (void)
+FcInitFallbackConfig (const FcChar8 *sysroot)
 {
     FcConfig	*config;
 
     config = FcConfigCreate ();
     if (!config)
 	goto bail0;
+    FcConfigSetSysRoot (config, sysroot);
     if (!FcConfigAddDir (config, (FcChar8 *) FC_DEFAULT_FONTS))
 	goto bail1;
     if (!FcConfigAddCacheDir (config, (FcChar8 *) FC_CACHEDIR))
@@ -78,20 +79,35 @@ FcInitLoadOwnConfig (FcConfig *config)
 
     if (!FcConfigParseAndLoad (config, 0, FcTrue))
     {
+	const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+	FcConfig *fallback = FcInitFallbackConfig (sysroot);
+
 	FcConfigDestroy (config);
-	return FcInitFallbackConfig ();
+
+	return fallback;
     }
 
     if (config->cacheDirs && config->cacheDirs->num == 0)
     {
 	FcChar8 *prefix, *p;
 	size_t plen;
+	FcBool have_own = FcFalse;
+	char *env_file, *env_path;
 
-	fprintf (stderr,
-		 "Fontconfig warning: no <cachedir> elements found. Check configuration.\n");
-	fprintf (stderr,
-		 "Fontconfig warning: adding <cachedir>%s</cachedir>\n",
-		 FC_CACHEDIR);
+	env_file = getenv ("FONTCONFIG_FILE");
+	env_path = getenv ("FONTCONFIG_PATH");
+	if ((env_file != NULL && env_file[0] != 0) ||
+	    (env_path != NULL && env_path[0] != 0))
+	    have_own = FcTrue;
+
+	if (!have_own)
+	{
+	    fprintf (stderr,
+		     "Fontconfig warning: no <cachedir> elements found. Check configuration.\n");
+	    fprintf (stderr,
+		     "Fontconfig warning: adding <cachedir>%s</cachedir>\n",
+		     FC_CACHEDIR);
+	}
 	prefix = FcConfigXdgCacheHome ();
 	if (!prefix)
 	    goto bail;
@@ -102,19 +118,26 @@ FcInitLoadOwnConfig (FcConfig *config)
 	prefix = p;
 	memcpy (&prefix[plen], FC_DIR_SEPARATOR_S "fontconfig", 11);
 	prefix[plen + 11] = 0;
-	fprintf (stderr,
-		 "Fontconfig warning: adding <cachedir prefix=\"xdg\">fontconfig</cachedir>\n");
+	if (!have_own)
+	    fprintf (stderr,
+		     "Fontconfig warning: adding <cachedir prefix=\"xdg\">fontconfig</cachedir>\n");
 
 	if (!FcConfigAddCacheDir (config, (FcChar8 *) FC_CACHEDIR) ||
 	    !FcConfigAddCacheDir (config, (FcChar8 *) prefix))
 	{
+	    FcConfig *fallback;
+	    const FcChar8 *sysroot;
+
 	  bail:
+	    sysroot = FcConfigGetSysRoot (config);
 	    fprintf (stderr,
 		     "Fontconfig error: out of memory");
 	    if (prefix)
 		FcStrFree (prefix);
+	    fallback = FcInitFallbackConfig (sysroot);
 	    FcConfigDestroy (config);
-	    return FcInitFallbackConfig ();
+
+	    return fallback;
 	}
 	FcStrFree (prefix);
     }
@@ -169,6 +192,8 @@ FcFini (void)
     FcConfigFini ();
     FcCacheFini ();
     FcDefaultFini ();
+    FcObjectFini ();
+    FcConfigPathFini ();
 }
 
 /*
@@ -178,11 +203,18 @@ FcBool
 FcInitReinitialize (void)
 {
     FcConfig	*config;
+    FcBool	ret;
 
     config = FcInitLoadConfigAndFonts ();
     if (!config)
 	return FcFalse;
-    return FcConfigSetCurrent (config);
+    ret = FcConfigSetCurrent (config);
+    /* FcConfigSetCurrent() increases the refcount.
+     * decrease it here to avoid the memory leak.
+     */
+    FcConfigDestroy (config);
+
+    return ret;
 }
 
 FcBool
@@ -191,6 +223,8 @@ FcInitBringUptoDate (void)
     FcConfig	*config = FcConfigGetCurrent ();
     time_t	now;
 
+    if (!config)
+	return FcFalse;
     /*
      * rescanInterval == 0 disables automatic up to date
      */

Index: xsrc/external/mit/fontconfig/dist/src/fcint.h
diff -u xsrc/external/mit/fontconfig/dist/src/fcint.h:1.7 xsrc/external/mit/fontconfig/dist/src/fcint.h:1.8
--- xsrc/external/mit/fontconfig/dist/src/fcint.h:1.7	Sat Jul 12 04:11:34 2014
+++ xsrc/external/mit/fontconfig/dist/src/fcint.h	Tue Aug 29 08:38:50 2017
@@ -38,6 +38,8 @@
 #include <assert.h>
 #include <errno.h>
 #include <limits.h>
+#include <float.h>
+#include <math.h>
 #include <unistd.h>
 #include <stddef.h>
 #include <sys/types.h>
@@ -68,6 +70,12 @@ extern pfnSHGetFolderPathA pSHGetFolderP
 #  define FC_DIR_SEPARATOR_S       "/"
 #endif
 
+#ifdef PATH_MAX
+#define FC_PATH_MAX	PATH_MAX
+#else
+#define FC_PATH_MAX	128
+#endif
+
 #if __GNUC__ >= 4
 #define FC_UNUSED	__attribute__((unused))
 #else
@@ -85,6 +93,7 @@ extern pfnSHGetFolderPathA pSHGetFolderP
 #define FC_DBG_SCANV	256
 #define FC_DBG_CONFIG	1024
 #define FC_DBG_LANGSET	2048
+#define FC_DBG_MATCH2	4096
 
 #define _FC_ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] FC_UNUSED
 #define _FC_ASSERT_STATIC0(_line, _cond) _FC_ASSERT_STATIC1 (_line, (_cond))
@@ -161,6 +170,7 @@ typedef enum _FcValueBinding {
 #define FcValueString(v)	FcPointerMember(v,u.s,FcChar8)
 #define FcValueCharSet(v)	FcPointerMember(v,u.c,const FcCharSet)
 #define FcValueLangSet(v)	FcPointerMember(v,u.l,const FcLangSet)
+#define FcValueRange(v)		FcPointerMember(v,u.r,const FcRange)
 
 typedef struct _FcValueList *FcValueListPtr;
 
@@ -244,20 +254,26 @@ typedef struct _FcExprName {
   FcMatchKind	kind;
 } FcExprName;
 
+struct _FcRange {
+    double begin;
+    double end;
+};
+
 
 typedef struct _FcExpr {
     FcOp   op;
     union {
-	int	    ival;
-	double	    dval;
-	const FcChar8	    *sval;
-	FcExprMatrix *mexpr;
-	FcBool	    bval;
-	FcCharSet   *cval;
-	FcLangSet   *lval;
+	int		ival;
+	double		dval;
+	const FcChar8	*sval;
+	FcExprMatrix	*mexpr;
+	FcBool		bval;
+	FcCharSet	*cval;
+	FcLangSet	*lval;
+	FcRange		*rval;
 
-	FcExprName  name;
-	const FcChar8	    *constant;
+	FcExprName	name;
+	const FcChar8	*constant;
 	struct {
 	    struct _FcExpr *left, *right;
 	} tree;
@@ -329,11 +345,19 @@ struct _FcCharSet {
 					       FcCharLeaf))
 #define FcCharSetNumbers(c)	FcOffsetMember(c,numbers_offset,FcChar16)
 
+#define FCSS_DEFAULT            0 /* default behavior */
+#define FCSS_ALLOW_DUPLICATES   1 /* allows for duplicate strings in the set */
+#define FCSS_GROW_BY_64         2 /* grows buffer by 64 elements instead of 1 */
+
+#define FcStrSetHasControlBit(s,c)  (s->control & c)
+#define FcStrSetHasControlBits(s,c) ( (c) == (s->control & (c)) )
+
 struct _FcStrSet {
     FcRef	    ref;	/* reference count */
     int		    num;
     int		    size;
     FcChar8	    **strs;
+    unsigned int    control;    /* control bits for set behavior */
 };
 
 struct _FcStrList {
@@ -352,13 +376,14 @@ typedef struct _FcStrBuf {
 
 struct _FcCache {
     unsigned int magic;              /* FC_CACHE_MAGIC_MMAP or FC_CACHE_ALLOC */
-    int		version;	    /* FC_CACHE_CONTENT_VERSION */
+    int		version;	    /* FC_CACHE_VERSION_NUMBER */
     intptr_t	size;		    /* size of file */
     intptr_t	dir;		    /* offset to dir name */
     intptr_t	dirs;		    /* offset to subdirs */
     int		dirs_count;	    /* number of subdir strings */
     intptr_t	set;		    /* offset to font set */
     int		checksum;	    /* checksum of directory state */
+    int64_t	checksum_nano;	    /* checksum of directory state */
 };
 
 #undef FcCacheDir
@@ -444,7 +469,6 @@ typedef struct _FcCaseFold {
 
 #define FC_CACHE_MAGIC_MMAP	    0xFC02FC04
 #define FC_CACHE_MAGIC_ALLOC	    0xFC02FC05
-#define FC_CACHE_CONTENT_VERSION    4
 
 struct _FcAtomic {
     FcChar8	*file;		/* original file name */
@@ -532,13 +556,6 @@ typedef struct _FcFileTime {
 
 typedef struct _FcCharMap FcCharMap;
 
-typedef struct _FcRange	    FcRange;
-
-struct _FcRange {
-    FcChar32 begin;
-    FcChar32 end;
-};
-
 typedef struct _FcStatFS    FcStatFS;
 
 struct _FcStatFS {
@@ -588,6 +605,13 @@ FcCacheFini (void);
 FcPrivate void
 FcDirCacheReference (FcCache *cache, int nref);
 
+FcPrivate int
+FcDirCacheLock (const FcChar8 *dir,
+		FcConfig      *config);
+
+FcPrivate void
+FcDirCacheUnlock (int fd);
+
 /* fccfg.c */
 
 FcPrivate FcBool
@@ -701,6 +725,9 @@ FcPrivate FcLangSet *
 FcLangSetSerialize(FcSerialize *serialize, const FcLangSet *l);
 
 /* fccharset.c */
+FcPrivate FcCharSet *
+FcCharSetPromote (FcValuePromotionBuffer *vbuf);
+
 FcPrivate void
 FcLangCharSetPopulate (void);
 
@@ -789,6 +816,9 @@ FcSubstPrint (const FcSubst *subst);
 FcPrivate void
 FcCharSetPrint (const FcCharSet *c);
 
+FcPrivate void
+FcPatternPrint2 (FcPattern *p1, FcPattern *p2, const FcObjectSet *os);
+
 extern FcPrivate int FcDebugVal;
 
 #define FcDebug() (FcDebugVal)
@@ -844,18 +874,6 @@ FcFontSetSerialize (FcSerialize *seriali
 FcPrivate FcFontSet *
 FcFontSetDeserialize (const FcFontSet *set);
 
-/* fchash.c */
-FcPrivate FcChar8 *
-FcHashGetSHA256Digest (const FcChar8 *input_strings,
-		       size_t         len);
-
-FcPrivate FcChar8 *
-FcHashGetSHA256DigestFromFile (const FcChar8 *filename);
-
-FcPrivate FcChar8 *
-FcHashGetSHA256DigestFromMemory (const char *fontdata,
-				 size_t      length);
-
 /* fcinit.c */
 FcPrivate FcConfig *
 FcInitLoadOwnConfig (FcConfig *config);
@@ -865,6 +883,9 @@ FcInitLoadOwnConfigAndFonts (FcConfig *c
 
 /* fcxml.c */
 FcPrivate void
+FcConfigPathFini (void);
+
+FcPrivate void
 FcTestDestroy (FcTest *test);
 
 FcPrivate void
@@ -1008,6 +1029,9 @@ FcPatternObjectAddBool (FcPattern *p, Fc
 FcPrivate FcBool
 FcPatternObjectAddLangSet (FcPattern *p, FcObject object, const FcLangSet *ls);
 
+FcPrivate FcBool
+FcPatternObjectAddRange (FcPattern *p, FcObject object, const FcRange *r);
+
 FcPrivate FcResult
 FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int n, int *i);
 
@@ -1029,9 +1053,15 @@ FcPatternObjectGetBool (const FcPattern 
 FcPrivate FcResult
 FcPatternObjectGetLangSet (const FcPattern *p, FcObject object, int n, FcLangSet **ls);
 
+FcPrivate FcResult
+FcPatternObjectGetRange (const FcPattern *p, FcObject object, int id, FcRange **r);
+
 FcPrivate FcBool
 FcPatternAppend (FcPattern *p, FcPattern *s);
 
+FcPrivate int
+FcPatternPosition (const FcPattern *p, const char *object);
+
 FcPrivate FcChar32
 FcStringHash (const FcChar8 *s);
 
@@ -1056,6 +1086,26 @@ extern FcPrivate const FcMatrix    FcIde
 FcPrivate void
 FcMatrixFree (FcMatrix *mat);
 
+/* fcrange.c */
+
+FcPrivate FcRange *
+FcRangePromote (double v, FcValuePromotionBuffer *vbuf);
+
+FcPrivate FcBool
+FcRangeIsInRange (const FcRange *a, const FcRange *b);
+
+FcPrivate FcBool
+FcRangeCompare (FcOp op, const FcRange *a, const FcRange *b);
+
+FcPrivate FcChar32
+FcRangeHash (const FcRange *r);
+
+FcPrivate FcBool
+FcRangeSerializeAlloc (FcSerialize *serialize, const FcRange *r);
+
+FcPrivate FcRange *
+FcRangeSerialize (FcSerialize *serialize, const FcRange *r);
+
 /* fcstat.c */
 
 FcPrivate int
@@ -1071,6 +1121,9 @@ FcPrivate FcBool
 FcIsFsMtimeBroken (const FcChar8 *dir);
 
 /* fcstr.c */
+FcPrivate FcStrSet *
+FcStrSetCreateEx (unsigned int control);
+
 FcPrivate FcBool
 FcStrSetAddLangs (FcStrSet *strs, const char *languages);
 
@@ -1104,12 +1157,6 @@ FcStrCmpIgnoreBlanksAndCase (const FcCha
 FcPrivate int
 FcStrCmpIgnoreCaseAndDelims (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *delims);
 
-FcPrivate FcBool
-FcStrRegexCmp (const FcChar8 *s, const FcChar8 *regex);
-
-FcPrivate FcBool
-FcStrRegexCmpIgnoreCase (const FcChar8 *s, const FcChar8 *regex);
-
 FcPrivate const FcChar8 *
 FcStrContainsIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2);
 
@@ -1150,6 +1197,9 @@ FcStrSerialize (FcSerialize *serialize, 
 
 /* fcobjs.c */
 
+FcPrivate void
+FcObjectFini (void);
+
 FcPrivate FcObject
 FcObjectLookupIdByName (const char *str);
 
Index: xsrc/external/mit/fontconfig/dist/src/fcmatch.c
diff -u xsrc/external/mit/fontconfig/dist/src/fcmatch.c:1.7 xsrc/external/mit/fontconfig/dist/src/fcmatch.c:1.8
--- xsrc/external/mit/fontconfig/dist/src/fcmatch.c:1.7	Sat Jul 12 04:11:34 2014
+++ xsrc/external/mit/fontconfig/dist/src/fcmatch.c	Tue Aug 29 08:38:50 2017
@@ -191,6 +191,49 @@ FcCompareSize (FcValue *value1, FcValue 
 }
 
 static double
+FcCompareSizeRange (FcValue *v1, FcValue *v2)
+{
+    FcValue value1 = FcValueCanonicalize (v1);
+    FcValue value2 = FcValueCanonicalize (v2);
+    FcRange *r1 = NULL, *r2 = NULL;
+    double ret = -1.0;
+
+    switch ((int) value1.type) {
+    case FcTypeDouble:
+	r1 = FcRangeCreateDouble (value1.u.d, value1.u.d);
+	break;
+    case FcTypeRange:
+	r1 = FcRangeCopy (value1.u.r);
+	break;
+    default:
+	goto bail;
+    }
+    switch ((int) value2.type) {
+    case FcTypeDouble:
+	r2 = FcRangeCreateDouble (value2.u.d, value2.u.d);
+	break;
+    case FcTypeRange:
+	r2 = FcRangeCopy (value2.u.r);
+	break;
+    default:
+	goto bail;
+    }
+
+    if (FcRangeIsInRange (r1, r2))
+	ret = 0.0;
+    else
+	ret = FC_MIN (fabs (r1->end - r2->begin), fabs (r1->begin - r2->end));
+
+bail:
+    if (r1)
+	FcRangeDestroy (r1);
+    if (r2)
+	FcRangeDestroy (r2);
+
+    return ret;
+}
+
+static double
 FcCompareFilename (FcValue *v1, FcValue *v2)
 {
     const FcChar8 *s1 = FcValueString (v1), *s2 = FcValueString (v2);
@@ -204,16 +247,8 @@ FcCompareFilename (FcValue *v1, FcValue 
 	return 3.0;
 }
 
-static double
-FcCompareHash (FcValue *v1, FcValue *v2)
-{
-    const FcChar8 *s1 = FcValueString (v1), *s2 = FcValueString (v2);
 
-    /* Do not match an empty string */
-    if (!s1 || !s2 || !s1[0] || !s2[0])
-	return 1.0;
-    return FcCompareString (v1, v2);
-}
+/* Define priorities to -1 for objects that don't have a compare function. */
 
 #define PRI_NULL(n)				\
     PRI_ ## n ## _STRONG = -1,			\
@@ -228,7 +263,7 @@ FcCompareHash (FcValue *v1, FcValue *v2)
 #define PRI_FcCompareCharSet(n)		PRI1(n)
 #define PRI_FcCompareLang(n)		PRI1(n)
 #define PRI_FcComparePostScript(n)	PRI1(n)
-#define PRI_FcCompareHash(n)		PRI1(n)
+#define PRI_FcCompareSizeRange(n)	PRI1(n)
 
 #define FC_OBJECT(NAME, Type, Cmp)	PRI_##Cmp(NAME)
 
@@ -238,6 +273,9 @@ typedef enum _FcMatcherPriorityDummy {
 
 #undef FC_OBJECT
 
+
+/* Canonical match priority order. */
+
 #undef PRI1
 #define PRI1(n)					\
     PRI_ ## n,					\
@@ -245,10 +283,10 @@ typedef enum _FcMatcherPriorityDummy {
     PRI_ ## n ## _WEAK = PRI_ ## n
 
 typedef enum _FcMatcherPriority {
-    PRI1(HASH),
     PRI1(FILE),
     PRI1(FONTFORMAT),
     PRI1(SCALABLE),
+    PRI1(COLOR),
     PRI1(FOUNDRY),
     PRI1(CHARSET),
     PRI_FAMILY_STRONG,
@@ -256,7 +294,9 @@ typedef enum _FcMatcherPriority {
     PRI1(LANG),
     PRI_FAMILY_WEAK,
     PRI_POSTSCRIPT_NAME_WEAK,
+    PRI1(SYMBOL),
     PRI1(SPACING),
+    PRI1(SIZE),
     PRI1(PIXEL_SIZE),
     PRI1(STYLE),
     PRI1(SLANT),
@@ -336,10 +376,17 @@ FcCompareValueList (FcObject	     object
 	return FcTrue;
     }
 
+#if 0
     best = DBL_MAX;
     bestStrong = DBL_MAX;
     bestWeak = DBL_MAX;
     j = 1;
+#else
+    best = 1e99;
+    bestStrong = 1e99;
+    bestWeak = 1e99;
+    j = 0;
+#endif
     for (v1 = v1orig; v1; v1 = FcValueListNext(v1))
     {
 	for (v2 = v2orig, k = 0; v2; v2 = FcValueListNext(v2), k++)
@@ -447,7 +494,7 @@ FcFontRenderPrepare (FcConfig	    *confi
 {
     FcPattern	    *new;
     int		    i;
-    FcPatternElt    *fe, *pe, *fel, *pel;
+    FcPatternElt    *fe, *pe;
     FcValue	    v;
     FcResult	    result;
 
@@ -472,36 +519,25 @@ FcFontRenderPrepare (FcConfig	    *confi
 	    fe->object == FC_STYLE_OBJECT ||
 	    fe->object == FC_FULLNAME_OBJECT)
 	{
+	    FcPatternElt    *fel, *pel;
+
 	    FC_ASSERT_STATIC ((FC_FAMILY_OBJECT + 1) == FC_FAMILYLANG_OBJECT);
 	    FC_ASSERT_STATIC ((FC_STYLE_OBJECT + 1) == FC_STYLELANG_OBJECT);
 	    FC_ASSERT_STATIC ((FC_FULLNAME_OBJECT + 1) == FC_FULLNAMELANG_OBJECT);
 
 	    fel = FcPatternObjectFindElt (font, fe->object + 1);
 	    pel = FcPatternObjectFindElt (pat, fe->object + 1);
-	}
-	else
-	{
-	    fel = NULL;
-	    pel = NULL;
-	}
-	pe = FcPatternObjectFindElt (pat, fe->object);
-	if (pe)
-	{
-	    const FcMatcher *match = FcObjectToMatcher (pe->object, FcFalse);
 
-	    if (!FcCompareValueList (pe->object, match,
-				     FcPatternEltValues(pe),
-				     FcPatternEltValues(fe), &v, NULL, NULL, &result))
-	    {
-		FcPatternDestroy (new);
-		return NULL;
-	    }
 	    if (fel && pel)
 	    {
+		/* The font has name languages, and pattern asks for specific language(s).
+		 * Match on language and and prefer that result.
+		 * Note:  Currently the code only give priority to first matching language.
+		 */
 		int n = 1, j;
 		FcValueListPtr l1, l2, ln = NULL, ll = NULL;
+		const FcMatcher *match = FcObjectToMatcher (pel->object, FcTrue);
 
-		match = FcObjectToMatcher (pel->object, FcTrue);
 		if (!FcCompareValueList (pel->object, match,
 					 FcPatternEltValues (pel),
 					 FcPatternEltValues (fel), NULL, NULL, &n, &result))
@@ -544,9 +580,10 @@ FcFontRenderPrepare (FcConfig	    *confi
 	    }
 	    else if (fel)
 	    {
+		/* Pattern doesn't ask for specific language.  Copy all for name and
+		 * lang. */
 		FcValueListPtr l1, l2;
 
-	    copy_lang:
 		l1 = FcValueListDuplicate (FcPatternEltValues (fe));
 		l2 = FcValueListDuplicate (FcPatternEltValues (fel));
 		FcPatternObjectListAdd (new, fe->object, l1, FcFalse);
@@ -554,12 +591,23 @@ FcFontRenderPrepare (FcConfig	    *confi
 
 		continue;
 	    }
+	}
+
+	pe = FcPatternObjectFindElt (pat, fe->object);
+	if (pe)
+	{
+	    const FcMatcher *match = FcObjectToMatcher (pe->object, FcFalse);
+	    if (!FcCompareValueList (pe->object, match,
+				     FcPatternEltValues(pe),
+				     FcPatternEltValues(fe), &v, NULL, NULL, &result))
+	    {
+		FcPatternDestroy (new);
+		return NULL;
+	    }
 	    FcPatternObjectAdd (new, fe->object, v, FcFalse);
 	}
 	else
 	{
-	    if (fel)
-		goto copy_lang;
 	    FcPatternObjectListAdd (new, fe->object,
 				    FcValueListDuplicate (FcPatternEltValues (fe)),
 				    FcTrue);
@@ -650,6 +698,47 @@ FcFontSetMatchInternal (FcFontSet   **se
 	printf ("\n");
 	FcPatternPrint (best);
     }
+    if (FcDebug () & FC_DBG_MATCH2)
+    {
+	char *env = getenv ("FC_DBG_MATCH_FILTER");
+	FcObjectSet *os = NULL;
+
+	if (env)
+	{
+	    char *ss, *s;
+	    char *p;
+	    FcBool f = FcTrue;
+
+	    ss = s = strdup (env);
+	    os = FcObjectSetCreate ();
+	    while (f)
+	    {
+		size_t len;
+		char *x;
+
+		if (!(p = strchr (s, ',')))
+		{
+		    f = FcFalse;
+		    len = strlen (s) + 1;
+		}
+		else
+		{
+		    len = (p - s) + 1;
+		}
+		x = malloc (sizeof (char) * len);
+		strncpy (x, s, len - 1);
+		x[len - 1] = 0;
+		if (FcObjectFromName (x) > 0)
+		    FcObjectSetAdd (os, x);
+		s = p + 1;
+		free (x);
+	    }
+	    free (ss);
+	}
+	FcPatternPrint2 (p, best, os);
+	if (os)
+	    FcObjectSetDestroy (os);
+    }
     /* assuming that 'result' is initialized with FcResultNoMatch
      * outside this function */
     if (best)
Index: xsrc/external/mit/fontconfig/dist/src/fcname.c
diff -u xsrc/external/mit/fontconfig/dist/src/fcname.c:1.7 xsrc/external/mit/fontconfig/dist/src/fcname.c:1.8
--- xsrc/external/mit/fontconfig/dist/src/fcname.c:1.7	Sat Jul 12 04:11:34 2014
+++ xsrc/external/mit/fontconfig/dist/src/fcname.c	Tue Aug 29 08:38:50 2017
@@ -87,6 +87,12 @@ FcObjectValidType (FcObject object, FcTy
 	    if (type == FcTypeLangSet || type == FcTypeString)
 		return FcTrue;
 	    break;
+	case FcTypeRange:
+	    if (type == FcTypeRange ||
+		type == FcTypeDouble ||
+		type == FcTypeInteger)
+		return FcTrue;
+	    break;
 	default:
 	    if (type == t->type)
 		return FcTrue;
@@ -132,6 +138,8 @@ static const FcConstant _FcBaseConstants
     { (FcChar8 *) "thin",	    "weight",   FC_WEIGHT_THIN, },
     { (FcChar8 *) "extralight",	    "weight",   FC_WEIGHT_EXTRALIGHT, },
     { (FcChar8 *) "ultralight",	    "weight",   FC_WEIGHT_EXTRALIGHT, },
+    { (FcChar8 *) "demilight",	    "weight",   FC_WEIGHT_DEMILIGHT, },
+    { (FcChar8 *) "semilight",	    "weight",   FC_WEIGHT_DEMILIGHT, },
     { (FcChar8 *) "light",	    "weight",   FC_WEIGHT_LIGHT, },
     { (FcChar8 *) "book",	    "weight",	FC_WEIGHT_BOOK, },
     { (FcChar8 *) "regular",	    "weight",   FC_WEIGHT_REGULAR, },
@@ -273,6 +281,8 @@ FcNameConvert (FcType type, FcChar8 *str
 {
     FcValue	v;
     FcMatrix	m;
+    double	b, e;
+    char	*p;
 
     v.type = type;
     switch ((int) v.type) {
@@ -307,6 +317,20 @@ FcNameConvert (FcType type, FcChar8 *str
 	if (!v.u.l)
 	    v.type = FcTypeVoid;
 	break;
+    case FcTypeRange:
+	if (sscanf ((char *) string, "[%lg %lg)", &b, &e) != 2)
+	{
+	    v.u.d = strtod ((char *) string, &p);
+	    if (p != NULL && p[0] != 0)
+	    {
+		v.type = FcTypeVoid;
+		break;
+	    }
+	    v.type = FcTypeDouble;
+	}
+	else
+	    v.u.r = FcRangeCreateDouble (b, e);
+	break;
     default:
 	break;
     }
@@ -501,6 +525,9 @@ FcNameUnparseValue (FcStrBuf	*buf,
 	return FcNameUnparseLangSet (buf, v.u.l);
     case FcTypeFTFace:
 	return FcTrue;
+    case FcTypeRange:
+	sprintf ((char *) temp, "[%g %g)", v.u.r->begin, v.u.r->end);
+	return FcNameUnparseString (buf, temp, 0);
     }
     return FcFalse;
 }
@@ -533,12 +560,13 @@ FcNameUnparse (FcPattern *pat)
 FcChar8 *
 FcNameUnparseEscaped (FcPattern *pat, FcBool escape)
 {
-    FcStrBuf		    buf;
-    FcChar8		    buf_static[8192];
+    FcStrBuf		    buf, buf2;
+    FcChar8		    buf_static[8192], buf2_static[256];
     int			    i;
     FcPatternElt	    *e;
 
     FcStrBufInit (&buf, buf_static, sizeof (buf_static));
+    FcStrBufInit (&buf2, buf2_static, sizeof (buf2_static));
     e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT);
     if (e)
     {
@@ -548,10 +576,17 @@ FcNameUnparseEscaped (FcPattern *pat, Fc
     e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT);
     if (e)
     {
-	if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0))
+	FcChar8 *p;
+
+	if (!FcNameUnparseString (&buf2, (FcChar8 *) "-", 0))
 	    goto bail0;
-	if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
+	if (!FcNameUnparseValueList (&buf2, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
 	    goto bail0;
+	p = FcStrBufDoneStatic (&buf2);
+	FcStrBufDestroy (&buf2);
+	if (strlen ((const char *)p) > 1)
+	    if (!FcStrBufString (&buf, p))
+		goto bail0;
     }
     for (i = 0; i < NUM_OBJECT_TYPES; i++)
     {

Index: xsrc/external/mit/fontconfig/dist/src/fcstat.c
diff -u xsrc/external/mit/fontconfig/dist/src/fcstat.c:1.6 xsrc/external/mit/fontconfig/dist/src/fcstat.c:1.7
--- xsrc/external/mit/fontconfig/dist/src/fcstat.c:1.6	Fri Dec 16 15:10:08 2016
+++ xsrc/external/mit/fontconfig/dist/src/fcstat.c	Tue Aug 29 08:38:50 2017
@@ -42,6 +42,7 @@
 #ifdef HAVE_SYS_MOUNT_H
 #include <sys/mount.h>
 #endif
+#include <errno.h>
 
 #ifdef _WIN32
 #ifdef __GNUC__
@@ -164,21 +165,86 @@ FcDirChecksumScandirFilter(const struct 
 }
 #endif
 
-#ifdef HAVE_SCANDIR
 static int
 FcDirChecksumScandirSorter(const struct dirent **lhs, const struct dirent **rhs)
 {
     return strcmp((*lhs)->d_name, (*rhs)->d_name);
 }
-#elif HAVE_SCANDIR_VOID_P
-static int
-FcDirChecksumScandirSorter(const void *a, const void *b)
+
+static void
+free_dirent (struct dirent **p)
 {
-    const struct dirent *lhs = a, *rhs = b;
+    struct dirent **x;
+
+    for (x = p; *x != NULL; x++)
+	free (*x);
 
-    return strcmp(lhs->d_name, rhs->d_name);
+    free (p);
+}
+
+int
+FcScandir (const char		*dirp,
+	   struct dirent	***namelist,
+	   int (*filter) (const struct dirent *),
+	   int (*compar) (const struct dirent **, const struct dirent **));
+
+int
+FcScandir (const char		*dirp,
+	   struct dirent	***namelist,
+	   int (*filter) (const struct dirent *),
+	   int (*compar) (const struct dirent **, const struct dirent **))
+{
+    DIR *d;
+    struct dirent *dent, *p, **dlist, **dlp;
+    size_t lsize = 128, n = 0;
+
+    d = opendir (dirp);
+    if (!d)
+	return -1;
+
+    dlist = (struct dirent **) malloc (sizeof (struct dirent *) * lsize);
+    if (!dlist)
+    {
+	closedir (d);
+	errno = ENOMEM;
+
+	return -1;
+    }
+    *dlist = NULL;
+    while ((dent = readdir (d)))
+    {
+	if (!filter || (filter) (dent))
+	{
+	    size_t dentlen = FcPtrToOffset (dent, dent->d_name) + strlen (dent->d_name) + 1;
+	    dentlen = ((dentlen + ALIGNOF_VOID_P - 1) & ~(ALIGNOF_VOID_P - 1));
+	    p = (struct dirent *) malloc (dentlen);
+	    memcpy (p, dent, dentlen);
+	    if ((n + 1) >= lsize)
+	    {
+		lsize += 128;
+		dlp = (struct dirent **) realloc (dlist, sizeof (struct dirent *) * lsize);
+		if (!dlp)
+		{
+		    free_dirent (dlist);
+		    closedir (d);
+		    errno = ENOMEM;
+
+		    return -1;
+		}
+		dlist = dlp;
+	    }
+	    dlist[n++] = p;
+	    dlist[n] = NULL;
+	}
+    }
+    closedir (d);
+
+    qsort (dlist, n, sizeof (struct dirent *), (int (*) (const void *, const void *))compar);
+
+    *namelist = dlist;
+
+    return n;
 }
-#endif
 
 static int
 FcDirChecksum (const FcChar8 *dir, time_t *checksum)
@@ -191,7 +257,7 @@ FcDirChecksum (const FcChar8 *dir, time_
 
     Adler32Init (&ctx);
 
-    n = scandir ((const char *)dir, &files,
+    n = FcScandir ((const char *)dir, &files,
 #ifdef HAVE_STRUCT_DIRENT_D_TYPE
 		 &FcDirChecksumScandirFilter,
 #else
@@ -212,8 +278,13 @@ FcDirChecksum (const FcChar8 *dir, time_
 	{
 #endif
 	struct stat statb;
-	char f[PATH_MAX + 1];
+	char *f = malloc (len + 1 + dlen + 1);
 
+	if (!f)
+	{
+	    ret = -1;
+	    goto bail;
+	}
 	memcpy (f, dir, len);
 	f[len] = FC_DIR_SEPARATOR;
 	memcpy (&f[len + 1], files[n]->d_name, dlen);
@@ -221,11 +292,16 @@ FcDirChecksum (const FcChar8 *dir, time_
 	if (lstat (f, &statb) < 0)
 	{
 	    ret = -1;
+	    free (f);
 	    goto bail;
 	}
 	if (S_ISDIR (statb.st_mode))
+	{
+	    free (f);
 	    goto bail;
+	}
 
+	free (f);
 	dtype = statb.st_mode;
 #ifdef HAVE_STRUCT_DIRENT_D_TYPE
 	}
@@ -360,3 +436,7 @@ FcIsFsMtimeBroken (const FcChar8 *dir)
 
     return FcFalse;
 }
+
+#define __fcstat__
+#include "fcaliastail.h"
+#undef __fcstat__

Index: xsrc/external/mit/fontconfig/include/config.h
diff -u xsrc/external/mit/fontconfig/include/config.h:1.6 xsrc/external/mit/fontconfig/include/config.h:1.7
--- xsrc/external/mit/fontconfig/include/config.h:1.6	Fri Dec 16 16:00:22 2016
+++ xsrc/external/mit/fontconfig/include/config.h	Tue Aug 29 08:38:50 2017
@@ -5,7 +5,10 @@
 /* #undef AC_APPLE_UNIVERSAL_BUILD */
 
 /* The normal alignment of `double', in bytes. */
-#define ALIGNOF_DOUBLE 8
+#define ALIGNOF_DOUBLE 4
+
+/* The normal alignment of `void *', in bytes. */
+#define ALIGNOF_VOID_P 4
 
 /* Use libxml2 instead of Expat */
 /* #undef ENABLE_LIBXML2 */
@@ -16,10 +19,11 @@
 /* Architecture prefix to use for cache file names */
 /* #undef FC_ARCHITECTURE */
 
-#if 0
 /* System font directory */
 #define FC_DEFAULT_FONTS "/usr/share/fonts"
-#endif
+
+/* The type of len parameter of the gperf hash/lookup function */
+#define FC_GPERF_SIZE_T size_t
 
 /* Define to nothing if C supports flexible array members, and to 1 if it does
    not. That way, with a declaration like `struct s { int n; double
@@ -85,10 +89,8 @@
 /* Define to 1 if you have the `getprogname' function. */
 #define HAVE_GETPROGNAME 1
 
-//#if 0 // fontconfig 2.10, but we should have this in -current now
 /* Have Intel __sync_* atomic primitives */
 #define HAVE_INTEL_ATOMIC_PRIMITIVES 1
-//#endif
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #define HAVE_INTTYPES_H 1
@@ -109,7 +111,7 @@
 #define HAVE_MKDTEMP 1
 
 /* Define to 1 if you have the `mkostemp' function. */
-/* #undef HAVE_MKOSTEMP */
+#define HAVE_MKOSTEMP 1
 
 /* Define to 1 if you have the `mkstemp' function. */
 #define HAVE_MKSTEMP 1
@@ -120,11 +122,11 @@
 /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
 /* #undef HAVE_NDIR_H */
 
-/* Define to 1 if you have the 'posix_fadivse' function. */
+/* Define to 1 if you have the 'posix_fadvise' function. */
 #define HAVE_POSIX_FADVISE 1
 
 /* Have POSIX threads */
-#define HAVE_PTHREAD 1
+/* #undef HAVE_PTHREAD */
 
 /* Have PTHREAD_PRIO_INHERIT. */
 /* #undef HAVE_PTHREAD_PRIO_INHERIT */
@@ -144,28 +146,6 @@
 /* Define to 1 if you have the `readlink' function. */
 #define HAVE_READLINK 1
 
-/* Define to 1 if you have the `regcomp' function. */
-#define HAVE_REGCOMP 1
-
-/* Define to 1 if you have the `regerror' function. */
-#define HAVE_REGERROR 1
-
-/* Define to 1 if you have the `regexec' function. */
-#define HAVE_REGEXEC 1
-
-/* Define to 1 if you have the <regex.h> header file. */
-#define HAVE_REGEX_H 1
-
-/* Define to 1 if you have the `regfree' function. */
-#define HAVE_REGFREE 1
-
-/* Define to 1 if you have the 'scandir' function. */
-#define HAVE_SCANDIR 1
-
-/* Define to 1 if you have the 'scandir' function with int (* compar)(const
-   void *, const void *) */
-/* #undef HAVE_SCANDIR_VOID_P */
-
 /* Define to 1 if you have the <sched.h> header file. */
 /* #undef HAVE_SCHED_H */
 
@@ -202,6 +182,9 @@
 /* Define to 1 if `f_fstypename' is a member of `struct statvfs'. */
 #define HAVE_STRUCT_STATVFS_F_FSTYPENAME 1
 
+/* Define to 1 if `st_mtim' is a member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_MTIM 1
+
 /* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
    */
 /* #undef HAVE_SYS_DIR_H */
@@ -231,6 +214,12 @@
 /* Define to 1 if you have the <sys/vfs.h> header file. */
 /* #undef HAVE_SYS_VFS_H */
 
+/* Define to 1 if `usLowerOpticalPointSize' is a member of `TT_OS2'. */
+#define HAVE_TT_OS2_USLOWEROPTICALPOINTSIZE 1
+
+/* Define to 1 if `usUpperOpticalPointSize' is a member of `TT_OS2'. */
+#define HAVE_TT_OS2_USUPPEROPTICALPOINTSIZE 1
+
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
@@ -249,8 +238,7 @@
 /* Define to 1 if you have the `_mktemp_s' function. */
 /* #undef HAVE__MKTEMP_S */
 
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
-   */
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
 #define LT_OBJDIR ".libs/"
 
 /* Name of package */
@@ -263,7 +251,7 @@
 #define PACKAGE_NAME "fontconfig"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "fontconfig 2.11.0"
+#define PACKAGE_STRING "fontconfig 2.12.4"
 
 /* Define to the one symbol short name of this package. */
 #define PACKAGE_TARNAME "fontconfig"
@@ -272,7 +260,7 @@
 #define PACKAGE_URL ""
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "2.11.0"
+#define PACKAGE_VERSION "2.12.4"
 
 /* Define to necessary symbol if this constant uses a non-standard name on
    your system. */
@@ -294,7 +282,7 @@
 /* #undef SIZEOF_VOIDP */
 
 /* The size of `void *', as computed by sizeof. */
-#define SIZEOF_VOID_P 8
+#define SIZEOF_VOID_P 4
 
 /* Define to 1 if you have the ANSI C header files. */
 #define STDC_HEADERS 1
@@ -302,9 +290,6 @@
 /* Use iconv. */
 #define USE_ICONV 0
 
-/* Use regex */
-#define USE_REGEX /**/
-
 /* Enable extensions on AIX 3, Interix.  */
 #ifndef _ALL_SOURCE
 # define _ALL_SOURCE 1
@@ -328,7 +313,7 @@
 
 
 /* Version number of package */
-#define VERSION "2.11.0"
+#define VERSION "2.12.4"
 
 /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
    significant byte first (like Motorola and SPARC, unlike Intel). */

Reply via email to