Module Name:    xsrc
Committed By:   mrg
Date:           Fri Mar  8 09:49:08 UTC 2019

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 fcformat.c
            fcfreetype.c fcinit.c fcint.h fcmatch.c fcname.c fcstat.c
Added Files:
        xsrc/external/mit/fontconfig/dist/src: fchash.c
Removed Files:
        xsrc/external/mit/fontconfig/dist/conf.d: 30-urw-aliases.conf
        xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel: x102.html
        xsrc/external/mit/fontconfig/dist/fc-blanks: Makefile.am Makefile.in
            fc-blanks.py fcblanks.h fcblanks.tmpl.h
        xsrc/external/mit/fontconfig/dist/fc-glyphname: Makefile.am Makefile.in
            fc-glyphname.c fcglyphname.h fcglyphname.tmpl.h zapfdingbats.txt
        xsrc/external/mit/fontconfig/dist/src: fcblanks.c fcobjshash.gperf
            fcobjshash.h
        xsrc/external/mit/fontconfig/dist/test: out.expected out271.expected
            run-test271.sh

Log Message:
merge fontconfig 2.13.1.


To generate a diff of this commit:
cvs rdiff -u -r1.1.1.5 -r0 \
    xsrc/external/mit/fontconfig/dist/conf.d/30-urw-aliases.conf
cvs rdiff -u -r1.4 -r1.5 \
    xsrc/external/mit/fontconfig/dist/doc/FcLangSetGetLangs.3
cvs rdiff -u -r1.4 -r1.5 \
    
xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel/fclangsetgetlangs.html
cvs rdiff -u -r1.1.1.7 -r0 \
    xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel/x102.html
cvs rdiff -u -r1.1.1.1 -r0 \
    xsrc/external/mit/fontconfig/dist/fc-blanks/Makefile.am \
    xsrc/external/mit/fontconfig/dist/fc-blanks/Makefile.in \
    xsrc/external/mit/fontconfig/dist/fc-blanks/fc-blanks.py \
    xsrc/external/mit/fontconfig/dist/fc-blanks/fcblanks.h \
    xsrc/external/mit/fontconfig/dist/fc-blanks/fcblanks.tmpl.h
cvs rdiff -u -r1.7 -r1.8 \
    xsrc/external/mit/fontconfig/dist/fc-cache/fc-cache.c
cvs rdiff -u -r1.1.1.4 -r0 \
    xsrc/external/mit/fontconfig/dist/fc-glyphname/Makefile.am
cvs rdiff -u -r1.1.1.7 -r0 \
    xsrc/external/mit/fontconfig/dist/fc-glyphname/Makefile.in
cvs rdiff -u -r1.1.1.5 -r0 \
    xsrc/external/mit/fontconfig/dist/fc-glyphname/fc-glyphname.c
cvs rdiff -u -r1.1.1.1 -r0 \
    xsrc/external/mit/fontconfig/dist/fc-glyphname/fcglyphname.h \
    xsrc/external/mit/fontconfig/dist/fc-glyphname/zapfdingbats.txt
cvs rdiff -u -r1.1.1.3 -r0 \
    xsrc/external/mit/fontconfig/dist/fc-glyphname/fcglyphname.tmpl.h
cvs rdiff -u -r1.1.1.5 -r0 xsrc/external/mit/fontconfig/dist/src/fcblanks.c
cvs rdiff -u -r1.9 -r1.10 xsrc/external/mit/fontconfig/dist/src/fccache.c
cvs rdiff -u -r1.3 -r1.4 xsrc/external/mit/fontconfig/dist/src/fccfg.c \
    xsrc/external/mit/fontconfig/dist/src/fcinit.c
cvs rdiff -u -r1.2 -r1.3 xsrc/external/mit/fontconfig/dist/src/fcformat.c \
    xsrc/external/mit/fontconfig/dist/src/fcfreetype.c
cvs rdiff -u -r0 -r1.5 xsrc/external/mit/fontconfig/dist/src/fchash.c
cvs rdiff -u -r1.8 -r1.9 xsrc/external/mit/fontconfig/dist/src/fcint.h \
    xsrc/external/mit/fontconfig/dist/src/fcname.c \
    xsrc/external/mit/fontconfig/dist/src/fcstat.c
cvs rdiff -u -r1.10 -r1.11 xsrc/external/mit/fontconfig/dist/src/fcmatch.c
cvs rdiff -u -r1.1.1.2 -r0 \
    xsrc/external/mit/fontconfig/dist/src/fcobjshash.gperf
cvs rdiff -u -r1.2 -r0 xsrc/external/mit/fontconfig/dist/src/fcobjshash.h
cvs rdiff -u -r1.1.1.1 -r0 \
    xsrc/external/mit/fontconfig/dist/test/out.expected \
    xsrc/external/mit/fontconfig/dist/test/out271.expected \
    xsrc/external/mit/fontconfig/dist/test/run-test271.sh

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.4 xsrc/external/mit/fontconfig/dist/doc/FcLangSetGetLangs.3:1.5
--- xsrc/external/mit/fontconfig/dist/doc/FcLangSetGetLangs.3:1.4	Tue Aug 29 08:38:50 2017
+++ xsrc/external/mit/fontconfig/dist/doc/FcLangSetGetLangs.3	Fri Mar  8 09:49:07 2019
@@ -1,5 +1,5 @@
 .\" auto-generated by docbook2man-spec from docbook-utils package
-.TH "FcLangSetGetLangs" "3" "05 7月 2017" "Fontconfig 2.12.4" ""
+.TH "FcLangSetGetLangs" "3" "30 8月 2018" "Fontconfig 2.13.1" ""
 .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.4 xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel/fclangsetgetlangs.html:1.5
--- xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel/fclangsetgetlangs.html:1.4	Tue Aug 29 08:38:50 2017
+++ xsrc/external/mit/fontconfig/dist/doc/fontconfig-devel/fclangsetgetlangs.html	Fri Mar  8 09:49:07 2019
@@ -10,7 +10,7 @@ REL="HOME"
 HREF="t1.html"><LINK
 REL="UP"
 TITLE="FcLangSet"
-HREF="x102.html#AEN2016"><LINK
+HREF="x103.html#AEN2336"><LINK
 REL="PREVIOUS"
 TITLE="FcGetDefaultLangs"
 HREF="fcgetdefaultlangs.html"><LINK
@@ -75,7 +75,7 @@ NAME="FCLANGSETGETLANGS"
 ><DIV
 CLASS="REFNAMEDIV"
 ><A
-NAME="AEN2334"
+NAME="AEN2654"
 ></A
 ><H2
 >Name</H2
@@ -83,7 +83,7 @@ NAME="AEN2334"
 ><DIV
 CLASS="REFSYNOPSISDIV"
 ><A
-NAME="AEN2337"
+NAME="AEN2657"
 ></A
 ><H2
 >Synopsis</H2
@@ -92,7 +92,7 @@ CLASS="FUNCSYNOPSIS"
 ><P
 ></P
 ><A
-NAME="AEN2338"
+NAME="AEN2658"
 ></A
 ><TABLE
 BORDER="0"
@@ -129,7 +129,7 @@ CLASS="PARAMETER"
 ><DIV
 CLASS="REFSECT1"
 ><A
-NAME="AEN2345"
+NAME="AEN2665"
 ></A
 ><H2
 >Description</H2
@@ -192,7 +192,7 @@ WIDTH="34%"
 ALIGN="center"
 VALIGN="top"
 ><A
-HREF="x102.html#AEN2016"
+HREF="x103.html#AEN2336"
 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.7 xsrc/external/mit/fontconfig/dist/fc-cache/fc-cache.c:1.8
--- xsrc/external/mit/fontconfig/dist/fc-cache/fc-cache.c:1.7	Tue Aug 29 08:38:50 2017
+++ xsrc/external/mit/fontconfig/dist/fc-cache/fc-cache.c	Fri Mar  8 09:49:07 2019
@@ -41,6 +41,7 @@
 #include <fcntl.h>
 #include <dirent.h>
 #include <string.h>
+#include <locale.h>
 
 #if defined (_WIN32)
 #define STRICT
@@ -49,6 +50,14 @@
 #undef STRICT
 #endif
 
+#ifdef ENABLE_NLS
+#include <libintl.h>
+#define _(x)		(dgettext(GETTEXT_PACKAGE, x))
+#else
+#define dgettext(d, s)	(s)
+#define _(x)		(x)
+#endif
+
 #ifndef O_BINARY
 #define O_BINARY 0
 #endif
@@ -87,37 +96,36 @@ static void
 usage (char *program, int error)
 {
     FILE *file = error ? stderr : stdout;
-#if HAVE_GETOPT_LONG
-    fprintf (file, "usage: %s [-EfqrsvVh] [--quick] [-y SYSROOT] [--error-on-no-fonts] [--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 [-EfqrsvVh] [-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, _("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");
-    fprintf (file, "  -s, --system-only        scan system-wide directories only\n");
-    fprintf (file, "  -y, --sysroot=SYSROOT    prepend SYSROOT to all paths for scanning\n");
-    fprintf (file, "  -v, --verbose            display status information while busy\n");
-    fprintf (file, "  -V, --version            display font config version and exit\n");
-    fprintf (file, "  -h, --help               display this help and exit\n");
+    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"));
+    fprintf (file, _("  -s, --system-only        scan system-wide directories only\n"));
+    fprintf (file, _("  -y, --sysroot=SYSROOT    prepend SYSROOT to all paths for scanning\n"));
+    fprintf (file, _("  -v, --verbose            display status information while busy\n"));
+    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");
-    fprintf (file, "  -s         (system)  scan system-wide directories only\n");
-    fprintf (file, "  -y SYSROOT (sysroot) prepend SYSROOT to all paths for scanning\n");
-    fprintf (file, "  -v         (verbose) display status information while busy\n");
-    fprintf (file, "  -V         (version) display font config version and exit\n");
-    fprintf (file, "  -h         (help)    display this help and exit\n");
+    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"));
+    fprintf (file, _("  -s         (system)  scan system-wide directories only\n"));
+    fprintf (file, _("  -y SYSROOT (sysroot) prepend SYSROOT to all paths for scanning\n"));
+    fprintf (file, _("  -v         (verbose) display status information while busy\n"));
+    fprintf (file, _("  -V         (version) display font config version and exit\n"));
+    fprintf (file, _("  -h         (help)    display this help and exit\n"));
 #endif
     exit (error);
 }
@@ -154,7 +162,7 @@ scanDirs (FcStrList *list, FcConfig *con
 	if (FcStrSetMember (processed_dirs, dir))
 	{
 	    if (verbose)
-		printf ("skipping, looped directory detected\n");
+		printf (_("skipping, looped directory detected\n"));
 	    continue;
 	}
 
@@ -164,7 +172,7 @@ scanDirs (FcStrList *list, FcConfig *con
 	    case ENOENT:
 	    case ENOTDIR:
 		if (verbose)
-		    printf ("skipping, no such directory\n");
+		    printf (_("skipping, no such directory\n"));
 		break;
 	    default:
 		fprintf (stderr, "\"%s\": ", dir);
@@ -177,13 +185,16 @@ scanDirs (FcStrList *list, FcConfig *con
 
 	if (!S_ISDIR (statb.st_mode))
 	{
-	    fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
+	    fprintf (stderr, _("\"%s\": not a directory, skipping\n"), dir);
 	    continue;
 	}
 	was_processed = FcTrue;
 
 	if (really_force)
+	{
 	    FcDirCacheUnlink (dir, config);
+	    FcDirCacheCreateUUID ((FcChar8 *) dir, FcTrue, config);
+	}
 
 	cache = NULL;
 	was_valid = FcFalse;
@@ -199,7 +210,7 @@ scanDirs (FcStrList *list, FcConfig *con
 	    cache = FcDirCacheRead (dir, FcTrue, config);
 	    if (!cache)
 	    {
-		fprintf (stderr, "%s: error scanning\n", dir);
+		fprintf (stderr, _("\"%s\": scanning error\n"), dir);
 		ret++;
 		continue;
 	    }
@@ -208,18 +219,18 @@ scanDirs (FcStrList *list, FcConfig *con
 	if (was_valid)
 	{
 	    if (verbose)
-		printf ("skipping, existing cache is valid: %d fonts, %d dirs\n",
+		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", 
+		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);
+		fprintf (stderr, _("%s: failed to write cache\n"), dir);
 		(void) FcDirCacheUnlink (dir, config);
 		ret++;
 	    }
@@ -228,7 +239,7 @@ scanDirs (FcStrList *list, FcConfig *con
 	subdirs = FcStrSetCreate ();
 	if (!subdirs)
 	{
-	    fprintf (stderr, "%s: Can't create subdir set\n", dir);
+	    fprintf (stderr, _("%s: Can't create subdir set\n"), dir);
 	    ret++;
 	    FcDirCacheUnload (cache);
 	    continue;
@@ -242,7 +253,7 @@ scanDirs (FcStrList *list, FcConfig *con
 	FcStrSetDestroy (subdirs);
 	if (!sublist)
 	{
-	    fprintf (stderr, "%s: Can't create subdir list\n", dir);
+	    fprintf (stderr, _("%s: Can't create subdir list\n"), dir);
 	    ret++;
 	    continue;
 	}
@@ -295,6 +306,7 @@ main (int argc, char **argv)
 #if HAVE_GETOPT_LONG || HAVE_GETOPT
     int		c;
 
+    setlocale (LC_ALL, "");
 #if HAVE_GETOPT_LONG
     while ((c = getopt_long (argc, argv, "Efqrsy:Vvh", longopts, NULL)) != -1)
 #else
@@ -321,7 +333,7 @@ main (int argc, char **argv)
 	    sysroot = FcStrCopy ((const FcChar8 *)optarg);
 	    break;
 	case 'V':
-	    fprintf (stderr, "fontconfig version %d.%d.%d\n", 
+	    fprintf (stderr, "fontconfig version %d.%d.%d\n",
 		     FC_MAJOR, FC_MINOR, FC_REVISION);
 	    exit (0);
 	case 'v':
@@ -352,7 +364,7 @@ main (int argc, char **argv)
     }
     if (!config)
     {
-	fprintf (stderr, "%s: Can't init font config library\n", argv[0]);
+	fprintf (stderr, _("%s: Can't initialize font config library\n"), argv[0]);
 	return 1;
     }
     FcConfigSetCurrent (config);
@@ -362,7 +374,7 @@ main (int argc, char **argv)
 	dirs = FcStrSetCreate ();
 	if (!dirs)
 	{
-	    fprintf (stderr, "%s: Can't create list of directories\n",
+	    fprintf (stderr, _("%s: Can't create list of directories\n"),
 		     argv[0]);
 	    return 1;
 	}
@@ -370,7 +382,7 @@ main (int argc, char **argv)
 	{
 	    if (!FcStrSetAddFilename (dirs, (FcChar8 *) argv[i]))
 	    {
-		fprintf (stderr, "%s: Can't add directory\n", argv[0]);
+		fprintf (stderr, _("%s: Can't add directory\n"), argv[0]);
 		return 1;
 	    }
 	    i++;
@@ -379,10 +391,10 @@ main (int argc, char **argv)
 	FcStrSetDestroy (dirs);
     }
     else
-	list = FcConfigGetConfigDirs (config);
+	list = FcConfigGetFontDirs (config);
 
     if ((processed_dirs = FcStrSetCreate()) == NULL) {
-	fprintf(stderr, "Cannot malloc\n");
+	fprintf(stderr, _("Out of Memory\n"));
 	return 1;
     }
 
@@ -414,6 +426,6 @@ main (int argc, char **argv)
     if (!quick && changed)
 	sleep (2);
     if (verbose)
-	printf ("%s: %s\n", argv[0], ret ? "failed" : "succeeded");
+	printf ("%s: %s\n", argv[0], ret ? _("failed") : _("succeeded"));
     return ret;
 }

Index: xsrc/external/mit/fontconfig/dist/src/fccache.c
diff -u xsrc/external/mit/fontconfig/dist/src/fccache.c:1.9 xsrc/external/mit/fontconfig/dist/src/fccache.c:1.10
--- xsrc/external/mit/fontconfig/dist/src/fccache.c:1.9	Tue Aug 29 08:38:50 2017
+++ xsrc/external/mit/fontconfig/dist/src/fccache.c	Fri Mar  8 09:49:07 2019
@@ -30,6 +30,7 @@
 #include <limits.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 #include <assert.h>
 #if defined(HAVE_MMAP) || defined(__CYGWIN__)
 #  include <unistd.h>
@@ -37,12 +38,196 @@
 #endif
 #if defined(_WIN32)
 #include <sys/locking.h>
+#else
+#if !defined TOOL_FCCACHE
+#include <uuid/uuid.h>
+#endif
 #endif
 
 #ifndef O_BINARY
 #define O_BINARY 0
 #endif
 
+FcBool
+FcDirCacheCreateUUID (FcChar8  *dir,
+		      FcBool    force,
+		      FcConfig *config)
+{
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+    FcChar8 *target;
+    FcBool ret = FcTrue;
+#if !defined TOOL_FCCACHE
+#ifndef _WIN32
+    FcChar8 *uuidname;
+
+    if (sysroot)
+	target = FcStrBuildFilename (sysroot, dir, NULL);
+    else
+	target = FcStrdup (dir);
+    uuidname = FcStrBuildFilename (target, ".uuid", NULL);
+
+    if (!uuidname)
+    {
+	FcStrFree (target);
+	return FcFalse;
+    }
+
+    if (force || access ((const char *) uuidname, F_OK) < 0)
+    {
+	FcAtomic *atomic;
+	int fd;
+	uuid_t uuid;
+	char out[37];
+	FcBool (* hash_add) (FcHashTable *, void*, void*);
+	struct stat statb;
+	struct timeval times[2];
+
+	if (FcStat (target, &statb) != 0)
+	{
+	    ret = FcFalse;
+	    goto bail1;
+	}
+	atomic = FcAtomicCreate (uuidname);
+	if (!atomic)
+	{
+	    ret = FcFalse;
+	    goto bail1;
+	}
+	if (!FcAtomicLock (atomic))
+	{
+	    ret = FcFalse;
+	    goto bail2;
+	}
+	fd = FcOpen ((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT, 0644);
+	if (fd == -1)
+	{
+	    ret = FcFalse;
+	    goto bail3;
+	}
+	uuid_generate_random (uuid);
+	if (force)
+	    hash_add = FcHashTableReplace;
+	else
+	    hash_add = FcHashTableAdd;
+	if (!hash_add (config->uuid_table, target, uuid))
+	{
+	    ret = FcFalse;
+	    FcAtomicDeleteNew (atomic);
+	    close (fd);
+	    goto bail3;
+	}
+	uuid_unparse (uuid, out);
+	if (FcDebug () & FC_DBG_CACHE)
+	    printf ("FcDirCacheCreateUUID %s: %s\n", uuidname, out);
+	write (fd, out, strlen (out));
+	close (fd);
+	FcAtomicReplaceOrig (atomic);
+    bail3:
+	FcAtomicUnlock (atomic);
+    bail2:
+	FcAtomicDestroy (atomic);
+
+	if (ret)
+	{
+	    /* revert mtime of the directory */
+	    times[0].tv_sec = statb.st_atime;
+	    times[1].tv_sec = statb.st_mtime;
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+	    times[0].tv_usec = statb.st_atim.tv_nsec / 1000;
+	    times[1].tv_usec = statb.st_mtim.tv_nsec / 1000;
+#else
+	    times[0].tv_usec = 0;
+	    times[1].tv_usec = 0;
+#endif
+	    if (utimes ((const  char *) target, times) != 0)
+	    {
+		fprintf (stderr, "Unable to revert mtime: %s\n", target);
+	    }
+	}
+    }
+bail1:
+    FcStrFree (uuidname);
+    FcStrFree (target);
+#endif
+#endif
+
+    return ret;
+}
+
+FcBool
+FcDirCacheDeleteUUID (const FcChar8  *dir,
+		      FcConfig       *config)
+{
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+    FcChar8 *target;
+    FcBool ret = FcTrue;
+
+    if (sysroot)
+	target = FcStrBuildFilename (sysroot, dir, ".uuid", NULL);
+    else
+	target = FcStrBuildFilename (dir, ".uuid", NULL);
+
+    ret = unlink ((char *) target) == 0;
+    FcHashTableRemove (config->uuid_table, target);
+    FcStrFree(target);
+
+    return ret;
+}
+
+#if !defined TOOL_FCCACHE
+#ifndef _WIN32
+static void
+FcDirCacheReadUUID (FcChar8  *dir,
+		    FcConfig *config)
+{
+    void *u;
+    uuid_t uuid;
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+    FcChar8 *target;
+
+    if (sysroot)
+	target = FcStrBuildFilename (sysroot, dir, NULL);
+    else
+	target = FcStrdup (dir);
+
+    if (!FcHashTableFind (config->uuid_table, target, &u))
+    {
+	FcChar8 *uuidname = FcStrBuildFilename (target, ".uuid", NULL);
+	int fd;
+
+	if ((fd = FcOpen ((char *) uuidname, O_RDONLY)) >= 0)
+	{
+	    char suuid[37];
+	    ssize_t len;
+
+	    memset (suuid, 0, sizeof (suuid));
+	    len = read (fd, suuid, 36);
+	    if (len != -1)
+	    {
+		suuid[len] = 0;
+		memset (uuid, 0, sizeof (uuid));
+		if (uuid_parse (suuid, uuid) == 0)
+		{
+		    if (FcDebug () & FC_DBG_CACHE)
+			printf ("FcDirCacheReadUUID %s -> %s\n", uuidname, suuid);
+		    FcHashTableAdd (config->uuid_table, target, uuid);
+		}
+	    }
+	    close (fd);
+	}
+	else
+	{
+	    if (FcDebug () & FC_DBG_CACHE)
+		printf ("FcDirCacheReadUUID Unable to read %s\n", uuidname);
+	}
+	FcStrFree (uuidname);
+    }
+    else
+	FcHashUuidFree (u);
+    FcStrFree (target);
+}
+#endif
+#endif
 
 struct MD5Context {
         FcChar32 buf[4];
@@ -55,7 +240,7 @@ static void MD5Update(struct MD5Context 
 static void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
 static void MD5Transform(FcChar32 buf[4], FcChar32 in[16]);
 
-#define CACHEBASE_LEN (1 + 32 + 1 + sizeof (FC_ARCHITECTURE) + sizeof (FC_CACHE_SUFFIX))
+#define CACHEBASE_LEN (1 + 36 + 1 + sizeof (FC_ARCHITECTURE) + sizeof (FC_CACHE_SUFFIX))
 
 static FcBool
 FcCacheIsMmapSafe (int fd)
@@ -94,7 +279,7 @@ static const char bin2hex[] = { '0', '1'
 				'c', 'd', 'e', 'f' };
 
 static FcChar8 *
-FcDirCacheBasename (const FcChar8 * dir, FcChar8 cache_base[CACHEBASE_LEN])
+FcDirCacheBasenameMD5 (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
 {
     unsigned char 	hash[16];
     FcChar8		*hex_hash;
@@ -119,6 +304,33 @@ FcDirCacheBasename (const FcChar8 * dir,
     return cache_base;
 }
 
+#if !defined TOOL_FCCACHE
+#ifndef _WIN32
+static FcChar8 *
+FcDirCacheBasenameUUID (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN], FcConfig *config)
+{
+    void *u;
+    FcChar8 *target;
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+
+    if (sysroot)
+	target = FcStrBuildFilename (sysroot, dir, NULL);
+    else
+	target = FcStrdup (dir);
+    if (FcHashTableFind (config->uuid_table, target, &u))
+    {
+	uuid_unparse (u, (char *) cache_base);
+	strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
+	FcHashUuidFree (u);
+	FcStrFree (target);
+	return cache_base;
+    }
+    FcStrFree (target);
+    return NULL;
+}
+#endif
+#endif
+
 FcBool
 FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
 {
@@ -128,7 +340,12 @@ FcDirCacheUnlink (const FcChar8 *dir, Fc
     FcChar8	*cache_dir;
     const FcChar8 *sysroot = FcConfigGetSysRoot (config);
 
-    FcDirCacheBasename (dir, cache_base);
+#if !defined TOOL_FCCACHE
+#ifndef _WIN32
+    if (!FcDirCacheBasenameUUID (dir, cache_base, config))
+#endif
+#endif
+	FcDirCacheBasenameMD5 (dir, cache_base);
 
     list = FcStrListCreate (config->cacheDirs);
     if (!list)
@@ -143,6 +360,7 @@ FcDirCacheUnlink (const FcChar8 *dir, Fc
         if (!cache_hashed)
 	    break;
 	(void) unlink ((char *) cache_hashed);
+	FcDirCacheDeleteUUID (dir, config);
 	FcStrFree (cache_hashed);
     }
     FcStrListDone (list);
@@ -204,7 +422,12 @@ FcDirCacheProcess (FcConfig *config, con
     }
     FcStrFree (d);
 
-    FcDirCacheBasename (dir, cache_base);
+#if !defined TOOL_FCCACHE
+#ifndef _WIN32
+    if (!FcDirCacheBasenameUUID (dir, cache_base, config))
+#endif
+#endif
+	FcDirCacheBasenameMD5 (dir, cache_base);
 
     list = FcStrListCreate (config->cacheDirs);
     if (!list)
@@ -254,6 +477,7 @@ struct _FcCacheSkip {
     FcCache	    *cache;
     FcRef	    ref;
     intptr_t	    size;
+    void	   *allocated;
     dev_t	    cache_dev;
     ino_t	    cache_ino;
     time_t	    cache_mtime;
@@ -379,6 +603,7 @@ FcCacheInsert (FcCache *cache, struct st
 
     s->cache = cache;
     s->size = cache->size;
+    s->allocated = NULL;
     FcRefInit (&s->ref, 1);
     if (cache_stat)
     {
@@ -453,6 +678,7 @@ FcCacheRemoveUnlocked (FcCache *cache)
     FcCacheSkip	    **update[FC_CACHE_MAX_LEVEL];
     FcCacheSkip	    *s, **next;
     int		    i;
+    void            *allocated;
 
     /*
      * Find links along each chain
@@ -470,6 +696,15 @@ FcCacheRemoveUnlocked (FcCache *cache)
 	*update[i] = s->next[i];
     while (fcCacheMaxLevel > 0 && fcCacheChains[fcCacheMaxLevel - 1] == NULL)
 	fcCacheMaxLevel--;
+
+    allocated = s->allocated;
+    while (allocated)
+    {
+	/* First element in allocated chunk is the free list */
+	next = *(void **)allocated;
+	free (allocated);
+	allocated = next;
+    }
     free (s);
 }
 
@@ -485,7 +720,7 @@ FcCacheFindByStat (struct stat *cache_st
 	    s->cache_mtime == cache_stat->st_mtime)
 	{
 #ifdef HAVE_STRUCT_STAT_ST_MTIM
-	    if (s->cache_mtime != cache_stat->st_mtim.tv_nsec)
+	    if (s->cache_mtime_nano != cache_stat->st_mtim.tv_nsec)
 		continue;
 #endif
 	    FcRefInc (&s->ref);
@@ -539,6 +774,30 @@ FcCacheObjectDereference (void *object)
     unlock_cache ();
 }
 
+void *
+FcCacheAllocate (FcCache *cache, size_t len)
+{
+    FcCacheSkip	*skip;
+    void *allocated = NULL;
+
+    lock_cache ();
+    skip = FcCacheFindByAddrUnlocked (cache);
+    if (skip)
+    {
+      void *chunk = malloc (sizeof (void *) + len);
+      if (chunk)
+      {
+	  /* First element in allocated chunk is the free list */
+	  *(void **)chunk = skip->allocated;
+	  skip->allocated = chunk;
+	  /* Return the rest */
+	  allocated = ((FcChar8 *)chunk) + sizeof (void *);
+      }
+    }
+    unlock_cache ();
+    return allocated;
+}
+
 void
 FcCacheFini (void)
 {
@@ -632,7 +891,7 @@ FcCacheOffsetsValid (FcCache *cache)
         if (fs->nfont > (end - (char *) fs) / sizeof (FcPattern))
             return FcFalse;
 
-        if (fs->fonts != 0 && !FcIsEncodedOffset(fs->fonts))
+        if (!FcIsEncodedOffset(fs->fonts))
             return FcFalse;
 
         for (i = 0; i < fs->nfont; i++)
@@ -646,7 +905,8 @@ FcCacheOffsetsValid (FcCache *cache)
                 (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))
+                font->num > (end - (char *) font - font->elts_offset) / sizeof (FcPatternElt) ||
+		!FcRefIsConst (&font->ref))
                 return FcFalse;
 
 
@@ -792,6 +1052,11 @@ FcDirCacheLoad (const FcChar8 *dir, FcCo
 {
     FcCache *cache = NULL;
 
+#if !defined TOOL_FCCACHE
+#ifndef _WIN32
+    FcDirCacheReadUUID ((FcChar8 *) dir, config);
+#endif
+#endif
     if (!FcDirCacheProcess (config, dir,
 			    FcDirCacheMapHelper,
 			    &cache, cache_file))
@@ -817,6 +1082,55 @@ FcDirCacheLoadFile (const FcChar8 *cache
     return cache;
 }
 
+static int
+FcDirChecksum (struct stat *statb)
+{
+    int			ret = (int) statb->st_mtime;
+    char		*endptr;
+    char		*source_date_epoch;
+    unsigned long long	epoch;
+
+    source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+    if (source_date_epoch)
+    {
+	epoch = strtoull(source_date_epoch, &endptr, 10);
+
+	if (endptr == source_date_epoch)
+	    fprintf (stderr,
+		     "Fontconfig: SOURCE_DATE_EPOCH invalid\n");
+	else if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
+		|| (errno != 0 && epoch == 0))
+	    fprintf (stderr,
+		     "Fontconfig: SOURCE_DATE_EPOCH: strtoull: %s: %llu\n",
+		     strerror(errno), epoch);
+	else if (*endptr != '\0')
+	    fprintf (stderr,
+		     "Fontconfig: SOURCE_DATE_EPOCH has trailing garbage\n");
+	else if (epoch > ULONG_MAX)
+	    fprintf (stderr,
+		     "Fontconfig: SOURCE_DATE_EPOCH must be <= %lu but saw: %llu\n",
+		     ULONG_MAX, epoch);
+	else if (epoch < ret)
+	    /* Only override if directory is newer */
+	    ret = (int) epoch;
+    }
+
+    return ret;
+}
+
+static int64_t
+FcDirChecksumNano (struct stat *statb)
+{
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+    /* No nanosecond component to parse */
+    if (getenv("SOURCE_DATE_EPOCH"))
+	return 0;
+    return statb->st_mtim.tv_nsec;
+#else
+    return 0;
+#endif
+}
+
 /*
  * Validate a cache file by reading the header and checking
  * the magic number and the size field
@@ -835,10 +1149,10 @@ FcDirCacheValidateHelper (FcConfig *conf
 	ret = FcFalse;
     else if (fd_stat->st_size != c.size)
 	ret = FcFalse;
-    else if (c.checksum != (int) dir_stat->st_mtime)
+    else if (c.checksum != FcDirChecksum (dir_stat))
 	ret = FcFalse;
 #ifdef HAVE_STRUCT_STAT_ST_MTIM
-    else if (c.checksum_nano != dir_stat->st_mtim.tv_nsec)
+    else if (c.checksum_nano != FcDirChecksumNano (dir_stat))
 	ret = FcFalse;
 #endif
     return ret;
@@ -914,10 +1228,8 @@ FcDirCacheBuild (FcFontSet *set, const F
     cache->magic = FC_CACHE_MAGIC_ALLOC;
     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
+    cache->checksum = FcDirChecksum (dir_stat);
+    cache->checksum_nano = FcDirChecksumNano (dir_stat);
 
     /*
      * Serialize directory name
@@ -1048,11 +1360,16 @@ FcDirCacheWrite (FcCache *cache, FcConfi
     if (!cache_dir)
 	return FcFalse;
 
-    FcDirCacheBasename (dir, cache_base);
+#if !defined TOOL_FCCACHE
+#ifndef _WIN32
+    if (!FcDirCacheBasenameUUID (dir, cache_base, config))
+#endif
+#endif
+	FcDirCacheBasenameMD5 (dir, cache_base);
     cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL);
+    FcStrFree (cache_dir);
     if (!cache_hashed)
         return FcFalse;
-    FcStrFree (cache_dir);
 
     if (FcDebug () & FC_DBG_CACHE)
         printf ("FcDirCacheWriteDir dir \"%s\" file \"%s\"\n",
@@ -1245,7 +1562,12 @@ FcDirCacheLock (const FcChar8 *dir,
     const FcChar8 *sysroot = FcConfigGetSysRoot (config);
     int fd = -1;
 
-    FcDirCacheBasename (dir, cache_base);
+#if !defined TOOL_FCCACHE
+#ifndef _WIN32
+    if (!FcDirCacheBasenameUUID (dir, cache_base, config))
+#endif
+#endif
+	FcDirCacheBasenameMD5 (dir, cache_base);
     list = FcStrListCreate (config->cacheDirs);
     if (!list)
 	return -1;

Index: xsrc/external/mit/fontconfig/dist/src/fccfg.c
diff -u xsrc/external/mit/fontconfig/dist/src/fccfg.c:1.3 xsrc/external/mit/fontconfig/dist/src/fccfg.c:1.4
--- xsrc/external/mit/fontconfig/dist/src/fccfg.c:1.3	Tue Aug 29 08:38:50 2017
+++ xsrc/external/mit/fontconfig/dist/src/fccfg.c	Fri Mar  8 09:49:07 2019
@@ -27,7 +27,6 @@
 #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
@@ -53,6 +52,36 @@ retry:
     return config;
 }
 
+static FcChar32
+FcHashAsStrIgnoreCase (const void *data)
+{
+    return FcStrHashIgnoreCase (data);
+}
+
+static int
+FcCompareAsStr (const void *v1, const void *v2)
+{
+    return FcStrCmp (v1, v2);
+}
+
+static void
+FcDestroyAsRule (void *data)
+{
+    FcRuleDestroy (data);
+}
+
+static void
+FcDestroyAsRuleSet (void *data)
+{
+    FcRuleSetDestroy (data);
+}
+
+static void
+FcDestroyAsStr (void *data)
+{
+    FcStrFree (data);
+}
+
 FcBool
 FcConfigInit (void)
 {
@@ -73,6 +102,8 @@ FcConfigCreate (void)
 {
     FcSetName	set;
     FcConfig	*config;
+    FcMatchKind	k;
+    FcBool	err = FcFalse;
 
     config = malloc (sizeof (FcConfig));
     if (!config)
@@ -110,11 +141,15 @@ FcConfigCreate (void)
     if (!config->cacheDirs)
 	goto bail8;
 
-    config->blanks = &fcBlanks;
+    for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
+    {
+	config->subst[k] = FcPtrListCreate (FcDestroyAsRuleSet);
+	if (!config->subst[k])
+	    err = FcTrue;
+    }
+    if (err)
+	goto bail9;
 
-    config->substPattern = 0;
-    config->substFont = 0;
-    config->substScan = 0;
     config->maxObjects = 0;
     for (set = FcSetSystem; set <= FcSetApplication; set++)
 	config->fonts[set] = 0;
@@ -126,10 +161,31 @@ FcConfigCreate (void)
 
     config->sysRoot = NULL;
 
+    config->rulesetList = FcPtrListCreate (FcDestroyAsRuleSet);
+    if (!config->rulesetList)
+	goto bail9;
+    config->availConfigFiles = FcStrSetCreate ();
+    if (!config->availConfigFiles)
+	goto bail10;
+
+    config->uuid_table = FcHashTableCreate (FcHashAsStrIgnoreCase,
+					    FcCompareAsStr,
+					    FcHashStrCopy,
+					    FcHashUuidCopy,
+					    FcDestroyAsStr,
+					    FcHashUuidFree);
+
     FcRefInit (&config->ref, 1);
 
     return config;
 
+bail10:
+    FcPtrListDestroy (config->rulesetList);
+bail9:
+    for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
+	if (config->subst[k])
+	    FcPtrListDestroy (config->subst[k]);
+    FcStrSetDestroy (config->cacheDirs);
 bail8:
     FcFontSetDestroy (config->rejectPatterns);
 bail7:
@@ -207,21 +263,6 @@ FcConfigUptoDate (FcConfig *config)
     return FcTrue;
 }
 
-static void
-FcSubstDestroy (FcSubst *s)
-{
-    FcSubst *n;
-
-    while (s)
-    {
-	n = s->next;
-	if (s->rule)
-	    FcRuleDestroy (s->rule);
-	free (s);
-	s = n;
-    }
-}
-
 FcExpr *
 FcConfigAllocExpr (FcConfig *config)
 {
@@ -261,6 +302,7 @@ FcConfigDestroy (FcConfig *config)
 {
     FcSetName	set;
     FcExprPage	*page;
+    FcMatchKind	k;
 
     if (FcRefDec (&config->ref) != 1)
 	return;
@@ -276,12 +318,10 @@ FcConfigDestroy (FcConfig *config)
     FcFontSetDestroy (config->acceptPatterns);
     FcFontSetDestroy (config->rejectPatterns);
 
-    if (config->blanks)
-	FcBlanksDestroy (config->blanks);
-
-    FcSubstDestroy (config->substPattern);
-    FcSubstDestroy (config->substFont);
-    FcSubstDestroy (config->substScan);
+    for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
+	FcPtrListDestroy (config->subst[k]);
+    FcPtrListDestroy (config->rulesetList);
+    FcStrSetDestroy (config->availConfigFiles);
     for (set = FcSetSystem; set <= FcSetApplication; set++)
 	if (config->fonts[set])
 	    FcFontSetDestroy (config->fonts[set]);
@@ -296,6 +336,8 @@ FcConfigDestroy (FcConfig *config)
     if (config->sysRoot)
 	FcStrFree (config->sysRoot);
 
+    FcHashTableDestroy (config->uuid_table);
+
     free (config);
 }
 
@@ -305,11 +347,15 @@ FcConfigDestroy (FcConfig *config)
 
 FcBool
 FcConfigAddCache (FcConfig *config, FcCache *cache,
-		  FcSetName set, FcStrSet *dirSet)
+		  FcSetName set, FcStrSet *dirSet, FcChar8 *forDir)
 {
     FcFontSet	*fs;
     intptr_t	*dirs;
     int		i;
+    FcBool      relocated = FcFalse;
+
+    if (strcmp ((char *)FcCacheDir(cache), (char *)forDir) != 0)
+      relocated = FcTrue;
 
     /*
      * Add fonts
@@ -323,23 +369,43 @@ FcConfigAddCache (FcConfig *config, FcCa
 	{
 	    FcPattern	*font = FcFontSetFont (fs, i);
 	    FcChar8	*font_file;
+	    FcChar8	*relocated_font_file = NULL;
 
-	    /*
-	     * Check to see if font is banned by filename
-	     */
 	    if (FcPatternObjectGetString (font, FC_FILE_OBJECT,
-					  0, &font_file) == FcResultMatch &&
-		!FcConfigAcceptFilename (config, font_file))
+					  0, &font_file) == FcResultMatch)
 	    {
-		continue;
+		if (relocated)
+		  {
+		    FcChar8 *slash = FcStrLastSlash (font_file);
+		    relocated_font_file = FcStrBuildFilename (forDir, slash + 1, NULL);
+		    font_file = relocated_font_file;
+		  }
+
+		/*
+		 * Check to see if font is banned by filename
+		 */
+		if (!FcConfigAcceptFilename (config, font_file))
+		{
+		    free (relocated_font_file);
+		    continue;
+		}
 	    }
-		
+
 	    /*
 	     * Check to see if font is banned by pattern
 	     */
 	    if (!FcConfigAcceptFont (config, font))
+	    {
+		free (relocated_font_file);
 		continue;
-		
+	    }
+
+	    if (relocated_font_file)
+	    {
+	      font = FcPatternCacheRewriteFile (font, cache, relocated_font_file);
+	      free (relocated_font_file);
+	    }
+
 	    if (FcFontSetAdd (config->fonts[set], font))
 		nref++;
 	}
@@ -354,9 +420,19 @@ FcConfigAddCache (FcConfig *config, FcCa
     {
 	for (i = 0; i < cache->dirs_count; i++)
 	{
-	    FcChar8	*dir = FcOffsetToPtr (dirs, dirs[i], FcChar8);
+	    const FcChar8 *dir = FcCacheSubdir (cache, i);
+	    FcChar8 *s = NULL;
+
+	    if (relocated)
+	    {
+		FcChar8 *base = FcStrBasename (dir);
+		dir = s = FcStrBuildFilename (forDir, base, NULL);
+		FcStrFree (base);
+	    }
 	    if (FcConfigAcceptFilename (config, dir))
 		FcStrSetAddFilename (dirSet, dir);
+	    if (s)
+		FcStrFree (s);
 	}
     }
     return FcTrue;
@@ -380,7 +456,7 @@ FcConfigAddDirList (FcConfig *config, Fc
 	cache = FcDirCacheRead (dir, FcFalse, config);
 	if (!cache)
 	    continue;
-	FcConfigAddCache (config, cache, set, dirSet);
+	FcConfigAddCache (config, cache, set, dirSet, dir);
 	FcDirCacheUnload (cache);
     }
     FcStrListDone (dirlist);
@@ -474,14 +550,6 @@ FcConfigAddFontDir (FcConfig	    *config
     return FcStrSetAddFilename (config->fontDirs, d);
 }
 
-FcBool
-FcConfigAddDir (FcConfig	    *config,
-		const FcChar8	    *d)
-{
-    return (FcConfigAddConfigDir (config, d) &&
-	    FcConfigAddFontDir (config, d));
-}
-
 FcStrList *
 FcConfigGetFontDirs (FcConfig	*config)
 {
@@ -569,41 +637,50 @@ FcConfigSetFonts (FcConfig	*config,
     config->fonts[set] = fonts;
 }
 
+
 FcBlanks *
-FcConfigGetBlanks (FcConfig	*config)
+FcBlanksCreate (void)
 {
-    if (!config)
-    {
-	config = FcConfigGetCurrent ();
-	if (!config)
-	    return 0;
-    }
-    return config->blanks;
+    /* Deprecated. */
+    return NULL;
+}
+
+void
+FcBlanksDestroy (FcBlanks *b FC_UNUSED)
+{
+    /* Deprecated. */
 }
 
 FcBool
-FcConfigAddBlank (FcConfig	*config,
-		  FcChar32    	blank)
+FcBlanksAdd (FcBlanks *b FC_UNUSED, FcChar32 ucs4 FC_UNUSED)
 {
-    FcBlanks	*b, *freeme = 0;
+    /* Deprecated. */
+    return FcFalse;
+}
 
-    b = config->blanks;
-    if (!b)
-    {
-	freeme = b = FcBlanksCreate ();
-	if (!b)
-	    return FcFalse;
-    }
-    if (!FcBlanksAdd (b, blank))
-    {
-        if (freeme)
-            FcBlanksDestroy (freeme);
-	return FcFalse;
-    }
-    config->blanks = b;
-    return FcTrue;
+FcBool
+FcBlanksIsMember (FcBlanks *b FC_UNUSED, FcChar32 ucs4 FC_UNUSED)
+{
+    /* Deprecated. */
+    return FcFalse;
+}
+
+FcBlanks *
+FcConfigGetBlanks (FcConfig	*config FC_UNUSED)
+{
+    /* Deprecated. */
+    return NULL;
+}
+
+FcBool
+FcConfigAddBlank (FcConfig	*config FC_UNUSED,
+		  FcChar32    	blank FC_UNUSED)
+{
+    /* Deprecated. */
+    return FcFalse;
 }
 
+
 int
 FcConfigGetRescanInterval (FcConfig *config)
 {
@@ -649,61 +726,8 @@ FcConfigAddRule (FcConfig	*config,
 		 FcRule		*rule,
 		 FcMatchKind	kind)
 {
-    FcSubst	*subst, **prev;
-    FcRule	*r;
-    int		n = 0;
-
-    if (!rule)
-	return FcFalse;
-    switch (kind) {
-    case FcMatchPattern:
-	prev = &config->substPattern;
-	break;
-    case FcMatchFont:
-	prev = &config->substFont;
-	break;
-    case FcMatchScan:
-	prev = &config->substScan;
-	break;
-    default:
-	return FcFalse;
-    }
-    subst = (FcSubst *) malloc (sizeof (FcSubst));
-    if (!subst)
-	return FcFalse;
-    for (; *prev; prev = &(*prev)->next);
-    *prev = subst;
-    subst->next = NULL;
-    subst->rule = rule;
-    for (r = rule; r; r = r->next)
-    {
-	switch (r->type)
-	{
-	case FcRuleTest:
-	    if (r->u.test &&
-		r->u.test->kind == FcMatchDefault)
-		r->u.test->kind = kind;
-
-	    if (n < r->u.test->object)
-		n = r->u.test->object;
-	    break;
-	case FcRuleEdit:
-	    if (n < r->u.edit->object)
-		n = r->u.edit->object;
-	    break;
-	default:
-	    break;
-	}
-    }
-    n = FC_OBJ_ID (n) - FC_MAX_BASE_OBJECT;
-    if (config->maxObjects < n)
-	config->maxObjects = n;
-    if (FcDebug () & FC_DBG_EDIT)
-    {
-	printf ("Add Subst ");
-	FcSubstPrint (subst);
-    }
-    return FcTrue;
+    /* deprecated */
+    return FcFalse;
 }
 
 static FcValue
@@ -724,12 +748,12 @@ 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)
+    else if (buf && v.type == FcTypeVoid && u.type == FcTypeLangSet)
     {
 	v.u.l = FcLangSetPromote (NULL, buf);
 	v.type = FcTypeLangSet;
     }
-    else if (v.type == FcTypeVoid && u.type == FcTypeCharSet)
+    else if (buf && v.type == FcTypeVoid && u.type == FcTypeCharSet)
     {
 	v.u.c = FcCharSetPromote (buf);
 	v.type = FcTypeCharSet;
@@ -793,14 +817,30 @@ FcConfigCompareValue (const FcValue	*lef
 	case FcTypeBool:
 	    switch ((int) op) {
 	    case FcOpEqual:
+		ret = left.u.b == right.u.b;
+		break;
 	    case FcOpContains:
 	    case FcOpListing:
-		ret = left.u.b == right.u.b;
+		ret = left.u.b == right.u.b || left.u.b == FcDontCare;
 		break;
 	    case FcOpNotEqual:
-	    case FcOpNotContains:
 		ret = left.u.b != right.u.b;
 		break;
+	    case FcOpNotContains:
+		ret = !(left.u.b == right.u.b || left.u.b == FcDontCare);
+		break;
+	    case FcOpLess:
+		ret = left.u.b != right.u.b && right.u.b == FcDontCare;
+		break;
+	    case FcOpLessEqual:
+		ret = left.u.b == right.u.b || right.u.b == FcDontCare;
+		break;
+	    case FcOpMore:
+		ret = left.u.b != right.u.b && left.u.b == FcDontCare;
+		break;
+	    case FcOpMoreEqual:
+		ret = left.u.b == right.u.b || left.u.b == FcDontCare;
+		break;
 	    default:
 		break;
 	    }
@@ -1517,8 +1557,10 @@ FcConfigSubstituteWithPat (FcConfig    *
 			   FcMatchKind kind)
 {
     FcValue v;
-    FcSubst	    *s;
+    FcPtrList	    *s;
+    FcPtrListIter    iter, iter2;
     FcRule          *r;
+    FcRuleSet	    *rs;
     FcValueList	    *l, **value = NULL, *vl;
     FcPattern	    *m;
     FcStrSet	    *strs;
@@ -1535,9 +1577,11 @@ FcConfigSubstituteWithPat (FcConfig    *
 	    return FcFalse;
     }
 
-    switch (kind) {
-    case FcMatchPattern:
-	s = config->substPattern;
+    if (kind < FcMatchKindBegin || kind >= FcMatchKindEnd)
+	return FcFalse;
+    s = config->subst[kind];
+    if (kind == FcMatchPattern)
+    {
 	strs = FcGetDefaultLangs ();
 	if (strs)
 	{
@@ -1597,15 +1641,6 @@ FcConfigSubstituteWithPat (FcConfig    *
 	    if (prgname)
 		FcPatternObjectAddString (p, FC_PRGNAME_OBJECT, prgname);
 	}
-	break;
-    case FcMatchFont:
-	s = config->substFont;
-	break;
-    case FcMatchScan:
-	s = config->substScan;
-	break;
-    default:
-	return FcFalse;
     }
 
     nobjs = FC_MAX_BASE_OBJECT + config->maxObjects + 2;
@@ -1633,186 +1668,198 @@ FcConfigSubstituteWithPat (FcConfig    *
 	printf ("FcConfigSubstitute ");
 	FcPatternPrint (p);
     }
-    for (; s; s = s->next)
+    FcPtrListIterInit (s, &iter);
+    for (; FcPtrListIterIsValid (s, &iter); FcPtrListIterNext (s, &iter))
     {
-	r = s->rule;
-	for (i = 0; i < nobjs; i++)
+	rs = (FcRuleSet *) FcPtrListIterGetValue (s, &iter);
+	if (FcDebug () & FC_DBG_EDIT)
 	{
-	    elt[i] = NULL;
-	    value[i] = NULL;
-	    tst[i] = NULL;
+	    printf ("\nRule Set: %s\n", rs->name);
 	}
-	for (; r; r = r->next)
+	FcPtrListIterInit (rs->subst[kind], &iter2);
+	for (; FcPtrListIterIsValid (rs->subst[kind], &iter2); FcPtrListIterNext (rs->subst[kind], &iter2))
 	{
-	    switch (r->type) {
-	    case FcRuleUnknown:
-		/* shouldn't be reached */
-		break;
-	    case FcRuleTest:
-		object = FC_OBJ_ID (r->u.test->object);
-		/*
-		 * Check the tests to see if
-		 * they all match the pattern
-		 */
-		if (FcDebug () & FC_DBG_EDIT)
-		{
-		    printf ("FcConfigSubstitute test ");
-		    FcTestPrint (r->u.test);
-		}
-		if (kind == FcMatchFont && r->u.test->kind == FcMatchPattern)
-		    m = p_pat;
-		else
-		    m = p;
-		if (m)
-		    e = FcPatternObjectFindElt (m, r->u.test->object);
-		else
-		    e = NULL;
-		/* different 'kind' won't be the target of edit */
-		if (!elt[object] && kind == r->u.test->kind)
-		{
-		    elt[object] = e;
-		    tst[object] = r->u.test;
-		}
-		/*
-		 * If there's no such field in the font,
-		 * then FcQualAll matches while FcQualAny does not
-		 */
-		if (!e)
-		{
-		    if (r->u.test->qual == FcQualAll)
+	    r = (FcRule *) FcPtrListIterGetValue (rs->subst[kind], &iter2);
+	    for (i = 0; i < nobjs; i++)
+	    {
+		elt[i] = NULL;
+		value[i] = NULL;
+		tst[i] = NULL;
+	    }
+	    for (; r; r = r->next)
+	    {
+		switch (r->type) {
+		case FcRuleUnknown:
+		    /* shouldn't be reached */
+		    break;
+		case FcRuleTest:
+		    object = FC_OBJ_ID (r->u.test->object);
+		    /*
+		     * Check the tests to see if
+		     * they all match the pattern
+		     */
+		    if (FcDebug () & FC_DBG_EDIT)
 		    {
-			value[object] = NULL;
-			continue;
+			printf ("FcConfigSubstitute test ");
+			FcTestPrint (r->u.test);
 		    }
+		    if (kind == FcMatchFont && r->u.test->kind == FcMatchPattern)
+			m = p_pat;
 		    else
+			m = p;
+		    if (m)
+			e = FcPatternObjectFindElt (m, r->u.test->object);
+		    else
+			e = NULL;
+		    /* different 'kind' won't be the target of edit */
+		    if (!elt[object] && kind == r->u.test->kind)
+		    {
+			elt[object] = e;
+			tst[object] = r->u.test;
+		    }
+		    /*
+		     * If there's no such field in the font,
+		     * then FcQualAll matches while FcQualAny does not
+		     */
+		    if (!e)
+		    {
+			if (r->u.test->qual == FcQualAll)
+			{
+			    value[object] = NULL;
+			    continue;
+			}
+			else
+			{
+			    if (FcDebug () & FC_DBG_EDIT)
+				printf ("No match\n");
+			    goto bail;
+			}
+		    }
+		    /*
+		     * Check to see if there is a match, mark the location
+		     * to apply match-relative edits
+		     */
+		    vl = FcConfigMatchValueList (m, p_pat, kind, r->u.test, e->values);
+		    /* different 'kind' won't be the target of edit */
+		    if (!value[object] && kind == r->u.test->kind)
+			value[object] = vl;
+		    if (!vl ||
+			(r->u.test->qual == FcQualFirst && vl != e->values) ||
+			(r->u.test->qual == FcQualNotFirst && vl == e->values))
 		    {
 			if (FcDebug () & FC_DBG_EDIT)
 			    printf ("No match\n");
 			goto bail;
 		    }
-		}
-		/*
-		 * Check to see if there is a match, mark the location
-		 * to apply match-relative edits
-		 */
-		vl = FcConfigMatchValueList (m, p_pat, kind, r->u.test, e->values);
-		/* different 'kind' won't be the target of edit */
-		if (!value[object] && kind == r->u.test->kind)
-		    value[object] = vl;
-		if (!vl ||
-		    (r->u.test->qual == FcQualFirst && vl != e->values) ||
-		    (r->u.test->qual == FcQualNotFirst && vl == e->values))
-		{
+		    break;
+		case FcRuleEdit:
+		    object = FC_OBJ_ID (r->u.edit->object);
 		    if (FcDebug () & FC_DBG_EDIT)
-			printf ("No match\n");
-		    goto bail;
-		}
-		break;
-	    case FcRuleEdit:
-		object = FC_OBJ_ID (r->u.edit->object);
-		if (FcDebug () & FC_DBG_EDIT)
-		{
-		    printf ("Substitute ");
-		    FcEditPrint (r->u.edit);
-		    printf ("\n\n");
-		}
-		/*
-		 * Evaluate the list of expressions
-		 */
-		l = FcConfigValues (p, p_pat,kind,  r->u.edit->expr, r->u.edit->binding);
-		if (tst[object] && (tst[object]->kind == FcMatchFont || kind == FcMatchPattern))
-		    elt[object] = FcPatternObjectFindElt (p, tst[object]->object);
-
-		switch (FC_OP_GET_OP (r->u.edit->op)) {
-		case FcOpAssign:
+		    {
+			printf ("Substitute ");
+			FcEditPrint (r->u.edit);
+			printf ("\n\n");
+		    }
 		    /*
-		     * If there was a test, then replace the matched
-		     * value with the new list of values
+		     * Evaluate the list of expressions
 		     */
-		    if (value[object])
-		    {
-			FcValueList	*thisValue = value[object];
-			FcValueList	*nextValue = l;
+		    l = FcConfigValues (p, p_pat,kind,  r->u.edit->expr, r->u.edit->binding);
+		    if (tst[object] && (tst[object]->kind == FcMatchFont || kind == FcMatchPattern))
+			elt[object] = FcPatternObjectFindElt (p, tst[object]->object);
 
+		    switch (FC_OP_GET_OP (r->u.edit->op)) {
+		    case FcOpAssign:
 			/*
-			 * Append the new list of values after the current value
+			 * If there was a test, then replace the matched
+			 * value with the new list of values
 			 */
-			FcConfigAdd (&elt[object]->values, thisValue, FcTrue, l, r->u.edit->object);
+			if (value[object])
+			{
+			    FcValueList	*thisValue = value[object];
+			    FcValueList	*nextValue = l;
+
+			    /*
+			     * Append the new list of values after the current value
+			     */
+			    FcConfigAdd (&elt[object]->values, thisValue, FcTrue, l, r->u.edit->object);
+			    /*
+			     * Delete the marked value
+			     */
+			    if (thisValue)
+				FcConfigDel (&elt[object]->values, thisValue);
+			    /*
+			     * Adjust a pointer into the value list to ensure
+			     * future edits occur at the same place
+			     */
+			    value[object] = nextValue;
+			    break;
+			}
+			/* fall through ... */
+		    case FcOpAssignReplace:
 			/*
-			 * Delete the marked value
+			 * Delete all of the values and insert
+			 * the new set
 			 */
-			if (thisValue)
-			    FcConfigDel (&elt[object]->values, thisValue);
+			FcConfigPatternDel (p, r->u.edit->object);
+			FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
 			/*
-			 * Adjust a pointer into the value list to ensure
-			 * future edits occur at the same place
+			 * Adjust a pointer into the value list as they no
+			 * longer point to anything valid
 			 */
-			value[object] = nextValue;
+			value[object] = NULL;
 			break;
-		    }
-		    /* fall through ... */
-		case FcOpAssignReplace:
-		    /*
-		     * Delete all of the values and insert
-		     * the new set
-		     */
-		    FcConfigPatternDel (p, r->u.edit->object);
-		    FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
-		    /*
-		     * Adjust a pointer into the value list as they no
-		     * longer point to anything valid
-		     */
-		    value[object] = NULL;
-		    break;
-		case FcOpPrepend:
-		    if (value[object])
-		    {
-			FcConfigAdd (&elt[object]->values, value[object], FcFalse, l, r->u.edit->object);
+		    case FcOpPrepend:
+			if (value[object])
+			{
+			    FcConfigAdd (&elt[object]->values, value[object], FcFalse, l, r->u.edit->object);
+			    break;
+			}
+			/* fall through ... */
+		    case FcOpPrependFirst:
+			FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse);
 			break;
-		    }
-		    /* fall through ... */
-		case FcOpPrependFirst:
-		    FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse);
-		    break;
-		case FcOpAppend:
-		    if (value[object])
-		    {
-			FcConfigAdd (&elt[object]->values, value[object], FcTrue, l, r->u.edit->object);
+		    case FcOpAppend:
+			if (value[object])
+			{
+			    FcConfigAdd (&elt[object]->values, value[object], FcTrue, l, r->u.edit->object);
+			    break;
+			}
+			/* fall through ... */
+		    case FcOpAppendLast:
+			FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
+			break;
+		    case FcOpDelete:
+			if (value[object])
+			{
+			    FcConfigDel (&elt[object]->values, value[object]);
+			    FcValueListDestroy (l);
+			    break;
+			}
+			/* fall through ... */
+		    case FcOpDeleteAll:
+			FcConfigPatternDel (p, r->u.edit->object);
+			FcValueListDestroy (l);
+			break;
+		    default:
+			FcValueListDestroy (l);
 			break;
 		    }
-		    /* fall through ... */
-		case FcOpAppendLast:
-		    FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
-		    break;
-		case FcOpDelete:
-		    if (value[object])
+		    /*
+		     * Now go through the pattern and eliminate
+		     * any properties without data
+		     */
+		    FcConfigPatternCanon (p, r->u.edit->object);
+
+		    if (FcDebug () & FC_DBG_EDIT)
 		    {
-			FcConfigDel (&elt[object]->values, value[object]);
-			break;
+			printf ("FcConfigSubstitute edit");
+			FcPatternPrint (p);
 		    }
-		    /* fall through ... */
-		case FcOpDeleteAll:
-		    FcConfigPatternDel (p, r->u.edit->object);
-		    break;
-		default:
-		    FcValueListDestroy (l);
 		    break;
 		}
-		/*
-		 * Now go through the pattern and eliminate
-		 * any properties without data
-		 */
-		FcConfigPatternCanon (p, r->u.edit->object);
-
-		if (FcDebug () & FC_DBG_EDIT)
-		{
-		    printf ("FcConfigSubstitute edit");
-		    FcPatternPrint (p);
-		}
-		break;
 	    }
+	bail:;
 	}
-    bail:;
     }
     if (FcDebug () & FC_DBG_EDIT)
     {
@@ -2062,7 +2109,8 @@ FcConfigXdgCacheHome (void)
 	ret = malloc (len + 7 + 1);
 	if (ret)
 	{
-	    memcpy (ret, home, len);
+	    if (home)
+		memcpy (ret, home, len);
 	    memcpy (&ret[len], FC_DIR_SEPARATOR_S ".cache", 7);
 	    ret[len + 7] = 0;
 	}
@@ -2089,7 +2137,8 @@ FcConfigXdgConfigHome (void)
 	ret = malloc (len + 8 + 1);
 	if (ret)
 	{
-	    memcpy (ret, home, len);
+	    if (home)
+		memcpy (ret, home, len);
 	    memcpy (&ret[len], FC_DIR_SEPARATOR_S ".config", 8);
 	    ret[len + 8] = 0;
 	}
@@ -2116,7 +2165,8 @@ FcConfigXdgDataHome (void)
 	ret = malloc (len + 13 + 1);
 	if (ret)
 	{
-	    memcpy (ret, home, len);
+	    if (home)
+		memcpy (ret, home, len);
 	    memcpy (&ret[len], FC_DIR_SEPARATOR_S ".local" FC_DIR_SEPARATOR_S "share", 13);
 	    ret[len + 13] = 0;
 	}
@@ -2146,43 +2196,78 @@ FcConfigFilename (const FcChar8 *url)
     }
     file = 0;
 
-#ifdef _WIN32
-    if (isalpha (*url) &&
-	url[1] == ':' &&
-	(url[2] == '/' || url[2] == '\\'))
-	goto absolute_path;
-#endif
+    if (FcStrIsAbsoluteFilename(url))
+	return FcConfigFileExists (0, url);
 
-    switch (*url) {
-    case '~':
+    if (*url == '~')
+    {
 	dir = FcConfigHome ();
 	if (dir)
 	    file = FcConfigFileExists (dir, url + 1);
 	else
 	    file = 0;
-	break;
-#ifdef _WIN32
-    case '\\':
-    absolute_path:
-#endif
-    case '/':
-	file = FcConfigFileExists (0, url);
-	break;
-    default:
-	path = FcConfigGetPath ();
-	if (!path)
-	    return NULL;
-	for (p = path; *p; p++)
+    }
+
+    path = FcConfigGetPath ();
+    if (!path)
+	return NULL;
+    for (p = path; *p; p++)
+    {
+	file = FcConfigFileExists (*p, url);
+	if (file)
+	    break;
+    }
+    FcConfigFreePath (path);
+    return file;
+}
+
+FcChar8 *
+FcConfigRealFilename (FcConfig		*config,
+		      const FcChar8	*url)
+{
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+    FcChar8 *n = FcConfigFilename (url);
+    FcChar8 *nn = NULL;
+
+    if (n)
+    {
+	FcChar8 buf[PATH_MAX];
+	ssize_t len;
+
+	if (sysroot)
+	    nn = FcStrBuildFilename (sysroot, n, NULL);
+	else
+	    nn = FcStrdup (n);
+	FcStrFree (n);
+
+	if ((len = FcReadLink (nn, buf, sizeof (buf) - 1)) != -1)
 	{
-	    file = FcConfigFileExists (*p, url);
-	    if (file)
-		break;
+	    buf[len] = 0;
+
+	    if (!FcStrIsAbsoluteFilename (buf))
+	    {
+		FcChar8 *dirname = FcStrDirname (nn);
+		FcStrFree (nn);
+		if (!dirname)
+		    return NULL;
+
+		FcChar8 *path = FcStrBuildFilename (dirname, buf, NULL);
+		FcStrFree (dirname);
+		if (!path)
+		    return NULL;
+
+		nn = FcStrCanonFilename (path);
+		FcStrFree (path);
+	    }
+	    else
+	    {
+		FcStrFree (nn);
+		nn = FcStrdup (buf);
+	    }
 	}
-	FcConfigFreePath (path);
-	break;
     }
 
-    return file;
+    return nn;
 }
 
 /*
@@ -2221,7 +2306,7 @@ FcConfigAppFontAddFile (FcConfig    *con
 	FcConfigSetFonts (config, set, FcSetApplication);
     }
 	
-    if (!FcFileScanConfig (set, subdirs, config->blanks, file, config))
+    if (!FcFileScanConfig (set, subdirs, file, config))
     {
 	FcStrSetDestroy (subdirs);
 	return FcFalse;
@@ -2376,7 +2461,10 @@ FcConfigGetSysRoot (const FcConfig *conf
 	    return NULL;
     }
 
-    return config->sysRoot;
+    if (config->sysRoot)
+        return config->sysRoot;
+
+    return (FcChar8 *) getenv ("FONTCONFIG_SYSROOT");
 }
 
 void
@@ -2425,6 +2513,200 @@ FcConfigSetSysRoot (FcConfig      *confi
     }
 }
 
+FcRuleSet *
+FcRuleSetCreate (const FcChar8 *name)
+{
+    FcRuleSet *ret = (FcRuleSet *) malloc (sizeof (FcRuleSet));
+    FcMatchKind k;
+    const FcChar8 *p;
+
+    if (!name)
+	p = (const FcChar8 *)"";
+    else
+	p = name;
+
+    if (ret)
+    {
+	ret->name = FcStrdup (p);
+	ret->description = NULL;
+	ret->domain = NULL;
+	for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
+	    ret->subst[k] = FcPtrListCreate (FcDestroyAsRule);
+	FcRefInit (&ret->ref, 1);
+    }
+
+    return ret;
+}
+
+void
+FcRuleSetDestroy (FcRuleSet *rs)
+{
+    FcMatchKind k;
+
+    if (!rs)
+	return;
+    if (FcRefDec (&rs->ref) != 1)
+	return;
+
+    if (rs->name)
+	FcStrFree (rs->name);
+    if (rs->description)
+	FcStrFree (rs->description);
+    if (rs->domain)
+	FcStrFree (rs->domain);
+    for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
+	FcPtrListDestroy (rs->subst[k]);
+
+    free (rs);
+}
+
+void
+FcRuleSetReference (FcRuleSet *rs)
+{
+    if (!FcRefIsConst (&rs->ref))
+	FcRefInc (&rs->ref);
+}
+
+void
+FcRuleSetEnable (FcRuleSet	*rs,
+		 FcBool		flag)
+{
+    if (rs)
+    {
+	rs->enabled = flag;
+	/* XXX: we may want to provide a feature
+	 * to enable/disable rulesets through API
+	 * in the future?
+	 */
+    }
+}
+
+void
+FcRuleSetAddDescription (FcRuleSet	*rs,
+			 const FcChar8	*domain,
+			 const FcChar8	*description)
+{
+    if (rs->domain)
+	FcStrFree (rs->domain);
+    if (rs->description)
+	FcStrFree (rs->description);
+
+    rs->domain = domain ? FcStrdup (domain) : NULL;
+    rs->description = description ? FcStrdup (description) : NULL;
+}
+
+int
+FcRuleSetAdd (FcRuleSet		*rs,
+	      FcRule		*rule,
+	      FcMatchKind	kind)
+{
+    FcPtrListIter iter;
+    FcRule *r;
+    int n = 0, ret;
+
+    if (!rs ||
+       kind < FcMatchKindBegin || kind >= FcMatchKindEnd)
+	return -1;
+    FcPtrListIterInitAtLast (rs->subst[kind], &iter);
+    if (!FcPtrListIterAdd (rs->subst[kind], &iter, rule))
+	return -1;
+
+    for (r = rule; r; r = r->next)
+    {
+	switch (r->type)
+	{
+	case FcRuleTest:
+	    if (r->u.test)
+	    {
+		if (r->u.test->kind == FcMatchDefault)
+		    r->u.test->kind = kind;
+		if (n < r->u.test->object)
+		    n = r->u.test->object;
+	    }
+	    break;
+	case FcRuleEdit:
+	    if (n < r->u.edit->object)
+		n = r->u.edit->object;
+	    break;
+	default:
+	    break;
+	}
+    }
+    if (FcDebug () & FC_DBG_EDIT)
+    {
+	printf ("Add Rule(kind:%d, name: %s) ", kind, rs->name);
+	FcRulePrint (rule);
+    }
+    ret = FC_OBJ_ID (n) - FC_MAX_BASE_OBJECT;
+
+    return ret < 0 ? 0 : ret;
+}
+
+void
+FcConfigFileInfoIterInit (FcConfig		*config,
+			  FcConfigFileInfoIter	*iter)
+{
+    FcConfig *c;
+    FcPtrListIter *i = (FcPtrListIter *)iter;
+
+    if (!config)
+	c = FcConfigGetCurrent ();
+    else
+	c = config;
+    FcPtrListIterInit (c->rulesetList, i);
+}
+
+FcBool
+FcConfigFileInfoIterNext (FcConfig		*config,
+			  FcConfigFileInfoIter	*iter)
+{
+    FcConfig *c;
+    FcPtrListIter *i = (FcPtrListIter *)iter;
+
+    if (!config)
+	c = FcConfigGetCurrent ();
+    else
+	c = config;
+    if (FcPtrListIterIsValid (c->rulesetList, i))
+    {
+	FcPtrListIterNext (c->rulesetList, i);
+    }
+    else
+	return FcFalse;
+
+    return FcTrue;
+}
+
+FcBool
+FcConfigFileInfoIterGet (FcConfig		*config,
+			 FcConfigFileInfoIter	*iter,
+			 FcChar8		**name,
+			 FcChar8		**description,
+			 FcBool			*enabled)
+{
+    FcConfig *c;
+    FcRuleSet *r;
+    FcPtrListIter *i = (FcPtrListIter *)iter;
+
+    if (!config)
+	c = FcConfigGetCurrent ();
+    else
+	c = config;
+    if (!FcPtrListIterIsValid (c->rulesetList, i))
+	return FcFalse;
+    r = FcPtrListIterGetValue (c->rulesetList, i);
+    if (name)
+	*name = FcStrdup (r->name && r->name[0] ? r->name : (const FcChar8 *) "fonts.conf");
+    if (description)
+	*description = FcStrdup (!r->description ? _("No description") :
+				 dgettext (r->domain ? (const char *) r->domain : GETTEXT_PACKAGE "-conf",
+					   (const char *) r->description));
+    if (enabled)
+	*enabled = r->enabled;
+
+    return FcTrue;
+}
+
 #define __fccfg__
 #include "fcaliastail.h"
 #undef __fccfg__
Index: xsrc/external/mit/fontconfig/dist/src/fcinit.c
diff -u xsrc/external/mit/fontconfig/dist/src/fcinit.c:1.3 xsrc/external/mit/fontconfig/dist/src/fcinit.c:1.4
--- xsrc/external/mit/fontconfig/dist/src/fcinit.c:1.3	Tue Aug 29 08:38:50 2017
+++ xsrc/external/mit/fontconfig/dist/src/fcinit.c	Fri Mar  8 09:49:07 2019
@@ -39,15 +39,23 @@ static FcConfig *
 FcInitFallbackConfig (const FcChar8 *sysroot)
 {
     FcConfig	*config;
+    const FcChar8 *fallback = (const FcChar8 *) ""	\
+	"<fontconfig>" \
+	"  <dir>" FC_DEFAULT_FONTS "</dir>" \
+	"  <dir prefix=\"xdg\">fonts</dir>" \
+	"  <cachedir>" FC_CACHEDIR "</cachedir>" \
+	"  <cachedir prefix=\"xdg\">fontconfig</cachedir>" \
+	"  <include ignore_missing=\"yes\" prefix=\"xdg\">fontconfig/conf.d</include>" \
+	"  <include ignore_missing=\"yes\" prefix=\"xdg\">fontconfig/fonts.conf</include>" \
+	"</fontconfig>";
 
     config = FcConfigCreate ();
     if (!config)
 	goto bail0;
     FcConfigSetSysRoot (config, sysroot);
-    if (!FcConfigAddDir (config, (FcChar8 *) FC_DEFAULT_FONTS))
-	goto bail1;
-    if (!FcConfigAddCacheDir (config, (FcChar8 *) FC_CACHEDIR))
+    if (!FcConfigParseAndLoadFromMemory (config, fallback, FcFalse))
 	goto bail1;
+
     return config;
 
 bail1:
@@ -86,6 +94,7 @@ FcInitLoadOwnConfig (FcConfig *config)
 
 	return fallback;
     }
+    (void) FcConfigParseOnly (config, (const FcChar8 *)FC_TEMPLATEDIR, FcFalse);
 
     if (config->cacheDirs && config->cacheDirs->num == 0)
     {

Index: xsrc/external/mit/fontconfig/dist/src/fcformat.c
diff -u xsrc/external/mit/fontconfig/dist/src/fcformat.c:1.2 xsrc/external/mit/fontconfig/dist/src/fcformat.c:1.3
--- xsrc/external/mit/fontconfig/dist/src/fcformat.c:1.2	Tue Dec 10 23:08:36 2013
+++ xsrc/external/mit/fontconfig/dist/src/fcformat.c	Fri Mar  8 09:49:07 2019
@@ -544,7 +544,7 @@ interpret_count (FcFormatContext *c,
 		 FcStrBuf        *buf)
 {
     int count;
-    FcPatternElt *e;
+    FcPatternIter iter;
     FcChar8 buf_static[64];
 
     if (!expect_char (c, '#'))
@@ -554,16 +554,9 @@ interpret_count (FcFormatContext *c,
 	return FcFalse;
 
     count = 0;
-    e = FcPatternObjectFindElt (pat,
-				FcObjectFromName ((const char *) c->word));
-    if (e)
-    {
-	FcValueListPtr l;
-	count++;
-	for (l = FcPatternEltValues(e);
-	     l->next;
-	     l = l->next)
-	    count++;
+    if (FcPatternFindIter (pat, &iter, (const char *) c->word))
+    {
+	count = FcPatternIterValueCount (pat, &iter);
     }
 
     snprintf ((char *) buf_static, sizeof (buf_static), "%d", count);
@@ -695,7 +688,7 @@ interpret_simple (FcFormatContext *c,
 		  FcPattern       *pat,
 		  FcStrBuf        *buf)
 {
-    FcPatternElt *e;
+    FcPatternIter iter;
     FcBool        add_colon = FcFalse;
     FcBool        add_elt_name = FcFalse;
     int           idx;
@@ -743,9 +736,7 @@ interpret_simple (FcFormatContext *c,
 	c->word = orig;
     }
 
-    e = FcPatternObjectFindElt (pat,
-				FcObjectFromName ((const char *) c->word));
-    if (e || else_string)
+    if (FcPatternFindIter (pat, &iter, (const char *) c->word) || else_string)
     {
 	FcValueListPtr l = NULL;
 
@@ -757,8 +748,7 @@ interpret_simple (FcFormatContext *c,
 	    FcStrBufChar (buf, '=');
 	}
 
-	if (e)
-	    l = FcPatternEltValues(e);
+	l = FcPatternIterGetValues (pat, &iter);
 
 	if (idx != -1)
 	{
Index: xsrc/external/mit/fontconfig/dist/src/fcfreetype.c
diff -u xsrc/external/mit/fontconfig/dist/src/fcfreetype.c:1.2 xsrc/external/mit/fontconfig/dist/src/fcfreetype.c:1.3
--- xsrc/external/mit/fontconfig/dist/src/fcfreetype.c:1.2	Wed Aug 30 20:09:45 2017
+++ xsrc/external/mit/fontconfig/dist/src/fcfreetype.c	Fri Mar  8 09:49:07 2019
@@ -51,6 +51,7 @@
 #include <string.h>
 #include <ft2build.h>
 #include FT_FREETYPE_H
+#include FT_ADVANCES_H
 #include FT_TRUETYPE_TABLES_H
 #include FT_SFNT_NAMES_H
 #include FT_TRUETYPE_IDS_H
@@ -66,16 +67,6 @@
 
 #include "ftglue.h"
 
-#if HAVE_WARNING_CPP_DIRECTIVE
-#if !HAVE_FT_GET_BDF_PROPERTY
-#warning "No FT_Get_BDF_Property: Please install freetype 2.1.4 or later"
-#endif
-
-#if !HAVE_FT_GET_PS_FONT_INFO
-#warning "No FT_Get_PS_Font_Info: Please install freetype 2.1.1 or later"
-#endif
-#endif
-
 /*
  * Keep Han languages separated by eliminating languages
  * that the codePageRange bits says aren't supported
@@ -385,12 +376,7 @@ static const FcFtLanguage   fcFtLanguage
  {  TT_PLATFORM_MICROSOFT,	TT_MS_LANGID_LATVIAN_LATVIA,		"lv" },
  {  TT_PLATFORM_MICROSOFT,	TT_MS_LANGID_LITHUANIAN_LITHUANIA,	"lt" },
  {  TT_PLATFORM_MICROSOFT,	TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA,"lt" },
-
-#ifdef TT_MS_LANGID_MAORI_NEW_ZELAND
-    /* this seems to be an error that have been dropped */
  {  TT_PLATFORM_MICROSOFT,	TT_MS_LANGID_MAORI_NEW_ZEALAND,		"mi" },
-#endif
-
  {  TT_PLATFORM_MICROSOFT,	TT_MS_LANGID_FARSI_IRAN,		"fa" },
  {  TT_PLATFORM_MICROSOFT,	TT_MS_LANGID_VIETNAMESE_VIET_NAM,	"vi" },
  {  TT_PLATFORM_MICROSOFT,	TT_MS_LANGID_ARMENIAN_ARMENIA,		"hy" },
@@ -557,6 +543,9 @@ static const FcMacRomanFake fcMacRomanFa
 static FcChar8 *
 FcFontCapabilities(FT_Face face);
 
+static int
+FcFreeTypeSpacing (FT_Face face);
+
 #define NUM_FC_MAC_ROMAN_FAKE	(int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
 
 
@@ -1108,11 +1097,7 @@ FcGetPixelSize (FT_Face face, int i)
 	    return (double) prop.u.integer;
     }
 #endif
-#if HAVE_FT_BITMAP_SIZE_Y_PPEM
     return (double) face->available_sizes[i].y_ppem / 64.0;
-#else
-    return (double) face->available_sizes[i].height;
-#endif
 }
 
 static FcBool
@@ -1132,20 +1117,17 @@ static const FT_UShort platform_order[] 
     TT_PLATFORM_MICROSOFT,
     TT_PLATFORM_APPLE_UNICODE,
     TT_PLATFORM_MACINTOSH,
+    TT_PLATFORM_ISO,
 };
 #define NUM_PLATFORM_ORDER (sizeof (platform_order) / sizeof (platform_order[0]))
 
 static const FT_UShort nameid_order[] = {
-#ifdef TT_NAME_ID_WWS_FAMILY
     TT_NAME_ID_WWS_FAMILY,
-#endif
     TT_NAME_ID_PREFERRED_FAMILY,
     TT_NAME_ID_FONT_FAMILY,
     TT_NAME_ID_MAC_FULL_NAME,
     TT_NAME_ID_FULL_NAME,
-#ifdef TT_NAME_ID_WWS_SUBFAMILY
     TT_NAME_ID_WWS_SUBFAMILY,
-#endif
     TT_NAME_ID_PREFERRED_SUBFAMILY,
     TT_NAME_ID_FONT_SUBFAMILY,
     TT_NAME_ID_TRADEMARK,
@@ -1153,20 +1135,88 @@ static const FT_UShort nameid_order[] = 
 };
 
 #define NUM_NAMEID_ORDER  (sizeof (nameid_order) / sizeof (nameid_order[0]))
-FcPattern *
-FcFreeTypeQueryFace (const FT_Face  face,
-		     const FcChar8  *file,
-		     int	    id,
-		     FcBlanks	    *blanks)
+
+typedef struct
+{
+  unsigned int platform_id;
+  unsigned int name_id;
+  unsigned int encoding_id;
+  unsigned int language_id;
+  unsigned int idx;
+} FcNameMapping;
+
+static int
+name_mapping_cmp (const void *pa, const void *pb)
+{
+  const FcNameMapping *a = (const FcNameMapping *) pa;
+  const FcNameMapping *b = (const FcNameMapping *) pb;
+
+  if (a->platform_id != b->platform_id) return (int) a->platform_id - (int) b->platform_id;
+  if (a->name_id != b->name_id) return (int) a->name_id - (int) b->name_id;
+  if (a->encoding_id != b->encoding_id) return (int) a->encoding_id - (int) b->encoding_id;
+  if (a->language_id != b->language_id) return (int) a->language_id - (int) b->language_id;
+  if (a->idx != b->idx) return (int) a->idx - (int) b->idx;
+
+  return 0;
+}
+
+static int
+FcFreeTypeGetFirstName (const FT_Face face,
+			unsigned int  platform,
+			unsigned int  nameid,
+			FcNameMapping *mapping,
+			unsigned int   count,
+			FT_SfntName   *sname)
+{
+    int min = 0, max = (int) count - 1;
+
+    while (min <= max)
+    {
+	int mid = (min + max) / 2;
+
+	if (FT_Get_Sfnt_Name (face, mapping[mid].idx, sname) != 0)
+	    return FcFalse;
+
+	if (platform < sname->platform_id ||
+	    (platform == sname->platform_id &&
+	     (nameid < sname->name_id ||
+	      (nameid == sname->name_id &&
+	       (mid &&
+		platform == mapping[mid - 1].platform_id &&
+		nameid == mapping[mid - 1].name_id
+	       )))))
+	    max = mid - 1;
+	else if (platform > sname->platform_id ||
+		 (platform == sname->platform_id &&
+		  nameid > sname->name_id))
+	    min = mid + 1;
+	else
+	    return mid;
+    }
+
+    return -1;
+}
+
+static FcPattern *
+FcFreeTypeQueryFaceInternal (const FT_Face  face,
+			     const FcChar8  *file,
+			     unsigned int   id,
+			     FcCharSet      **cs_share,
+			     FcLangSet      **ls_share,
+			     FcNameMapping  **nm_share)
 {
     FcPattern	    *pat;
     int		    slant = -1;
-    int		    weight = -1;
-    int		    width = -1;
+    double	    weight = -1;
+    double	    width = -1;
     FcBool	    decorative = FcFalse;
-    int		    i;
-    FcCharSet	    *cs;
-    FcLangSet	    *ls;
+    FcBool	    variable = FcFalse;
+    FcBool	    variable_weight = FcFalse;
+    FcBool	    variable_width = FcFalse;
+    FcBool	    variable_size = FcFalse;
+    FcCharSet       *cs;
+    FcLangSet       *ls;
+    FcNameMapping   *name_mapping = NULL;
 #if 0
     FcChar8	    *family = 0;
 #endif
@@ -1189,9 +1239,8 @@ FcFreeTypeQueryFace (const FT_Face  face
 #endif
     TT_Header	    *head;
     const FcChar8   *exclusiveLang = 0;
-    FT_SfntName	    sname;
-    FT_UInt    	    snamei, snamec;
 
+    int		    name_count = 0;
     int		    nfamily = 0;
     int		    nfamily_lang = 0;
     int		    nstyle = 0;
@@ -1199,14 +1248,9 @@ FcFreeTypeQueryFace (const FT_Face  face
     int		    nfullname = 0;
     int		    nfullname_lang = 0;
     unsigned int    p, n;
-    int		    platform, nameid;
 
     FcChar8	    *style = 0;
     int		    st;
-    char	    psname[256];
-    const char	    *tmp;
-
-    FcRange	    *r = NULL;
 
     FcBool	    symbol = FcFalse;
 
@@ -1220,17 +1264,12 @@ FcFreeTypeQueryFace (const FT_Face  face
 	int has_outline = !!(face->face_flags & FT_FACE_FLAG_SCALABLE);
 	int has_color = 0;
 
-#ifdef FT_FACE_FLAG_COLOR
-	has_color = !!(face->face_flags & FT_FACE_FLAG_COLOR);
-#endif
-
 	if (!FcPatternAddBool (pat, FC_OUTLINE, has_outline))
 	    goto bail1;
 
-#ifdef FT_FACE_FLAG_COLOR
+	has_color = FT_HAS_COLOR (face);
 	if (!FcPatternAddBool (pat, FC_COLOR, has_color))
 	    goto bail1;
-#endif
 
 	/* All color fonts are designed to be scaled, even if they only have
 	 * bitmap strikes.  Client is responsible to scale the bitmaps.  This
@@ -1241,40 +1280,106 @@ FcFreeTypeQueryFace (const FT_Face  face
 
     if (id >> 16)
     {
-      if (!FT_Get_MM_Var (face, &master))
-	instance = &master->namedstyle[(id >> 16) - 1];
+      if (FT_Get_MM_Var (face, &master))
+	  goto bail1;
 
-      if (instance)
+      if (id >> 16 == 0x8000)
       {
-	  /* Pull out weight and width from named-instance. */
+	  /* Query variable font itself. */
 	  unsigned int i;
 
 	  for (i = 0; i < master->num_axis; i++)
 	  {
-	    double value = instance->coords[i] / (double) (1 << 16);
-	    double default_value = master->axis[i].def / (double) (1 << 16);
-	    double mult = value / default_value;
-	    //printf ("named-instance, axis %d tag %lx value %g\n", i, master->axis[i].tag, value);
-	    switch (master->axis[i].tag)
-	    {
-	      case FT_MAKE_TAG ('w','g','h','t'):
-	        weight_mult = mult;
-		break;
+	      double min_value = master->axis[i].minimum / (double) (1U << 16);
+	      double def_value = master->axis[i].def / (double) (1U << 16);
+	      double max_value = master->axis[i].maximum / (double) (1U << 16);
+	      const char *elt = NULL;
+
+	      if (min_value > def_value || def_value > max_value || min_value == max_value)
+		  continue;
+
+	      switch (master->axis[i].tag)
+	      {
+		case FT_MAKE_TAG ('w','g','h','t'):
+		  elt = FC_WEIGHT;
+		  min_value = FcWeightFromOpenTypeDouble (min_value);
+		  max_value = FcWeightFromOpenTypeDouble (max_value);
+		  variable_weight = FcTrue;
+		  weight = 0; /* To stop looking for weight. */
+		  break;
+
+		case FT_MAKE_TAG ('w','d','t','h'):
+		  elt = FC_WIDTH;
+		  /* Values in 'wdth' match Fontconfig FC_WIDTH_* scheme directly. */
+		  variable_width = FcTrue;
+		  width = 0; /* To stop looking for width. */
+		  break;
+
+		case FT_MAKE_TAG ('o','p','s','z'):
+		  elt = FC_SIZE;
+		  /* Values in 'opsz' match Fontconfig FC_SIZE, both are in points. */
+		  variable_size = FcTrue;
+		  break;
+	      }
+
+	      if (elt)
+	      {
+		  FcRange *r = FcRangeCreateDouble (min_value, max_value);
+		  if (!FcPatternAddRange (pat, elt, r))
+		  {
+		      FcRangeDestroy (r);
+		      goto bail1;
+		  }
+		  FcRangeDestroy (r);
+		  variable = FcTrue;
+	      }
+	  }
 
-	      case FT_MAKE_TAG ('w','d','t','h'):
-		width_mult = mult;
-		break;
+	  if (!variable)
+	      goto bail1;
+
+	  id &= 0xFFFF;
+      }
+      else if ((id >> 16) - 1 < master->num_namedstyles)
+      {
+	  /* Pull out weight and width from named-instance. */
+	  unsigned int i;
+
+	  instance = &master->namedstyle[(id >> 16) - 1];
 
-	      /* TODO optical size! */
+	  for (i = 0; i < master->num_axis; i++)
+	  {
+	      double value = instance->coords[i] / (double) (1U << 16);
+	      double default_value = master->axis[i].def / (double) (1U << 16);
+	      double mult = default_value ? value / default_value : 1;
+	      //printf ("named-instance, axis %d tag %lx value %g\n", i, master->axis[i].tag, value);
+	      switch (master->axis[i].tag)
+	      {
+		case FT_MAKE_TAG ('w','g','h','t'):
+		  weight_mult = mult;
+		  break;
+
+		case FT_MAKE_TAG ('w','d','t','h'):
+		  width_mult = mult;
+		  break;
+
+		case FT_MAKE_TAG ('o','p','s','z'):
+		  if (!FcPatternAddDouble (pat, FC_SIZE, value))
+		      goto bail1;
+		  break;
 	    }
 	  }
 	}
+        else
+	    goto bail1;
     }
+    if (!FcPatternAddBool (pat, FC_VARIABLE, variable))
+	goto bail1;
 
     /*
      * Get the OS/2 table
      */
-    os2 = (TT_OS2 *) FT_Get_Sfnt_Table (face, ft_sfnt_os2);
+    os2 = (TT_OS2 *) FT_Get_Sfnt_Table (face, FT_SFNT_OS2);
 
     /*
      * Look first in the OS/2 table for the foundry, if
@@ -1302,13 +1407,44 @@ FcFreeTypeQueryFace (const FT_Face  face
      * and style names.  FreeType makes quite a hash
      * of them
      */
-    snamec = FT_Get_Sfnt_Name_Count (face);
-    for (p = 0; p <= NUM_PLATFORM_ORDER; p++)
+    name_count = FT_Get_Sfnt_Name_Count (face);
+    if (nm_share)
+	name_mapping = *nm_share;
+    if (!name_mapping)
+    {
+	int i = 0;
+	name_mapping = malloc (name_count * sizeof (FcNameMapping));
+	if (!name_mapping)
+	    name_count = 0;
+	for (i = 0; i < name_count; i++)
+	{
+	    FcNameMapping *p = &name_mapping[i];
+	    FT_SfntName sname;
+	    if (FT_Get_Sfnt_Name (face, i, &sname) == 0)
+	    {
+		p->platform_id = sname.platform_id;
+		p->name_id  = sname.name_id;
+		p->encoding_id = sname.encoding_id;
+		p->language_id = sname.language_id;
+		p->idx = i;
+	    }
+	    else
+	    {
+		p->platform_id =
+		p->name_id  =
+		p->encoding_id =
+		p->language_id =
+		p->idx = (unsigned int) -1;
+	    }
+	}
+	qsort (name_mapping, name_count, sizeof(FcNameMapping), name_mapping_cmp);
+
+	if (nm_share)
+	    *nm_share = name_mapping;
+    }
+    for (p = 0; p < NUM_PLATFORM_ORDER; p++)
     {
-	if (p < NUM_PLATFORM_ORDER)
-	    platform = platform_order[p];
-	else
-	    platform = 0xffff;
+	int platform = platform_order[p];
 
 	/*
 	 * Order nameids so preferred names appear first
@@ -1316,73 +1452,47 @@ FcFreeTypeQueryFace (const FT_Face  face
 	 */
 	for (n = 0; n < NUM_NAMEID_ORDER; n++)
 	{
-	    nameid = nameid_order[n];
+	    FT_SfntName sname;
+	    int nameidx;
+	    const FcChar8	*lang;
+	    const char	*elt = 0, *eltlang = 0;
+	    int		*np = 0, *nlangp = 0;
+	    size_t		len;
+	    int nameid, lookupid;
 
-	    for (snamei = 0; snamei < snamec; snamei++)
-	    {
-		FcChar8		*utf8, *pp;
-		const FcChar8	*lang;
-		const char	*elt = 0, *eltlang = 0;
-		int		*np = 0, *nlangp = 0;
-		size_t		len;
+	    nameid = lookupid = nameid_order[n];
 
-		if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0)
-		    continue;
-
-		if (instance)
-		{
-		    /* For named-instances, we regular style nameIDs,
-		     * and map the instance's strid to FONT_SUBFAMILY. */
-		    if (sname.name_id == TT_NAME_ID_WWS_SUBFAMILY ||
-			sname.name_id == TT_NAME_ID_PREFERRED_SUBFAMILY ||
-			sname.name_id == TT_NAME_ID_FONT_SUBFAMILY)
-			continue;
-		    if (sname.name_id == instance->strid)
-			sname.name_id = TT_NAME_ID_FONT_SUBFAMILY;
-		}
-
-		if (sname.name_id != nameid)
+	    if (instance)
+	    {
+		/* For named-instances, we skip regular style nameIDs,
+		 * and treat the instance's nameid as FONT_SUBFAMILY.
+		 * Postscript name is automatically handled by FreeType. */
+		if (nameid == TT_NAME_ID_WWS_SUBFAMILY ||
+		    nameid == TT_NAME_ID_PREFERRED_SUBFAMILY)
 		    continue;
 
-		/*
-		 * Sort platforms in preference order, accepting
-		 * all other platforms last
-		 */
-		if (p < NUM_PLATFORM_ORDER)
-		{
-		    if (sname.platform_id != platform)
-			continue;
-		}
-		else
-		{
-		    unsigned int	sp;
-
-		    for (sp = 0; sp < NUM_PLATFORM_ORDER; sp++)
-			if (sname.platform_id == platform_order[sp])
-			    break;
-		    if (sp != NUM_PLATFORM_ORDER)
-			continue;
-		}
-		utf8 = FcSfntNameTranscode (&sname);
-		lang = FcSfntNameLanguage (&sname);
-
-		if (!utf8)
-		    continue;
+		if (nameid == TT_NAME_ID_FONT_SUBFAMILY)
+		    lookupid = instance->strid;
+	    }
 
-		switch (sname.name_id) {
-#ifdef TT_NAME_ID_WWS_FAMILY
+	    nameidx = FcFreeTypeGetFirstName (face, platform, lookupid,
+					      name_mapping, name_count,
+					      &sname);
+	    if (nameidx == -1)
+		continue;
+	    do
+	    {
+		switch (nameid) {
 		case TT_NAME_ID_WWS_FAMILY:
-#endif
 		case TT_NAME_ID_PREFERRED_FAMILY:
 		case TT_NAME_ID_FONT_FAMILY:
 #if 0	
 		case TT_NAME_ID_UNIQUE_ID:
 #endif
 		    if (FcDebug () & FC_DBG_SCANV)
-			printf ("found family (n %2d p %d e %d l 0x%04x) %s\n",
+			printf ("found family (n %2d p %d e %d l 0x%04x)",
 				sname.name_id, sname.platform_id,
-				sname.encoding_id, sname.language_id,
-				utf8);
+				sname.encoding_id, sname.language_id);
 
 		    elt = FC_FAMILY;
 		    eltlang = FC_FAMILYLANG;
@@ -1392,38 +1502,24 @@ FcFreeTypeQueryFace (const FT_Face  face
 		case TT_NAME_ID_MAC_FULL_NAME:
 		case TT_NAME_ID_FULL_NAME:
 		    if (FcDebug () & FC_DBG_SCANV)
-			printf ("found full   (n %2d p %d e %d l 0x%04x) %s\n",
+			printf ("found full   (n %2d p %d e %d l 0x%04x)",
 				sname.name_id, sname.platform_id,
-				sname.encoding_id, sname.language_id,
-				utf8);
+				sname.encoding_id, sname.language_id);
 
 		    elt = FC_FULLNAME;
 		    eltlang = FC_FULLNAMELANG;
 		    np = &nfullname;
 		    nlangp = &nfullname_lang;
 		    break;
-#ifdef TT_NAME_ID_WWS_SUBFAMILY
 		case TT_NAME_ID_WWS_SUBFAMILY:
-#endif
 		case TT_NAME_ID_PREFERRED_SUBFAMILY:
 		case TT_NAME_ID_FONT_SUBFAMILY:
-		    if (utf8)
-		    {
-			pp = utf8;
-			while (*pp == ' ')
-			    pp++;
-			len = strlen ((const char *) pp);
-			memmove (utf8, pp, len + 1);
-			pp = utf8 + len - 1;
-			while (*pp == ' ')
-			    pp--;
-			*(pp + 1) = 0;
-		    }
+		    if (variable)
+			break;
 		    if (FcDebug () & FC_DBG_SCANV)
-			printf ("found style  (n %2d p %d e %d l 0x%04x) %s\n",
+			printf ("found style  (n %2d p %d e %d l 0x%04x) ",
 				sname.name_id, sname.platform_id,
-				sname.encoding_id, sname.language_id,
-				utf8);
+				sname.encoding_id, sname.language_id);
 
 		    elt = FC_STYLE;
 		    eltlang = FC_STYLELANG;
@@ -1434,11 +1530,38 @@ FcFreeTypeQueryFace (const FT_Face  face
 		case TT_NAME_ID_MANUFACTURER:
 		    /* If the foundry wasn't found in the OS/2 table, look here */
 		    if(!foundry)
+		    {
+			FcChar8 *utf8;
+			utf8 = FcSfntNameTranscode (&sname);
 			foundry = FcNoticeFoundry((FT_String *) utf8);
+			free (utf8);
+		    }
 		    break;
 		}
 		if (elt)
 		{
+		    FcChar8		*utf8, *pp;
+
+		    utf8 = FcSfntNameTranscode (&sname);
+		    lang = FcSfntNameLanguage (&sname);
+
+		    if (FcDebug () & FC_DBG_SCANV)
+			printf ("%s\n", utf8);
+
+		    if (!utf8)
+			continue;
+
+		    /* Trim surrounding whitespace. */
+		    pp = utf8;
+		    while (*pp == ' ')
+			pp++;
+		    len = strlen ((const char *) pp);
+		    memmove (utf8, pp, len + 1);
+		    pp = utf8 + len;
+		    while (pp > utf8 && *(pp - 1) == ' ')
+			pp--;
+		    *pp = 0;
+
 		    if (FcStringInPatternElement (pat, elt, utf8))
 		    {
 			free (utf8);
@@ -1467,11 +1590,14 @@ FcFreeTypeQueryFace (const FT_Face  face
 		    }
 		    ++*np;
 		}
-		else
-		    free (utf8);
 	    }
+	    while (++nameidx < name_count &&
+		   FT_Get_Sfnt_Name (face, name_mapping[nameidx].idx, &sname) == 0 &&
+		   platform == sname.platform_id && lookupid == sname.name_id);
 	}
     }
+    if (!nm_share)
+	free (name_mapping);
 
     if (!nfamily && face->family_name &&
 	FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->family_name, (FcChar8 *) "") != 0)
@@ -1485,11 +1611,12 @@ FcFreeTypeQueryFace (const FT_Face  face
 	++nfamily;
     }
 
-    if (!nstyle && face->style_name &&
+    if (!variable && !nstyle && face->style_name &&
 	FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->style_name, (FcChar8 *) "") != 0)
     {
 	if (FcDebug () & FC_DBG_SCANV)
 	    printf ("using FreeType style \"%s\"\n", face->style_name);
+
 	if (!FcPatternAddString (pat, FC_STYLE, (FcChar8 *) face->style_name))
 	    goto bail1;
 	if (!FcPatternAddString (pat, FC_STYLELANG, (FcChar8 *) "en"))
@@ -1526,51 +1653,57 @@ FcFreeTypeQueryFace (const FT_Face  face
     }
 
     /* Add the PostScript name into the cache */
-    tmp = FT_Get_Postscript_Name (face);
-    if (!tmp)
+    if (!variable)
     {
-	FcChar8 *family, *familylang = NULL;
-	size_t len;
-	int n = 0;
+	char	    psname[256];
+	const char	    *tmp;
+	tmp = FT_Get_Postscript_Name (face);
+	if (!tmp)
+	{
+	    unsigned int i;
+	    FcChar8 *family, *familylang = NULL;
+	    size_t len;
+	    int n = 0;
 
-	/* Workaround when FT_Get_Postscript_Name didn't give any name.
-	 * try to find out the English family name and convert.
-	 */
-	while (FcPatternObjectGetString (pat, FC_FAMILYLANG_OBJECT, n, &familylang) == FcResultMatch)
-	{
-	    if (FcStrCmp (familylang, (const FcChar8 *)"en") == 0)
-		break;
-	    n++;
-	    familylang = NULL;
-	}
-	if (!familylang)
-	    n = 0;
+	    /* Workaround when FT_Get_Postscript_Name didn't give any name.
+	     * try to find out the English family name and convert.
+	     */
+	    while (FcPatternObjectGetString (pat, FC_FAMILYLANG_OBJECT, n, &familylang) == FcResultMatch)
+	    {
+		if (FcStrCmp (familylang, (const FcChar8 *)"en") == 0)
+		    break;
+		n++;
+		familylang = NULL;
+	    }
+	    if (!familylang)
+		n = 0;
 
-	if (FcPatternObjectGetString (pat, FC_FAMILY_OBJECT, n, &family) != FcResultMatch)
-	    goto bail1;
-	len = strlen ((const char *)family);
-	/* the literal name in PostScript Language is limited to 127 characters though,
-	 * It is the architectural limit. so assuming 255 characters may works enough.
-	 */
-	for (i = 0; i < len && i < 255; i++)
-	{
-	    /* those characters are not allowed to be the literal name in PostScript */
-	    static const char exclusive_chars[] = "\x04()/<>[]{}\t\f\r\n ";
+	    if (FcPatternObjectGetString (pat, FC_FAMILY_OBJECT, n, &family) != FcResultMatch)
+		goto bail1;
+	    len = strlen ((const char *)family);
+	    /* the literal name in PostScript Language is limited to 127 characters though,
+	     * It is the architectural limit. so assuming 255 characters may works enough.
+	     */
+	    for (i = 0; i < len && i < 255; i++)
+	    {
+		/* those characters are not allowed to be the literal name in PostScript */
+		static const char exclusive_chars[] = "\x04()/<>[]{}\t\f\r\n ";
 
-	    if (strchr(exclusive_chars, family[i]) != NULL)
-		psname[i] = '-';
-	    else
-		psname[i] = family[i];
+		if (strchr(exclusive_chars, family[i]) != NULL)
+		    psname[i] = '-';
+		else
+		    psname[i] = family[i];
+	    }
+	    psname[i] = 0;
 	}
-	psname[i] = 0;
-    }
-    else
-    {
-	strncpy (psname, tmp, 255);
-	psname[255] = 0;
+	else
+	{
+	    strncpy (psname, tmp, 255);
+	    psname[255] = 0;
+	}
+	if (!FcPatternAddString (pat, FC_POSTSCRIPT_NAME, (const FcChar8 *)psname))
+	    goto bail1;
     }
-    if (!FcPatternAddString (pat, FC_POSTSCRIPT_NAME, (const FcChar8 *)psname))
-	goto bail1;
 
     if (file && *file && !FcPatternAddString (pat, FC_FILE, file))
 	goto bail1;
@@ -1606,6 +1739,7 @@ FcFreeTypeQueryFace (const FT_Face  face
 
     if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
     {
+	unsigned int i;
 	for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
 	{
 	    FT_ULong	bits;
@@ -1620,7 +1754,7 @@ FcFreeTypeQueryFace (const FT_Face  face
 		bits = os2->ulCodePageRange2;
 		bit = FcCodePageRange[i].bit - 32;
 	    }
-	    if (bits & (1 << bit))
+	    if (bits & (1U << bit))
 	    {
 		/*
 		 * If the font advertises support for multiple
@@ -1640,21 +1774,12 @@ FcFreeTypeQueryFace (const FT_Face  face
     if (os2 && os2->version != 0xffff)
     {
 	weight = os2->usWeightClass;
-	if (weight < 10 && weight_mult != 1.0)
-	{
-		/* Work around bad values by cleaning them up before
-		 * multiplying by weight_mult. */
-		weight = FcWeightToOpenType (FcWeightFromOpenType (weight));
-	}
-	weight = FcWeightFromOpenType ((int) (weight * weight_mult + .5));
+	weight = FcWeightFromOpenTypeDouble (weight * weight_mult);
 	if ((FcDebug() & FC_DBG_SCANV) && weight != -1)
-	    printf ("\tos2 weight class %d multiplier %g maps to weight %d\n",
+	    printf ("\tos2 weight class %d multiplier %g maps to weight %g\n",
 		    os2->usWeightClass, weight_mult, weight);
 
-	/* TODO:
-	 * Add FcWidthFromOpenType and FcWidthToOpenType,
-	 * and apply width_mult post-conversion? */
-	switch ((int) (os2->usWidthClass * width_mult + .5)) {
+	switch (os2->usWidthClass) {
 	case 1:	width = FC_WIDTH_ULTRACONDENSED; break;
 	case 2:	width = FC_WIDTH_EXTRACONDENSED; break;
 	case 3:	width = FC_WIDTH_CONDENSED; break;
@@ -1665,8 +1790,9 @@ FcFreeTypeQueryFace (const FT_Face  face
 	case 8:	width = FC_WIDTH_EXTRAEXPANDED; break;
 	case 9:	width = FC_WIDTH_ULTRAEXPANDED; break;
 	}
+	width *= width_mult;
 	if ((FcDebug() & FC_DBG_SCANV) && width != -1)
-	    printf ("\tos2 width class %d multiplier %g maps to width %d\n",
+	    printf ("\tos2 width class %d multiplier %g maps to width %g\n",
 		    os2->usWidthClass, width_mult, width);
     }
     if (os2 && (complex_ = FcFontCapabilities(face)))
@@ -1679,24 +1805,31 @@ FcFreeTypeQueryFace (const FT_Face  face
 	free (complex_);
     }
 
-#if defined (HAVE_TT_OS2_USUPPEROPTICALPOINTSIZE) && defined (HAVE_TT_OS2_USLOWEROPTICALPOINTSIZE)
-    if (os2 && os2->version >= 0x0005 && os2->version != 0xffff)
+    if (!variable_size && os2 && os2->version >= 0x0005 && os2->version != 0xffff)
     {
 	double lower_size, upper_size;
+	FcRange *r;
 
 	/* usLowerPointSize and usUpperPointSize is actually twips */
 	lower_size = os2->usLowerOpticalPointSize / 20.0L;
 	upper_size = os2->usUpperOpticalPointSize / 20.0L;
 
-	r = FcRangeCreateDouble (lower_size, upper_size);
-	if (!FcPatternAddRange (pat, FC_SIZE, r))
+	if (lower_size == upper_size)
 	{
+	    if (!FcPatternAddDouble (pat, FC_SIZE, lower_size))
+		goto bail1;
+	}
+	else
+	{
+	    r = FcRangeCreateDouble (lower_size, upper_size);
+	    if (!FcPatternAddRange (pat, FC_SIZE, r))
+	    {
+		FcRangeDestroy (r);
+		goto bail1;
+	    }
 	    FcRangeDestroy (r);
-	    goto bail1;
 	}
-	FcRangeDestroy (r);
     }
-#endif
 
     /*
      * Type 1: Check for FontInfo dictionary information
@@ -1710,7 +1843,7 @@ FcFreeTypeQueryFace (const FT_Face  face
 	{
 	    weight = FcIsWeight ((FcChar8 *) psfontinfo.weight);
     	    if (FcDebug() & FC_DBG_SCANV)
-    		printf ("\tType1 weight %s maps to %d\n",
+		printf ("\tType1 weight %s maps to %g\n",
 			psfontinfo.weight, weight);
 	}
 
@@ -1774,7 +1907,7 @@ FcFreeTypeQueryFace (const FT_Face  face
 	{
 	    width = FcIsWidth ((FcChar8 *) prop.u.atom);
 	    if (FcDebug () & FC_DBG_SCANV)
-		printf ("\tsetwidth %s maps to %d\n", prop.u.atom, width);
+		printf ("\tsetwidth %s maps to %g\n", prop.u.atom, width);
 	}
     }
 #endif
@@ -1788,13 +1921,13 @@ FcFreeTypeQueryFace (const FT_Face  face
 	{
 	    weight = FcContainsWeight (style);
 	    if (FcDebug() & FC_DBG_SCANV)
-		printf ("\tStyle %s maps to weight %d\n", style, weight);
+		printf ("\tStyle %s maps to weight %g\n", style, weight);
 	}
 	if (width == -1)
 	{
 	    width = FcContainsWidth (style);
 	    if (FcDebug() & FC_DBG_SCANV)
-		printf ("\tStyle %s maps to width %d\n", style, width);
+		printf ("\tStyle %s maps to width %g\n", style, width);
 	}
 	if (slant == -1)
 	{
@@ -1836,10 +1969,10 @@ FcFreeTypeQueryFace (const FT_Face  face
     if (!FcPatternAddInteger (pat, FC_SLANT, slant))
 	goto bail1;
 
-    if (!FcPatternAddInteger (pat, FC_WEIGHT, weight))
+    if (!variable_weight && !FcPatternAddDouble (pat, FC_WEIGHT, weight))
 	goto bail1;
 
-    if (!FcPatternAddInteger (pat, FC_WIDTH, width))
+    if (!variable_width && !FcPatternAddDouble (pat, FC_WIDTH, width))
 	goto bail1;
 
     if (!FcPatternAddString (pat, FC_FOUNDRY, foundry))
@@ -1852,15 +1985,23 @@ FcFreeTypeQueryFace (const FT_Face  face
     /*
      * Compute the unicode coverage for the font
      */
-    cs = FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
+    if (cs_share && *cs_share)
+	cs = FcCharSetCopy (*cs_share);
+    else
+    {
+	cs = FcFreeTypeCharSet (face, NULL);
+	if (cs_share)
+	    *cs_share = FcCharSetCopy (cs);
+    }
     if (!cs)
 	goto bail1;
 
-    /* The FcFreeTypeCharSetAndSpacing() chose the encoding; test it for symbol. */
+    /* The FcFreeTypeCharSet() chose the encoding; test it for symbol. */
     symbol = face->charmap && face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
     if (!FcPatternAddBool (pat, FC_SYMBOL, symbol))
 	goto bail1;
 
+    spacing = FcFreeTypeSpacing (face);
 #if HAVE_FT_GET_BDF_PROPERTY
     /* For PCF fonts, override the computed spacing with the one from
        the property */
@@ -1895,7 +2036,14 @@ FcFreeTypeQueryFace (const FT_Face  face
 
     if (!symbol)
     {
-	ls = FcFreeTypeLangSet (cs, exclusiveLang);
+	if (ls_share && *ls_share)
+	    ls = FcLangSetCopy (*ls_share);
+	else
+	{
+	    ls = FcFreeTypeLangSet (cs, exclusiveLang);
+	    if (ls_share)
+		*ls_share = FcLangSetCopy (ls);
+	}
 	if (!ls)
 	    goto bail2;
     }
@@ -1920,6 +2068,7 @@ FcFreeTypeQueryFace (const FT_Face  face
 
     if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
     {
+	int i;
 	for (i = 0; i < face->num_fixed_sizes; i++)
 	    if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
 				     FcGetPixelSize (face, i)))
@@ -1965,9 +2114,18 @@ bail0:
 }
 
 FcPattern *
+FcFreeTypeQueryFace (const FT_Face  face,
+		     const FcChar8  *file,
+		     unsigned int   id,
+		     FcBlanks	    *blanks FC_UNUSED)
+{
+    return FcFreeTypeQueryFaceInternal (face, file, id, NULL, NULL, NULL);
+}
+
+FcPattern *
 FcFreeTypeQuery(const FcChar8	*file,
-		int		id,
-		FcBlanks	*blanks,
+		unsigned int	id,
+		FcBlanks	*blanks FC_UNUSED,
 		int		*count)
 {
     FT_Face	    face;
@@ -1977,12 +2135,13 @@ FcFreeTypeQuery(const FcChar8	*file,
     if (FT_Init_FreeType (&ftLibrary))
 	return NULL;
 
-    if (FT_New_Face (ftLibrary, (char *) file, id, &face))
+    if (FT_New_Face (ftLibrary, (char *) file, id & 0x7FFFFFFFF, &face))
 	goto bail;
 
-    *count = face->num_faces;
+    if (count)
+      *count = face->num_faces;
 
-    pat = FcFreeTypeQueryFace (face, file, id, blanks);
+    pat = FcFreeTypeQueryFaceInternal (face, file, id, NULL, NULL, NULL);
 
     FT_Done_Face (face);
 bail:
@@ -1990,138 +2149,135 @@ bail:
     return pat;
 }
 
-/*
- * For our purposes, this approximation is sufficient
- */
-#if !HAVE_FT_GET_NEXT_CHAR
-#define FT_Get_Next_Char(face, ucs4, gi) ((ucs4) >= 0xffffff ? \
-					  (*(gi) = 0), 0 : \
-					  (*(gi) = 1), (ucs4) + 1)
-#warning "No FT_Get_Next_Char: Please install freetype version 2.1.0 or newer"
-#endif
+unsigned int
+FcFreeTypeQueryAll(const FcChar8	*file,
+		   unsigned int		id,
+		   FcBlanks		*blanks,
+		   int			*count,
+		   FcFontSet            *set)
+{
+    FT_Face face = NULL;
+    FT_Library ftLibrary = NULL;
+    FcCharSet *cs = NULL;
+    FcLangSet *ls = NULL;
+    FcNameMapping  *nm = NULL;
+    FT_MM_Var *mm_var = NULL;
+    FcBool index_set = id != (unsigned int) -1;
+    unsigned int set_face_num = index_set ? id & 0xFFFF : 0;
+    unsigned int set_instance_num = index_set ? id >> 16 : 0;
+    unsigned int face_num = set_face_num;
+    unsigned int instance_num = set_instance_num;
+    unsigned int num_faces = 0;
+    unsigned int num_instances = 0;
+    unsigned int ret = 0;
+    int err = 0;
 
-static const FT_Encoding fcFontEncodings[] = {
-    FT_ENCODING_UNICODE,
-    FT_ENCODING_MS_SYMBOL
-};
+    if (count)
+	*count = 0;
 
-#define NUM_DECODE  (int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0]))
+    if (FT_Init_FreeType (&ftLibrary))
+	return 0;
 
-#include "../fc-glyphname/fcglyphname.h"
+    if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
+	goto bail;
 
-static FcChar32
-FcHashGlyphName (const FcChar8 *name)
-{
-    FcChar32	h = 0;
-    FcChar8	c;
+    num_faces = face->num_faces;
+    num_instances = face->style_flags >> 16;
+    if (num_instances && (!index_set || instance_num))
+    {
+	FT_Get_MM_Var (face, &mm_var);
+	if (!mm_var)
+	  num_instances = 0;
+    }
+
+    if (count)
+      *count = num_faces;
+
+    do {
+	FcPattern *pat = NULL;
+
+	if (instance_num == 0x8000 || instance_num > num_instances)
+	    FT_Set_Var_Design_Coordinates (face, 0, NULL); /* Reset variations. */
+	else if (instance_num)
+	{
+	    FT_Var_Named_Style *instance = &mm_var->namedstyle[instance_num - 1];
+	    FT_Fixed *coords = instance->coords;
+	    FcBool nonzero;
+	    unsigned int i;
+
+	    /* Skip named-instance that coincides with base instance. */
+	    nonzero = FcFalse;
+	    for (i = 0; i < mm_var->num_axis; i++)
+		if (coords[i] != mm_var->axis[i].def)
+		{
+		    nonzero = FcTrue;
+		    break;
+		}
+	    if (!nonzero)
+		goto skip;
 
-    while ((c = *name++))
-    {
-	h = ((h << 1) | (h >> 31)) ^ c;
-    }
-    return h;
-}
+	    FT_Set_Var_Design_Coordinates (face, mm_var->num_axis, coords);
+	}
 
-#if HAVE_FT_HAS_PS_GLYPH_NAMES
-/*
- * Use Type1 glyph names for fonts which have reliable names
- * and which export an Adobe Custom mapping
- */
-static FcBool
-FcFreeTypeUseNames (FT_Face face)
-{
-    FT_Int  map;
+	id = ((instance_num << 16) + face_num);
+	pat = FcFreeTypeQueryFaceInternal (face, (const FcChar8 *) file, id, &cs, &ls, &nm);
 
-    if (!FT_Has_PS_Glyph_Names (face))
-	return FcFalse;
-    for (map = 0; map < face->num_charmaps; map++)
-	if (face->charmaps[map]->encoding == ft_encoding_adobe_custom)
-	    return FcTrue;
-    return FcFalse;
-}
+	if (pat)
+	{
 
-static const FcChar8 *
-FcUcs4ToGlyphName (FcChar32 ucs4)
-{
-    int		i = (int) (ucs4 % FC_GLYPHNAME_HASH);
-    int		r = 0;
-    FcGlyphId	gn;
+	    ret++;
+	    if (!set || ! FcFontSetAdd (set, pat))
+		FcPatternDestroy (pat);
+	}
+	else if (instance_num != 0x8000)
+	    err = 1;
 
-    while ((gn = _fc_ucs_to_name[i]) != -1)
-    {
-	if (_fc_glyph_names[gn].ucs == ucs4)
-	    return _fc_glyph_names[gn].name;
-	if (!r)
+skip:
+	if (!index_set && instance_num < num_instances)
+	    instance_num++;
+	else if (!index_set && instance_num == num_instances)
+	    instance_num = 0x8000; /* variable font */
+	else
 	{
-	    r = (int) (ucs4 % FC_GLYPHNAME_REHASH);
-	    if (!r)
-		r = 1;
-	}
-	i += r;
-	if (i >= FC_GLYPHNAME_HASH)
-	    i -= FC_GLYPHNAME_HASH;
-    }
-    return 0;
-}
+	    free (nm);
+	    nm = NULL;
+	    FcLangSetDestroy (ls);
+	    ls = NULL;
+	    FcCharSetDestroy (cs);
+	    cs = NULL;
+	    FT_Done_Face (face);
+	    face = NULL;
 
-static FcChar32
-FcGlyphNameToUcs4 (FcChar8 *name)
-{
-    FcChar32	h = FcHashGlyphName (name);
-    int		i = (int) (h % FC_GLYPHNAME_HASH);
-    int		r = 0;
-    FcGlyphId	gn;
+	    face_num++;
+	    instance_num = set_instance_num;
 
-    while ((gn = _fc_name_to_ucs[i]) != -1)
-    {
-	if (!strcmp ((char *) name, (char *) _fc_glyph_names[gn].name))
-	    return _fc_glyph_names[gn].ucs;
-	if (!r)
-	{
-	    r = (int) (h % FC_GLYPHNAME_REHASH);
-	    if (!r)
-		r = 1;
+	    if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
+	      break;
 	}
-	i += r;
-	if (i >= FC_GLYPHNAME_HASH)
-	    i -= FC_GLYPHNAME_HASH;
-    }
-    return 0xffff;
-}
-
-/*
- * Work around a bug in some FreeType versions which fail
- * to correctly bounds check glyph name buffers and overwrite
- * the stack. As Postscript names have a limit of 127 characters,
- * this should be sufficient.
- */
+    } while (!err && (!index_set || face_num == set_face_num) && face_num < num_faces);
 
-#if FC_GLYPHNAME_MAXLEN < 127
-# define FC_GLYPHNAME_BUFLEN 127
+bail:
+#ifdef HAVE_FT_DONE_MM_VAR
+    FT_Done_MM_Var (ftLibrary, mm_var);
 #else
-# define FC_GLYPHNAME_BUFLEN FC_GLYPHNAME_MAXLEN
+    free (mm_var);
 #endif
+    FcLangSetDestroy (ls);
+    FcCharSetDestroy (cs);
+    if (face)
+	FT_Done_Face (face);
+    FT_Done_FreeType (ftLibrary);
 
-/*
- * Search through a font for a glyph by name.  This is
- * currently a linear search as there doesn't appear to be
- * any defined order within the font
- */
-static FT_UInt
-FcFreeTypeGlyphNameIndex (FT_Face face, const FcChar8 *name)
-{
-    FT_UInt gindex;
-    FcChar8 name_buf[FC_GLYPHNAME_BUFLEN + 2];
-
-    for (gindex = 0; gindex < (FT_UInt) face->num_glyphs; gindex++)
-    {
-	if (FT_Get_Glyph_Name (face, gindex, name_buf, FC_GLYPHNAME_BUFLEN+1) == 0)
-	    if (!strcmp ((char *) name, (char *) name_buf))
-		return gindex;
-    }
-    return 0;
+    return ret;
 }
-#endif
+
+
+static const FT_Encoding fcFontEncodings[] = {
+    FT_ENCODING_UNICODE,
+    FT_ENCODING_MS_SYMBOL
+};
+
+#define NUM_DECODE  (int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0]))
 
 /*
  * Map a UCS4 glyph to a glyph index.  Use all available encoding
@@ -2180,38 +2336,23 @@ FcFreeTypeCharIndex (FT_Face face, FcCha
 		return glyphindex;
 	}
     }
-#if HAVE_FT_HAS_PS_GLYPH_NAMES
-    /*
-     * Check postscript name table if present
-     */
-    if (FcFreeTypeUseNames (face))
-    {
-	const FcChar8	*name = FcUcs4ToGlyphName (ucs4);
-	if (name)
-	{
-	    glyphindex = FcFreeTypeGlyphNameIndex (face, name);
-	    if (glyphindex)
-		return glyphindex;
-	}
-    }
-#endif
     return 0;
 }
 
-static FcBool
-FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4,
-		      FT_UInt glyph, FcBlanks *blanks,
-		      FT_Pos *advance,
-		      FcBool using_strike)
+static inline int fc_min (int a, int b) { return a <= b ? a : b; }
+static inline int fc_max (int a, int b) { return a >= b ? a : b; }
+static inline FcBool fc_approximately_equal (int x, int y)
+{ return abs (x - y) * 33 <= fc_max (abs (x), abs (y)); }
+
+static int
+FcFreeTypeSpacing (FT_Face face)
 {
     FT_Int	    load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
-    FT_GlyphSlot    slot;
-
-    if (using_strike)
-	load_flags &= ~FT_LOAD_NO_SCALE;
+    FT_Pos	    advances[3] = {0};
+    unsigned int    num_advances = 0;
+    int		    o;
 
-    /*
-     * When using scalable fonts, only report those glyphs
+    /* When using scalable fonts, only report those glyphs
      * which can be scaled; otherwise those fonts will
      * only be available at some sizes, and never when
      * transformed.  Avoid this by simply reporting bitmap-only
@@ -2220,273 +2361,162 @@ FcFreeTypeCheckGlyph (FT_Face face, FcCh
     if (face->face_flags & FT_FACE_FLAG_SCALABLE)
 	load_flags |= FT_LOAD_NO_BITMAP;
 
-    if (FT_Load_Glyph (face, glyph, load_flags))
-	return FcFalse;
+    if (!(face->face_flags & FT_FACE_FLAG_SCALABLE) &&
+	face->num_fixed_sizes > 0 &&
+	FT_Get_Sfnt_Table (face, ft_sfnt_head))
+    {
+	FT_Int strike_index = 0, i;
+	/* Select the face closest to 16 pixels tall */
+	for (i = 1; i < face->num_fixed_sizes; i++)
+	{
+	    if (abs (face->available_sizes[i].height - 16) <
+		abs (face->available_sizes[strike_index].height - 16))
+		strike_index = i;
+	}
 
-    slot = face->glyph;
-    if (!glyph)
-	return FcFalse;
+	FT_Select_Size (face, strike_index);
+    }
 
-    *advance = slot->metrics.horiAdvance;
+    for (o = 0; o < NUM_DECODE; o++)
+    {
+	FcChar32        ucs4;
+	FT_UInt	 	glyph;
 
-    switch ((int) slot->format) {
-    case ft_glyph_format_bitmap:
-	/*
-	 * Bitmaps are assumed to be reasonable; if
-	 * this proves to be a rash assumption, this
-	 * code can be easily modified
-	 */
-	return FcTrue;
-    case ft_glyph_format_outline:
-	/*
-	 * Glyphs with contours are always OK
-	 */
-	if (slot->outline.n_contours != 0)
-	    return FcTrue;
-	/*
-	 * Glyphs with no contours are only OK if
-	 * they're members of the Blanks set specified
-	 * in the configuration.  If blanks isn't set,
-	 * then allow any glyph to be blank
-	 */
-	if (!blanks || FcBlanksIsMember (blanks, ucs4))
-	    return FcTrue;
-	/* fall through ... */
-    default:
+	if (FT_Select_Charmap (face, fcFontEncodings[o]) != 0)
+	    continue;
+
+	ucs4 = FT_Get_First_Char (face, &glyph);
+	while (glyph != 0 && num_advances < 3)
+	{
+	    FT_Pos advance = 0;
+	    if (!FT_Get_Advance (face, glyph, load_flags, &advance) && advance)
+	    {
+		unsigned int j;
+		for (j = 0; j < num_advances; j++)
+		  if (fc_approximately_equal (advance, advances[j]))
+		    break;
+		if (j == num_advances)
+		  advances[num_advances++] = advance;
+	    }
+
+	    ucs4 = FT_Get_Next_Char (face, ucs4, &glyph);
+	}
 	break;
     }
-    return FcFalse;
-}
 
-#define APPROXIMATELY_EQUAL(x,y) (FC_ABS ((x) - (y)) <= FC_MAX (FC_ABS (x), FC_ABS (y)) / 33)
+    if (num_advances <= 1)
+	return FC_MONO;
+    else if (num_advances == 2 &&
+	     fc_approximately_equal (fc_min (advances[0], advances[1]) * 2,
+				     fc_max (advances[0], advances[1])))
+	return FC_DUAL;
+    else
+	return FC_PROPORTIONAL;
+}
 
-static FcCharSet *
-FcFreeTypeCharSetAndSpacingForSize (FT_Face face, FcBlanks *blanks, int *spacing, FT_Int strike_index)
+FcCharSet *
+FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks FC_UNUSED)
 {
-    FcChar32	    page, off, ucs4;
-#ifdef CHECK
-    FcChar32	    font_max = 0;
-#endif
+    const FT_Int    load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
     FcCharSet	    *fcs;
-    FcCharLeaf	    *leaf;
     int		    o;
-    FT_UInt	    glyph;
-    FT_Pos	    advance, advance_one = 0, advance_two = 0;
-    FcBool	    has_advance = FcFalse, fixed_advance = FcTrue, dual_advance = FcFalse;
-    FcBool	    using_strike = FcFalse;
 
     fcs = FcCharSetCreate ();
     if (!fcs)
-	goto bail0;
-
-#if HAVE_FT_SELECT_SIZE
-    if (strike_index >= 0) {
-	if (FT_Select_Size (face, strike_index) != FT_Err_Ok)
-	    goto bail1;
-	using_strike = FcTrue;
-    }
-#endif
+	goto bail;
 
 #ifdef CHECK
     printf ("Family %s style %s\n", face->family_name, face->style_name);
 #endif
     for (o = 0; o < NUM_DECODE; o++)
     {
+	FcChar32        page, off, ucs4;
+	FcCharLeaf      *leaf;
+	FT_UInt	 	glyph;
+
 	if (FT_Select_Charmap (face, fcFontEncodings[o]) != 0)
 	    continue;
 
-	{
-            page = ~0;
-            leaf = NULL;
-            ucs4 = FT_Get_First_Char (face, &glyph);
-            while (glyph != 0)
+	page = ~0;
+	leaf = NULL;
+	ucs4 = FT_Get_First_Char (face, &glyph);
+	while (glyph != 0)
+	{
+	    FcBool good = FcTrue;
+
+	    /* CID fonts built by Adobe used to make ASCII control chars to cid1
+	     * (space glyph). As such, always check contour for those characters. */
+	    if (ucs4 <= 0x001F)
 	    {
-		if (FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike))
-		{
-		    if (advance)
-		    {
-			if (!has_advance)
-			{
-			    has_advance = FcTrue;
-			    advance_one = advance;
-			}
-			else if (!APPROXIMATELY_EQUAL (advance, advance_one))
-			{
-			    if (fixed_advance)
-			    {
-				dual_advance = FcTrue;
-				fixed_advance = FcFalse;
-				advance_two = advance;
-			    }
-			    else if (!APPROXIMATELY_EQUAL (advance, advance_two))
-				dual_advance = FcFalse;
-			}
-		    }
-
-		    if ((ucs4 >> 8) != page)
-		    {
-			page = (ucs4 >> 8);
-			leaf = FcCharSetFindLeafCreate (fcs, ucs4);
-			if (!leaf)
-			    goto bail1;
-		    }
-		    off = ucs4 & 0xff;
-		    leaf->map[off >> 5] |= (1 << (off & 0x1f));
-#ifdef CHECK
-		    if (ucs4 > font_max)
-			font_max = ucs4;
-#endif
-		}
-		ucs4 = FT_Get_Next_Char (face, ucs4, &glyph);
+		if (FT_Load_Glyph (face, glyph, load_flags) ||
+		    (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE &&
+		     face->glyph->outline.n_contours == 0))
+		    good = FcFalse;
 	    }
-	    if (fcFontEncodings[o] == FT_ENCODING_MS_SYMBOL)
+
+	    if (good)
 	    {
-		/* For symbol-encoded OpenType fonts, we duplicate the
-		 * U+F000..F0FF range at U+0000..U+00FF.  That's what
-		 * Windows seems to do, and that's hinted about at:
-		 * http://www.microsoft.com/typography/otspec/recom.htm
-		 * under "Non-Standard (Symbol) Fonts".
-		 *
-		 * See thread with subject "Webdings and other MS symbol
-		 * fonts don't display" on mailing list from May 2015.
-		 */
-		for (ucs4 = 0xF000; ucs4 < 0xF100; ucs4++)
+		FcCharSetAddChar (fcs, ucs4);
+		if ((ucs4 >> 8) != page)
 		{
-		    if (FcCharSetHasChar (fcs, ucs4))
-			FcCharSetAddChar (fcs, ucs4 - 0xF000);
+		    page = (ucs4 >> 8);
+		    leaf = FcCharSetFindLeafCreate (fcs, ucs4);
+		    if (!leaf)
+			goto bail;
 		}
+		off = ucs4 & 0xff;
+		leaf->map[off >> 5] |= (1U << (off & 0x1f));
 	    }
-#ifdef CHECK
-	    for (ucs4 = 0; ucs4 < 0x10000; ucs4++)
-	    {
-		FcBool	    FT_Has, FC_Has;
 
-		FT_Has = FT_Get_Char_Index (face, ucs4) != 0;
-		FC_Has = FcCharSetHasChar (fcs, ucs4);
-		if (FT_Has != FC_Has)
-		{
-		    printf ("0x%08x FT says %d FC says %d\n", ucs4, FT_Has, FC_Has);
-		}
-	    }
-#endif
+	    ucs4 = FT_Get_Next_Char (face, ucs4, &glyph);
 	}
-
-       break;
-    }
-#if HAVE_FT_HAS_PS_GLYPH_NAMES
-    /*
-     * Add mapping from PS glyph names if available
-     */
-    if (FcFreeTypeUseNames (face))
-    {
-	FcChar8 name_buf[FC_GLYPHNAME_BUFLEN + 2];
-
-	for (glyph = 0; glyph < (FT_UInt) face->num_glyphs; glyph++)
+	if (fcFontEncodings[o] == FT_ENCODING_MS_SYMBOL)
 	{
-	    if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_BUFLEN+1) == 0)
+	    /* For symbol-encoded OpenType fonts, we duplicate the
+	     * U+F000..F0FF range at U+0000..U+00FF.  That's what
+	     * Windows seems to do, and that's hinted about at:
+	     * http://www.microsoft.com/typography/otspec/recom.htm
+	     * under "Non-Standard (Symbol) Fonts".
+	     *
+	     * See thread with subject "Webdings and other MS symbol
+	     * fonts don't display" on mailing list from May 2015.
+	     */
+	    for (ucs4 = 0xF000; ucs4 < 0xF100; ucs4++)
 	    {
-		ucs4 = FcGlyphNameToUcs4 (name_buf);
-		if (ucs4 != 0xffff &&
-		    FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike))
-		{
-		    if (advance)
-		    {
-			if (!has_advance)
-			{
-			    has_advance = FcTrue;
-			    advance_one = advance;
-			}
-			else if (!APPROXIMATELY_EQUAL (advance, advance_one))
-			{
-			    if (fixed_advance)
-			    {
-				dual_advance = FcTrue;
-				fixed_advance = FcFalse;
-				advance_two = advance;
-			    }
-			    else if (!APPROXIMATELY_EQUAL (advance, advance_two))
-				dual_advance = FcFalse;
-			}
-		    }
-		    leaf = FcCharSetFindLeafCreate (fcs, ucs4);
-		    if (!leaf)
-			goto bail1;
-		    leaf->map[(ucs4 & 0xff) >> 5] |= (1 << (ucs4 & 0x1f));
-#ifdef CHECK
-		    if (ucs4 > font_max)
-			font_max = ucs4;
-#endif
-		}
+		if (FcCharSetHasChar (fcs, ucs4))
+		    FcCharSetAddChar (fcs, ucs4 - 0xF000);
 	    }
 	}
-    }
-#endif
 #ifdef CHECK
-    printf ("%d glyphs %d encoded\n", (int) face->num_glyphs, FcCharSetCount (fcs));
-    for (ucs4 = 0; ucs4 <= font_max; ucs4++)
-    {
-	FcBool	has_char = (glyph = FcFreeTypeCharIndex (face, ucs4)) != 0;
-	FcBool	has_bit = FcCharSetHasChar (fcs, ucs4);
-
-	if (has_char && !has_bit)
+	for (ucs4 = 0x0020; ucs4 < 0x10000; ucs4++)
 	{
-	    if (!FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike))
-		printf ("Bitmap missing broken char 0x%x\n", ucs4);
-	    else
-		printf ("Bitmap missing char 0x%x\n", ucs4);
+	    FcBool	    FT_Has, FC_Has;
+
+	    FT_Has = FT_Get_Char_Index (face, ucs4) != 0;
+	    FC_Has = FcCharSetHasChar (fcs, ucs4);
+	    if (FT_Has != FC_Has)
+	    {
+		printf ("0x%08x FT says %d FC says %d\n", ucs4, FT_Has, FC_Has);
+	    }
 	}
-	else if (!has_char && has_bit)
-	    printf ("Bitmap extra char 0x%x\n", ucs4);
-    }
 #endif
-    if (fixed_advance)
-	*spacing = FC_MONO;
-    else if (dual_advance && APPROXIMATELY_EQUAL (2 * FC_MIN (advance_one, advance_two), FC_MAX (advance_one, advance_two)))
-        *spacing = FC_DUAL;
-    else
-	*spacing = FC_PROPORTIONAL;
+	break;
+    }
+
     return fcs;
-bail1:
+bail:
     FcCharSetDestroy (fcs);
-bail0:
     return 0;
 }
 
 FcCharSet *
-FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
+FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spacing)
 {
-    FcCharSet	*cs;
-
-    /*
-     * Check for bitmap-only ttf fonts that are missing the glyf table.
-     * In that case, pick a size and look for glyphs in that size instead
-     */
-    if (!(face->face_flags & FT_FACE_FLAG_SCALABLE) &&
-	face->num_fixed_sizes > 0 &&
-	FT_Get_Sfnt_Table (face, ft_sfnt_head))
-    {
-	FT_Int  strike_index = 0;
-	int	    i;
 
-	/* Select the face closest to 16 pixels tall */
-	for (i = 1; i < face->num_fixed_sizes; i++) {
-	    if (abs (face->available_sizes[i].height - 16) <
-		abs (face->available_sizes[strike_index].height - 16))
-		strike_index = i;
-	}
-	cs = FcFreeTypeCharSetAndSpacingForSize (face, blanks, spacing, strike_index);
-    }
-    else
-	cs = FcFreeTypeCharSetAndSpacingForSize (face, blanks, spacing, -1);
-    return cs;
-}
-
-FcCharSet *
-FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks)
-{
-    int spacing;
+    if (spacing)
+	*spacing = FcFreeTypeSpacing (face);
 
-    return FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
+    return FcFreeTypeCharSet (face, blanks);
 }
 
 
@@ -2584,7 +2614,7 @@ GetScriptTags(FT_Face face, FT_ULong tab
     ftglue_stream_frame_exit( stream );
 
     *stags = malloc(script_count * sizeof (FT_ULong));
-    if (!stags)
+    if (!*stags)
 	return 0;
 
     p = 0;

Index: xsrc/external/mit/fontconfig/dist/src/fcint.h
diff -u xsrc/external/mit/fontconfig/dist/src/fcint.h:1.8 xsrc/external/mit/fontconfig/dist/src/fcint.h:1.9
--- xsrc/external/mit/fontconfig/dist/src/fcint.h:1.8	Tue Aug 29 08:38:50 2017
+++ xsrc/external/mit/fontconfig/dist/src/fcint.h	Fri Mar  8 09:49:07 2019
@@ -101,7 +101,6 @@ extern pfnSHGetFolderPathA pSHGetFolderP
 
 #define FC_MIN(a,b) ((a) < (b) ? (a) : (b))
 #define FC_MAX(a,b) ((a) > (b) ? (a) : (b))
-#define FC_ABS(a)   ((a) < 0 ? -(a) : (a))
 
 /* slim_internal.h */
 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun)
@@ -114,13 +113,18 @@ extern pfnSHGetFolderPathA pSHGetFolderP
 #define FcPrivate
 #endif
 
-FC_ASSERT_STATIC (sizeof (FcRef) == sizeof (int));
+/* NLS */
+#ifdef ENABLE_NLS
+#include <libintl.h>
+#define _(x)		(dgettext(GETTEXT_PACKAGE, x))
+#else
+#define dgettext(d, s)	(s)
+#define _(x)		(x)
+#endif
+
+#define N_(x)	x
 
-typedef enum _FcValueBinding {
-    FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame,
-    /* to make sure sizeof (FcValueBinding) == 4 even with -fshort-enums */
-    FcValueBindingEnd = INT_MAX
-} FcValueBinding;
+FC_ASSERT_STATIC (sizeof (FcRef) == sizeof (int));
 
 #define FcStrdup(s) ((FcChar8 *) strdup ((const char *) (s)))
 #define FcFree(s) (free ((FcChar8 *) (s)))
@@ -238,7 +242,7 @@ typedef enum _FcOp {
 } FcOp;
 
 typedef enum _FcOpFlags {
-	FcOpFlagIgnoreBlanks = 1 << 0
+	FcOpFlagIgnoreBlanks = 1U << 0
 } FcOpFlags;
 
 #define FC_OP_GET_OP(_x_)	((_x_) & 0xffff)
@@ -310,6 +314,16 @@ typedef struct _FcEdit {
     FcValueBinding  binding;
 } FcEdit;
 
+typedef void (* FcDestroyFunc) (void *data);
+
+typedef struct _FcPtrList	FcPtrList;
+/* need to sync with FcConfigFileInfoIter at fontconfig.h */
+typedef struct _FcPtrListIter {
+    void *dummy1;
+    void *dummy2;
+    void *dummy3;
+} FcPtrListIter;
+
 typedef enum _FcRuleType {
     FcRuleUnknown, FcRuleTest, FcRuleEdit
 } FcRuleType;
@@ -323,10 +337,14 @@ typedef struct _FcRule {
     } u;
 } FcRule;
 
-typedef struct _FcSubst {
-    struct _FcSubst	*next;
-    FcRule		*rule;
-} FcSubst;
+typedef struct _FcRuleSet {
+    FcRef	ref;
+    FcChar8	*name;
+    FcChar8	*description;
+    FcChar8	*domain;
+    FcBool	enabled;
+    FcPtrList	*subst[FcMatchKindEnd];
+} FcRuleSet;
 
 typedef struct _FcCharLeaf {
     FcChar32	map[256/32];
@@ -374,6 +392,13 @@ typedef struct _FcStrBuf {
     FcChar8 buf_static[16 * sizeof (void *)];
 } FcStrBuf;
 
+typedef struct _FcHashTable	FcHashTable;
+
+typedef FcChar32 (* FcHashFunc)	   (const void *data);
+typedef int	 (* FcCompareFunc) (const void *v1, const void *v2);
+typedef FcBool	 (* FcCopyFunc)	   (const void *src, void **dest);
+
+
 struct _FcCache {
     unsigned int magic;              /* FC_CACHE_MAGIC_MMAP or FC_CACHE_ALLOC */
     int		version;	    /* FC_CACHE_VERSION_NUMBER */
@@ -477,12 +502,6 @@ struct _FcAtomic {
     FcChar8	*tmp;		/* tmpfile name (used for locking) */
 };
 
-struct _FcBlanks {
-    int		nblank;
-    int		sblank;
-    FcChar32	*blanks;
-};
-
 struct _FcConfig {
     /*
      * File names loaded from the configuration -- saved here as the
@@ -491,11 +510,6 @@ struct _FcConfig {
      */
     FcStrSet	*configDirs;	    /* directories to scan for fonts */
     /*
-     * Set of allowed blank chars -- used to
-     * trim fonts of bogus glyphs
-     */
-    FcBlanks	*blanks;
-    /*
      * List of directories containing fonts,
      * built by recursively scanning the set
      * of configured directories
@@ -514,10 +528,12 @@ struct _FcConfig {
      * Substitution instructions for patterns and fonts;
      * maxObjects is used to allocate appropriate intermediate storage
      * while performing a whole set of substitutions
+     *
+     * 0.. substitutions for patterns
+     * 1.. substitutions for fonts
+     * 2.. substitutions for scanned fonts
      */
-    FcSubst	*substPattern;	    /* substitutions for patterns */
-    FcSubst	*substFont;	    /* substitutions for fonts */
-    FcSubst	*substScan;	    /* substitutions for scanned fonts */
+    FcPtrList	*subst[FcMatchKindEnd];
     int		maxObjects;	    /* maximum number of tests in all substs */
     /*
      * List of patterns used to control font file selection
@@ -547,6 +563,9 @@ struct _FcConfig {
     FcExprPage  *expr_pool;	    /* pool of FcExpr's */
 
     FcChar8     *sysRoot;	    /* override the system root directory */
+    FcStrSet	*availConfigFiles;  /* config files available */
+    FcPtrList	*rulesetList;	    /* List of rulesets being installed */
+    FcHashTable *uuid_table;	    /* UUID table for cachedirs */
 };
 
 typedef struct _FcFileTime {
@@ -574,8 +593,6 @@ struct _FcValuePromotionBuffer {
   } u;
 };
 
-/* fcblanks.c */
-
 /* fccache.c */
 
 FcPrivate FcCache *
@@ -599,9 +616,13 @@ FcCacheObjectReference (void *object);
 FcPrivate void
 FcCacheObjectDereference (void *object);
 
+FcPrivate void *
+FcCacheAllocate (FcCache *cache, size_t len);
+
 FcPrivate void
 FcCacheFini (void);
 
+
 FcPrivate void
 FcDirCacheReference (FcCache *cache, int nref);
 
@@ -641,10 +662,6 @@ FcConfigAddFontDir (FcConfig	    *config
 		    const FcChar8   *d);
 
 FcPrivate FcBool
-FcConfigAddDir (FcConfig	*config,
-		const FcChar8	*d);
-
-FcPrivate FcBool
 FcConfigAddCacheDir (FcConfig	    *config,
 		     const FcChar8  *d);
 
@@ -694,7 +711,30 @@ FcConfigModifiedTime (FcConfig *config);
 
 FcPrivate FcBool
 FcConfigAddCache (FcConfig *config, FcCache *cache,
-		  FcSetName set, FcStrSet *dirSet);
+		  FcSetName set, FcStrSet *dirSet, FcChar8 *forDir);
+
+FcPrivate FcRuleSet *
+FcRuleSetCreate (const FcChar8 *name);
+
+FcPrivate void
+FcRuleSetDestroy (FcRuleSet *rs);
+
+FcPrivate void
+FcRuleSetReference (FcRuleSet *rs);
+
+FcPrivate void
+FcRuleSetEnable (FcRuleSet	*rs,
+		 FcBool		flag);
+
+FcPrivate void
+FcRuleSetAddDescription (FcRuleSet	*rs,
+			 const FcChar8	*domain,
+			 const FcChar8	*description);
+
+FcPrivate int
+FcRuleSetAdd (FcRuleSet		*rs,
+	      FcRule		*rule,
+	      FcMatchKind	kind);
 
 /* fcserialize.c */
 FcPrivate intptr_t
@@ -781,6 +821,11 @@ FcRandom (void);
 FcPrivate FcBool
 FcMakeDirectory (const FcChar8 *dir);
 
+FcPrivate ssize_t
+FcReadLink (const FcChar8 *pathname,
+	    FcChar8       *buf,
+	    size_t         bufsiz);
+
 /* fcdbg.c */
 
 FcPrivate void
@@ -811,7 +856,7 @@ FcPrivate void
 FcEditPrint (const FcEdit *edit);
 
 FcPrivate void
-FcSubstPrint (const FcSubst *subst);
+FcRulePrint (const FcRule *rule);
 
 FcPrivate void
 FcCharSetPrint (const FcCharSet *c);
@@ -847,14 +892,12 @@ FcFileIsFile (const FcChar8 *file);
 FcPrivate FcBool
 FcFileScanConfig (FcFontSet	*set,
 		  FcStrSet	*dirs,
-		  FcBlanks	*blanks,
 		  const FcChar8 *file,
 		  FcConfig	*config);
 
 FcPrivate FcBool
 FcDirScanConfig (FcFontSet	*set,
 		 FcStrSet	*dirs,
-		 FcBlanks	*blanks,
 		 const FcChar8	*dir,
 		 FcBool		force,
 		 FcConfig	*config);
@@ -874,6 +917,42 @@ FcFontSetSerialize (FcSerialize *seriali
 FcPrivate FcFontSet *
 FcFontSetDeserialize (const FcFontSet *set);
 
+/* fcplist.c */
+FcPrivate FcPtrList *
+FcPtrListCreate (FcDestroyFunc func);
+
+FcPrivate void
+FcPtrListDestroy (FcPtrList *list);
+
+FcPrivate void
+FcPtrListIterInit (const FcPtrList	*list,
+		   FcPtrListIter	*iter);
+
+FcPrivate void
+FcPtrListIterInitAtLast (FcPtrList	*list,
+			 FcPtrListIter	*iter);
+
+FcPrivate FcBool
+FcPtrListIterNext (const FcPtrList	*list,
+		   FcPtrListIter	*iter);
+
+FcPrivate FcBool
+FcPtrListIterIsValid (const FcPtrList		*list,
+		      const FcPtrListIter	*iter);
+
+FcPrivate void *
+FcPtrListIterGetValue (const FcPtrList		*list,
+		       const FcPtrListIter	*iter);
+
+FcPrivate FcBool
+FcPtrListIterAdd (FcPtrList	*list,
+		  FcPtrListIter	*iter,
+		void		*data);
+
+FcPrivate FcBool
+FcPtrListIterRemove (FcPtrList		*list,
+		     FcPtrListIter	*iter);
+
 /* fcinit.c */
 FcPrivate FcConfig *
 FcInitLoadOwnConfig (FcConfig *config);
@@ -914,6 +993,15 @@ FcNameUnparseLangSet (FcStrBuf *buf, con
 FcPrivate FcChar8 *
 FcNameUnparseEscaped (FcPattern *pat, FcBool escape);
 
+FcPrivate FcBool
+FcConfigParseOnly (FcConfig		*config,
+		   const FcChar8	*name,
+		   FcBool		complain);
+
+FcPrivate FcChar8 *
+FcConfigRealFilename (FcConfig		*config,
+		      const FcChar8	*url);
+
 /* fclist.c */
 
 FcPrivate FcBool
@@ -1000,6 +1088,9 @@ FcPrivate FcBool
 FcPatternObjectAddWeak (FcPattern *p, FcObject object, FcValue value, FcBool append);
 
 FcPrivate FcResult
+FcPatternObjectGetWithBinding (const FcPattern *p, FcObject object, int id, FcValue *v, FcValueBinding *b);
+
+FcPrivate FcResult
 FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v);
 
 FcPrivate FcBool
@@ -1062,6 +1153,18 @@ FcPatternAppend (FcPattern *p, FcPattern
 FcPrivate int
 FcPatternPosition (const FcPattern *p, const char *object);
 
+FcPrivate FcBool
+FcPatternFindObjectIter (const FcPattern *pat, FcPatternIter *iter, FcObject object);
+
+FcPrivate FcObject
+FcPatternIterGetObjectId (const FcPattern *pat, FcPatternIter *iter);
+
+FcPrivate FcValueListPtr
+FcPatternIterGetValues (const FcPattern *pat, FcPatternIter *iter);
+
+FcPrivate FcPattern *
+FcPatternCacheRewriteFile (const FcPattern *pat, FcCache *cache, const FcChar8 *relocated_font_file);
+
 FcPrivate FcChar32
 FcStringHash (const FcChar8 *s);
 
@@ -1176,6 +1279,9 @@ FcStrGlobMatch (const FcChar8 *glob,
 FcPrivate FcBool
 FcStrUsesHome (const FcChar8 *s);
 
+FcPrivate FcBool
+FcStrIsAbsoluteFilename (const FcChar8 *s);
+
 FcPrivate FcChar8 *
 FcStrBuildFilename (const FcChar8 *path,
 		    ...);
@@ -1215,4 +1321,46 @@ FcObjectLookupOtherTypeById (FcObject id
 FcPrivate const FcObjectType *
 FcObjectLookupOtherTypeByName (const char *str);
 
+/* fchash.c */
+FcPrivate FcBool
+FcHashStrCopy (const void  *src,
+	       void       **dest);
+
+FcPrivate FcBool
+FcHashUuidCopy (const void  *src,
+		void       **dest);
+
+FcPrivate void
+FcHashUuidFree (void *data);
+
+FcPrivate FcHashTable *
+FcHashTableCreate (FcHashFunc    hash_func,
+		   FcCompareFunc compare_func,
+		   FcCopyFunc    key_copy_func,
+		   FcCopyFunc    value_copy_func,
+		   FcDestroyFunc key_destroy_func,
+		   FcDestroyFunc value_destroy_func);
+
+FcPrivate void
+FcHashTableDestroy (FcHashTable *table);
+
+FcPrivate FcBool
+FcHashTableFind (FcHashTable  *table,
+		 const void   *key,
+		 void        **value);
+
+FcPrivate FcBool
+FcHashTableAdd (FcHashTable *table,
+		void        *key,
+		void        *value);
+
+FcPrivate FcBool
+FcHashTableReplace (FcHashTable *table,
+		    void        *key,
+		    void        *value);
+
+FcPrivate FcBool
+FcHashTableRemove (FcHashTable *table,
+		   void        *key);
+
 #endif /* _FC_INT_H_ */
Index: xsrc/external/mit/fontconfig/dist/src/fcname.c
diff -u xsrc/external/mit/fontconfig/dist/src/fcname.c:1.8 xsrc/external/mit/fontconfig/dist/src/fcname.c:1.9
--- xsrc/external/mit/fontconfig/dist/src/fcname.c:1.8	Tue Aug 29 08:38:50 2017
+++ xsrc/external/mit/fontconfig/dist/src/fcname.c	Fri Mar  8 09:49:07 2019
@@ -258,6 +258,11 @@ FcNameBool (const FcChar8 *v, FcBool *re
 	*result = FcFalse;
 	return FcTrue;
     }
+    if (c0 == 'd' || c0 == 'x' || c0 == '2')
+    {
+	*result = FcDontCare;
+	return FcTrue;
+    }
     if (c0 == 'o')
     {
 	c1 = v[1];
@@ -272,6 +277,11 @@ FcNameBool (const FcChar8 *v, FcBool *re
 	    *result = FcFalse;
 	    return FcTrue;
 	}
+	if (c1 == 'r')
+	{
+	    *result = FcDontCare;
+	    return FcTrue;
+	}
     }
     return FcFalse;
 }
@@ -318,15 +328,39 @@ FcNameConvert (FcType type, FcChar8 *str
 	    v.type = FcTypeVoid;
 	break;
     case FcTypeRange:
-	if (sscanf ((char *) string, "[%lg %lg)", &b, &e) != 2)
+	if (sscanf ((char *) string, "[%lg %lg]", &b, &e) != 2)
 	{
-	    v.u.d = strtod ((char *) string, &p);
-	    if (p != NULL && p[0] != 0)
+	    char *sc, *ec;
+	    size_t len = strlen ((const char *) string);
+	    int si, ei;
+
+	    sc = malloc (len + 1);
+	    ec = malloc (len + 1);
+	    if (sc && ec && sscanf ((char *) string, "[%s %[^]]]", sc, ec) == 2)
 	    {
-		v.type = FcTypeVoid;
-		break;
+		if (FcNameConstant ((const FcChar8 *) sc, &si) &&
+		    FcNameConstant ((const FcChar8 *) ec, &ei))
+		    v.u.r =  FcRangeCreateDouble (si, ei);
+		else
+		    goto bail1;
 	    }
-	    v.type = FcTypeDouble;
+	    else
+	    {
+	    bail1:
+		v.type = FcTypeDouble;
+		if (FcNameConstant (string, &si))
+		{
+		    v.u.d = (double) si;
+		} else {
+		    v.u.d = strtod ((char *) string, &p);
+		    if (p != NULL && p[0] != 0)
+			v.type = FcTypeVoid;
+		}
+	    }
+	    if (sc)
+		free (sc);
+	    if (ec)
+		free (ec);
 	}
 	else
 	    v.u.r = FcRangeCreateDouble (b, e);
@@ -456,6 +490,10 @@ FcNameParse (const FcChar8 *name)
 			if (!FcPatternAddBool (pat, c->object, c->value))
 			    goto bail2;
 			break;
+		    case FcTypeRange:
+			if (!FcPatternAddInteger (pat, c->object, c->value))
+			    goto bail2;
+			break;
 		    default:
 			break;
 		    }
@@ -514,7 +552,10 @@ FcNameUnparseValue (FcStrBuf	*buf,
     case FcTypeString:
 	return FcNameUnparseString (buf, v.u.s, escape);
     case FcTypeBool:
-	return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
+	return FcNameUnparseString (buf,
+				    v.u.b == FcTrue  ? (FcChar8 *) "True" :
+				    v.u.b == FcFalse ? (FcChar8 *) "False" :
+				                       (FcChar8 *) "DontCare", 0);
     case FcTypeMatrix:
 	sprintf ((char *) temp, "%g %g %g %g",
 		 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
@@ -526,7 +567,7 @@ FcNameUnparseValue (FcStrBuf	*buf,
     case FcTypeFTFace:
 	return FcTrue;
     case FcTypeRange:
-	sprintf ((char *) temp, "[%g %g)", v.u.r->begin, v.u.r->end);
+	sprintf ((char *) temp, "[%g %g]", v.u.r->begin, v.u.r->end);
 	return FcNameUnparseString (buf, temp, 0);
     }
     return FcFalse;
Index: xsrc/external/mit/fontconfig/dist/src/fcstat.c
diff -u xsrc/external/mit/fontconfig/dist/src/fcstat.c:1.8 xsrc/external/mit/fontconfig/dist/src/fcstat.c:1.9
--- xsrc/external/mit/fontconfig/dist/src/fcstat.c:1.8	Sun Jan 28 16:43:32 2018
+++ xsrc/external/mit/fontconfig/dist/src/fcstat.c	Fri Mar  8 09:49:07 2019
@@ -217,17 +217,23 @@ FcScandir (const char		*dirp,
 	{
 	    size_t dentlen = FcPtrToOffset (dent, dent->d_name) + strlen (dent->d_name) + 1;
 	    dentlen = ((dentlen + ALIGNOF_VOID_P - 1) & ~(ALIGNOF_VOID_P - 1));
-	    p = malloc (dentlen);
-	    if (!p) 
-		goto out;
+	    p = (struct dirent *) malloc (dentlen);
+	    if (!p)
+	    {
+		free_dirent (dlist);
+		closedir (d);
+		errno = ENOMEM;
+
+		return -1;
+	    }
 	    memcpy (p, dent, dentlen);
 	    if ((n + 1) >= lsize)
 	    {
 		lsize += 128;
-		dlp = realloc (dlist, sizeof (struct dirent *) * lsize);
+		dlp = (struct dirent **) realloc (dlist, sizeof (struct dirent *) * lsize);
 		if (!dlp)
 		{
-out:
+		    free (p);
 		    free_dirent (dlist);
 		    closedir (d);
 		    errno = ENOMEM;

Index: xsrc/external/mit/fontconfig/dist/src/fcmatch.c
diff -u xsrc/external/mit/fontconfig/dist/src/fcmatch.c:1.10 xsrc/external/mit/fontconfig/dist/src/fcmatch.c:1.11
--- xsrc/external/mit/fontconfig/dist/src/fcmatch.c:1.10	Sun Jan 28 16:44:15 2018
+++ xsrc/external/mit/fontconfig/dist/src/fcmatch.c	Fri Mar  8 09:49:07 2019
@@ -27,7 +27,7 @@
 
 
 static double
-FcCompareNumber (FcValue *value1, FcValue *value2)
+FcCompareNumber (const FcValue *value1, const FcValue *value2, FcValue *bestValue)
 {
     double  v1, v2, v;
 
@@ -54,23 +54,27 @@ FcCompareNumber (FcValue *value1, FcValu
     v = v2 - v1;
     if (v < 0)
 	v = -v;
+    *bestValue = FcValueCanonicalize (value2);
     return v;
 }
 
 static double
-FcCompareString (FcValue *v1, FcValue *v2)
+FcCompareString (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 {
+    *bestValue = FcValueCanonicalize (v2);
     return (double) FcStrCmpIgnoreCase (FcValueString(v1), FcValueString(v2)) != 0;
 }
 
 static double
-FcCompareFamily (FcValue *v1, FcValue *v2)
+FcCompareFamily (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 {
     /* rely on the guarantee in FcPatternObjectAddWithBinding that
      * families are always FcTypeString. */
     const FcChar8* v1_string = FcValueString(v1);
     const FcChar8* v2_string = FcValueString(v2);
 
+    *bestValue = FcValueCanonicalize (v2);
+
     if (FcToLower(*v1_string) != FcToLower(*v2_string) &&
 	*v1_string != ' ' && *v2_string != ' ')
        return 1.0;
@@ -79,13 +83,15 @@ FcCompareFamily (FcValue *v1, FcValue *v
 }
 
 static double
-FcComparePostScript (FcValue *v1, FcValue *v2)
+FcComparePostScript (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 {
     const FcChar8 *v1_string = FcValueString (v1);
     const FcChar8 *v2_string = FcValueString (v2);
     int n;
     size_t len;
 
+    *bestValue = FcValueCanonicalize (v2);
+
     if (FcToLower (*v1_string) != FcToLower (*v2_string) &&
 	*v1_string != ' ' && *v2_string != ' ')
 	return 1.0;
@@ -97,7 +103,7 @@ FcComparePostScript (FcValue *v1, FcValu
 }
 
 static double
-FcCompareLang (FcValue *v1, FcValue *v2)
+FcCompareLang (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 {
     FcLangResult    result;
     FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
@@ -132,6 +138,7 @@ FcCompareLang (FcValue *v1, FcValue *v2)
     default:
 	return -1.0;
     }
+    *bestValue = FcValueCanonicalize (v2);
     switch (result) {
     case FcLangEqual:
 	return 0;
@@ -144,99 +151,133 @@ FcCompareLang (FcValue *v1, FcValue *v2)
 }
 
 static double
-FcCompareBool (FcValue *v1, FcValue *v2)
+FcCompareBool (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 {
     if (v2->type != FcTypeBool || v1->type != FcTypeBool)
 	return -1.0;
-    return (double) v2->u.b != v1->u.b;
+
+    if (v2->u.b != FcDontCare)
+	*bestValue = FcValueCanonicalize (v2);
+    else
+	*bestValue = FcValueCanonicalize (v1);
+
+    return (double) ((v2->u.b ^ v1->u.b) == 1);
 }
 
 static double
-FcCompareCharSet (FcValue *v1, FcValue *v2)
+FcCompareCharSet (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 {
+    *bestValue = FcValueCanonicalize (v2); /* TODO Improve. */
     return (double) FcCharSetSubtractCount (FcValueCharSet(v1), FcValueCharSet(v2));
 }
 
 static double
-FcCompareSize (FcValue *value1, FcValue *value2)
+FcCompareRange (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 {
-    double  v1, v2, v;
+    FcValue value1 = FcValueCanonicalize (v1);
+    FcValue value2 = FcValueCanonicalize (v2);
+    double b1, e1, b2, e2, d;
 
-    switch ((int) value1->type) {
+    switch ((int) value1.type) {
     case FcTypeInteger:
-	v1 = value1->u.i;
+        b1 = e1 = value1.u.i;
 	break;
     case FcTypeDouble:
-	v1 = value1->u.d;
+        b1 = e1 = value1.u.d;
+	break;
+    case FcTypeRange:
+	b1 = value1.u.r->begin;
+	e1 = value1.u.r->end;
 	break;
     default:
 	return -1;
     }
-    switch ((int) value2->type) {
+    switch ((int) value2.type) {
     case FcTypeInteger:
-	v2 = value2->u.i;
+        b2 = e2 = value2.u.i;
 	break;
     case FcTypeDouble:
-	v2 = value2->u.d;
+        b2 = e2 = value2.u.d;
+	break;
+    case FcTypeRange:
+	b2 = value2.u.r->begin;
+	e2 = value2.u.r->end;
 	break;
     default:
 	return -1;
     }
-    if (v2 == 0)
-	return 0;
-    v = v2 - v1;
-    if (v < 0)
-	v = -v;
-    return v;
+
+    if (e1 < b2)
+      d = b2;
+    else if (e2 < b1)
+      d = e2;
+    else
+      d = (FC_MAX (b1, b2) + FC_MIN (e1, e2)) * .5;
+
+    bestValue->type = FcTypeDouble;
+    bestValue->u.d = d;
+
+    /* If the ranges overlap, it's a match, otherwise return closest distance. */
+    if (e1 < b2 || e2 < b1)
+	return FC_MIN (fabs (b2 - e1), fabs (b1 - e2));
+    else
+	return 0.0;
 }
 
 static double
-FcCompareSizeRange (FcValue *v1, FcValue *v2)
+FcCompareSize (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 {
     FcValue value1 = FcValueCanonicalize (v1);
     FcValue value2 = FcValueCanonicalize (v2);
-    FcRange *r1 = NULL, *r2 = NULL;
-    double ret = -1.0;
+    double b1, e1, b2, e2;
 
     switch ((int) value1.type) {
+    case FcTypeInteger:
+        b1 = e1 = value1.u.i;
+	break;
     case FcTypeDouble:
-	r1 = FcRangeCreateDouble (value1.u.d, value1.u.d);
+        b1 = e1 = value1.u.d;
 	break;
     case FcTypeRange:
-	r1 = FcRangeCopy (value1.u.r);
+	abort();
+	b1 = value1.u.r->begin;
+	e1 = value1.u.r->end;
 	break;
     default:
-	goto bail;
+	return -1;
     }
     switch ((int) value2.type) {
+    case FcTypeInteger:
+        b2 = e2 = value2.u.i;
+	break;
     case FcTypeDouble:
-	r2 = FcRangeCreateDouble (value2.u.d, value2.u.d);
+        b2 = e2 = value2.u.d;
 	break;
     case FcTypeRange:
-	r2 = FcRangeCopy (value2.u.r);
+	b2 = value2.u.r->begin;
+	e2 = value2.u.r->end;
 	break;
     default:
-	goto bail;
+	return -1;
     }
 
-    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);
+    bestValue->type = FcTypeDouble;
+    bestValue->u.d = (b1 + e1) * .5;
 
-    return ret;
+    /* If the ranges overlap, it's a match, otherwise return closest distance. */
+    if (e1 < b2 || e2 < b1)
+	return FC_MIN (fabs (b2 - e1), fabs (b1 - e2));
+    if (b2 != e2 && b1 == e2) /* Semi-closed interval. */
+        return 1e-15;
+    else
+	return 0.0;
 }
 
 static double
-FcCompareFilename (FcValue *v1, FcValue *v2)
+FcCompareFilename (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 {
     const FcChar8 *s1 = FcValueString (v1), *s2 = FcValueString (v2);
+    *bestValue = FcValueCanonicalize (v2);
     if (FcStrCmp (s1, s2) == 0)
 	return 0.0;
     else if (FcStrCmpIgnoreCase (s1, s2) == 0)
@@ -257,13 +298,13 @@ FcCompareFilename (FcValue *v1, FcValue 
 #define PRI_FcCompareFamily(n)		PRI1(n)
 #define PRI_FcCompareString(n)		PRI1(n)
 #define PRI_FcCompareNumber(n)		PRI1(n)
-#define PRI_FcCompareSize(n)		PRI1(n)
 #define PRI_FcCompareBool(n)		PRI1(n)
 #define PRI_FcCompareFilename(n)	PRI1(n)
 #define PRI_FcCompareCharSet(n)		PRI1(n)
 #define PRI_FcCompareLang(n)		PRI1(n)
 #define PRI_FcComparePostScript(n)	PRI1(n)
-#define PRI_FcCompareSizeRange(n)	PRI1(n)
+#define PRI_FcCompareRange(n)		PRI1(n)
+#define PRI_FcCompareSize(n)		PRI1(n)
 
 #define FC_OBJECT(NAME, Type, Cmp)	PRI_##Cmp(NAME)
 
@@ -285,6 +326,7 @@ typedef enum _FcMatcherPriorityDummy {
 typedef enum _FcMatcherPriority {
     PRI1(FILE),
     PRI1(FONTFORMAT),
+    PRI1(VARIABLE),
     PRI1(SCALABLE),
     PRI1(COLOR),
     PRI1(FOUNDRY),
@@ -314,7 +356,7 @@ typedef enum _FcMatcherPriority {
 
 typedef struct _FcMatcher {
     FcObject object;
-    double   (*compare) (FcValue *value1, FcValue *value2);
+    double   (*compare) (const FcValue *v1, const FcValue *v2, FcValue *bestValue);
     int      strong, weak;
 } FcMatcher;
 
@@ -384,7 +426,8 @@ FcCompareValueList (FcObject	     object
     {
 	for (v2 = v2orig, k = 0; v2; v2 = FcValueListNext(v2), k++)
 	{
-	    v = (match->compare) (&v1->value, &v2->value);
+	    FcValue matchValue;
+	    v = (match->compare) (&v1->value, &v2->value, &matchValue);
 	    if (v < 0)
 	    {
 		*result = FcResultTypeMismatch;
@@ -394,7 +437,7 @@ FcCompareValueList (FcObject	     object
 	    if (v < best)
 	    {
 		if (bestValue)
-		    *bestValue = FcValueCanonicalize(&v2->value);
+		    *bestValue = matchValue;
 		best = v;
 		pos = k;
 	    }
@@ -490,10 +533,17 @@ FcFontRenderPrepare (FcConfig	    *confi
     FcPatternElt    *fe, *pe;
     FcValue	    v;
     FcResult	    result;
+    FcBool	    variable = FcFalse;
+    FcStrBuf        variations;
 
     assert (pat != NULL);
     assert (font != NULL);
 
+    FcPatternObjectGetBool (font, FC_VARIABLE_OBJECT, 0, &variable);
+    assert (variable != FcDontCare);
+    if (variable)
+	FcStrBufInit (&variations, NULL, 0);
+
     new = FcPatternCreate ();
     if (!new)
 	return NULL;
@@ -598,6 +648,39 @@ FcFontRenderPrepare (FcConfig	    *confi
 		return NULL;
 	    }
 	    FcPatternObjectAdd (new, fe->object, v, FcFalse);
+
+	    /* Set font-variations settings for standard axes in variable fonts. */
+	    if (variable &&
+		FcPatternEltValues(fe)->value.type == FcTypeRange &&
+		(fe->object == FC_WEIGHT_OBJECT ||
+		 fe->object == FC_WIDTH_OBJECT ||
+		 fe->object == FC_SIZE_OBJECT))
+	    {
+		double num;
+		FcChar8 temp[128];
+		const char *tag = "    ";
+		assert (v.type == FcTypeDouble);
+		num = v.u.d;
+		if (variations.len)
+		    FcStrBufChar (&variations, ',');
+		switch (fe->object)
+		{
+		    case FC_WEIGHT_OBJECT:
+			tag = "wght";
+			num = FcWeightToOpenType (num);
+			break;
+
+		    case FC_WIDTH_OBJECT:
+			tag = "wdth";
+			break;
+
+		    case FC_SIZE_OBJECT:
+			tag = "opsz";
+			break;
+		}
+		sprintf ((char *) temp, "%4s=%g", tag, num);
+		FcStrBufString (&variations, temp);
+	    }
 	}
 	else
 	{
@@ -621,6 +704,20 @@ FcFontRenderPrepare (FcConfig	    *confi
 	}
     }
 
+    if (variable && variations.len)
+    {
+	FcChar8 *vars = NULL;
+	if (FcPatternObjectGetString (new, FC_FONT_VARIATIONS_OBJECT, 0, &vars) == FcResultMatch)
+	{
+	    FcStrBufChar (&variations, ',');
+	    FcStrBufString (&variations, vars);
+	    FcPatternObjectDel (new, FC_FONT_VARIATIONS_OBJECT);
+	}
+
+	FcPatternObjectAddString (new, FC_FONT_VARIATIONS_OBJECT, FcStrBufDoneStatic (&variations));
+	FcStrBufDestroy (&variations);
+    }
+
     FcConfigSubstituteWithPat (config, new, pat, FcMatchFont);
     return new;
 }
@@ -718,25 +815,21 @@ FcFontSetMatchInternal (FcFontSet   **se
 		if (!(p = strchr (s, ',')))
 		{
 		    f = FcFalse;
-		    len = strlen (s) + 1;
+		    len = strlen (s);
 		}
 		else
 		{
-		    len = (p - s) + 1;
+		    len = (p - s);
 		}
-		x = malloc (sizeof (char) * len);
-		if (x == NULL)
+		x = malloc (sizeof (char) * (len + 1));
+		if (x)
 		{
-			fprintf (stderr, "Fontconfig Error: %s\n",
-			    strerror (errno));
-			exit (1);
+		    strcpy (x, s);
+		    if (FcObjectFromName (x) > 0)
+			FcObjectSetAdd (os, x);
+		    s = p + 1;
+		    free (x);
 		}
-		strncpy (x, s, len - 1);
-		x[len - 1] = 0;
-		if (FcObjectFromName (x) > 0)
-		    FcObjectSetAdd (os, x);
-		s = p + 1;
-		free (x);
 	    }
 	    free (ss);
 	}
@@ -1031,7 +1124,8 @@ FcFontSetSort (FcConfig	    *config FC_U
 		    FcPatternGet (p, FC_LANG, i, &patternLang) == FcResultMatch &&
 		    FcPatternGet (nodeps[f]->pattern, FC_LANG, 0, &nodeLang) == FcResultMatch)
 		{
-		    double  compare = FcCompareLang (&patternLang, &nodeLang);
+		    FcValue matchValue;
+		    double  compare = FcCompareLang (&patternLang, &nodeLang, &matchValue);
 		    if (compare >= 0 && compare < 2)
 		    {
 			if (FcDebug () & FC_DBG_MATCHV)

Added files:

Index: xsrc/external/mit/fontconfig/dist/src/fchash.c
diff -u /dev/null xsrc/external/mit/fontconfig/dist/src/fchash.c:1.5
--- /dev/null	Fri Mar  8 09:49:08 2019
+++ xsrc/external/mit/fontconfig/dist/src/fchash.c	Fri Mar  8 09:49:07 2019
@@ -0,0 +1,249 @@
+/*
+ * Copyright © 2000 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the author(s) not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  The authors make no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "fcint.h"
+#if !defined TOOL_FCCACHE
+#ifndef _WIN32
+#include <uuid/uuid.h>
+#endif
+#endif
+
+#define FC_HASH_SIZE 227
+
+typedef struct _FcHashBucket {
+    struct _FcHashBucket  *next;
+    void                  *key;
+    void                  *value;
+} FcHashBucket;
+
+struct _FcHashTable {
+    FcHashBucket  *buckets[FC_HASH_SIZE];
+    FcHashFunc     hash_func;
+    FcCompareFunc  compare_func;
+    FcCopyFunc     key_copy_func;
+    FcCopyFunc     value_copy_func;
+    FcDestroyFunc  key_destroy_func;
+    FcDestroyFunc  value_destroy_func;
+};
+
+
+FcBool
+FcHashStrCopy (const void  *src,
+	       void       **dest)
+{
+    *dest = FcStrdup (src);
+
+    return *dest != NULL;
+}
+
+FcBool
+FcHashUuidCopy (const void  *src,
+		void       **dest)
+{
+#if !defined TOOL_FCCACHE
+#ifndef _WIN32
+    *dest = malloc (sizeof (uuid_t));
+    uuid_copy (*dest, src);
+#endif
+#endif
+    return FcTrue;
+}
+
+void
+FcHashUuidFree (void *data)
+{
+    free (data);
+}
+
+FcHashTable *
+FcHashTableCreate (FcHashFunc    hash_func,
+		   FcCompareFunc compare_func,
+		   FcCopyFunc    key_copy_func,
+		   FcCopyFunc    value_copy_func,
+		   FcDestroyFunc key_destroy_func,
+		   FcDestroyFunc value_destroy_func)
+{
+    FcHashTable *ret = malloc (sizeof (FcHashTable));
+
+    if (ret)
+    {
+	memset (ret->buckets, 0, sizeof (FcHashBucket *) * FC_HASH_SIZE);
+	ret->hash_func = hash_func;
+	ret->compare_func = compare_func;
+	ret->key_copy_func = key_copy_func;
+	ret->value_copy_func = value_copy_func;
+	ret->key_destroy_func = key_destroy_func;
+	ret->value_destroy_func = value_destroy_func;
+    }
+    return ret;
+}
+
+void
+FcHashTableDestroy (FcHashTable *table)
+{
+    int i;
+
+    for (i = 0; i < FC_HASH_SIZE; i++)
+    {
+	FcHashBucket *bucket = table->buckets[i], *prev;
+
+	while (bucket)
+	{
+	    if (table->key_destroy_func)
+		table->key_destroy_func (bucket->key);
+	    if (table->value_destroy_func)
+		table->value_destroy_func (bucket->value);
+	    prev = bucket;
+	    bucket = bucket->next;
+	    free (prev);
+	}
+	table->buckets[i] = NULL;
+    }
+    free (table);
+}
+
+FcBool
+FcHashTableFind (FcHashTable  *table,
+		 const void   *key,
+		 void        **value)
+{
+    FcHashBucket *bucket;
+    FcChar32 hash = table->hash_func (key);
+
+    for (bucket = table->buckets[hash % FC_HASH_SIZE]; bucket; bucket = bucket->next)
+    {
+	if (!table->compare_func(bucket->key, key))
+	{
+	    if (table->value_copy_func)
+	    {
+		if (!table->value_copy_func (bucket->value, value))
+		    return FcFalse;
+	    }
+	    else
+		*value = bucket->value;
+	    return FcTrue;
+	}
+    }
+    return FcFalse;
+}
+
+static FcBool
+FcHashTableAddInternal (FcHashTable *table,
+			void        *key,
+			void        *value,
+			FcBool       replace)
+{
+    FcHashBucket **prev, *bucket, *b;
+    FcChar32 hash = table->hash_func (key);
+    FcBool ret = FcFalse;
+
+    bucket = (FcHashBucket *) malloc (sizeof (FcHashBucket));
+    if (!bucket)
+	return FcFalse;
+    memset (bucket, 0, sizeof (FcHashBucket));
+    if (table->key_copy_func)
+	ret |= !table->key_copy_func (key, &bucket->key);
+    else
+	bucket->key = key;
+    if (table->value_copy_func)
+	ret |= !table->value_copy_func (value, &bucket->value);
+    else
+	bucket->value = value;
+    if (ret)
+    {
+    destroy:
+	if (bucket->key && table->key_destroy_func)
+	    table->key_destroy_func (bucket->key);
+	if (bucket->value && table->value_destroy_func)
+	    table->value_destroy_func (bucket->value);
+	free (bucket);
+
+	return !ret;
+    }
+  retry:
+    for (prev = &table->buckets[hash % FC_HASH_SIZE];
+	 (b = fc_atomic_ptr_get (prev)); prev = &(b->next))
+    {
+	if (!table->compare_func (b->key, key))
+	{
+	    if (replace)
+	    {
+		bucket->next = b->next;
+		if (!fc_atomic_ptr_cmpexch (prev, b, bucket))
+		    goto retry;
+		bucket = b;
+	    }
+	    else
+		ret = FcTrue;
+	    goto destroy;
+	}
+    }
+    bucket->next = NULL;
+    if (!fc_atomic_ptr_cmpexch (prev, b, bucket))
+	goto retry;
+
+    return FcTrue;
+}
+
+FcBool
+FcHashTableAdd (FcHashTable *table,
+		void        *key,
+		void        *value)
+{
+    return FcHashTableAddInternal (table, key, value, FcFalse);
+}
+
+FcBool
+FcHashTableReplace (FcHashTable *table,
+		    void        *key,
+		    void        *value)
+{
+    return FcHashTableAddInternal (table, key, value, FcTrue);
+}
+
+FcBool
+FcHashTableRemove (FcHashTable *table,
+		   void        *key)
+{
+    FcHashBucket **prev, *bucket;
+    FcChar32 hash = table->hash_func (key);
+    FcBool ret = FcFalse;
+
+retry:
+    for (prev = &table->buckets[hash % FC_HASH_SIZE];
+	 (bucket = fc_atomic_ptr_get (prev)); prev = &(bucket->next))
+    {
+	if (!table->compare_func (bucket->key, key))
+	{
+	    if (!fc_atomic_ptr_cmpexch (prev, bucket, bucket->next))
+		goto retry;
+	    if (table->key_destroy_func)
+		table->key_destroy_func (bucket->key);
+	    if (table->value_destroy_func)
+		table->value_destroy_func (bucket->value);
+	    free (bucket);
+	    ret = FcTrue;
+	    break;
+	}
+    }
+
+    return ret;
+}

Reply via email to