fontconfig: Branch 'master' - 45 commits

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 conf.d/90-synthetic.conf |    6 
 fc-list/fc-list.c        |   24 +
 fc-match/fc-match.c      |   20 -
 fc-query/fc-query.c      |   39 +-
 fc-scan/fc-scan.c        |   17 -
 fontconfig/fcfreetype.h  |    2 
 fontconfig/fontconfig.h  |    9 
 src/fccfg.c              |   20 +
 src/fcdbg.c              |    7 
 src/fcdefault.c          |   10 
 src/fcfreetype.c         |  765 +++++++++++++++++++++++++++++------------------
 src/fclang.c             |    6 
 src/fcmatch.c            |  143 +++++---
 src/fcname.c             |   19 -
 src/fcobjs.h             |   10 
 src/fcpat.c              |    3 
 src/fcrange.c            |   13 
 17 files changed, 720 insertions(+), 393 deletions(-)

New commits:
commit 1580593ecca1db4b4f06d87c38bb52eeeb533b1d
Merge: 052115a 01f781a
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Thu Sep 28 14:52:41 2017 -0400

    Merge branch 'varfonts2'
    
    https://lists.freedesktop.org/archives/fontconfig/2017-September/006048.html

commit 01f781a9a44c98b9c1330caeb388545db8fe0bb2
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 27 18:55:50 2017 -0400

    [varfonts] Share lang across named-instances
    
    Makes VotoSerifGX scanning another 40% faster...  Down to 36ms now.

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 4c7d7bd..cddd3a1 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1189,7 +1189,8 @@ static FcPattern *
 FcFreeTypeQueryFaceInternal (const FT_Face  face,
 			     const FcChar8  *file,
 			     unsigned int   id,
-			     FcCharSet      *cs)
+			     FcCharSet      **cs_share,
+			     FcLangSet      **ls_share)
 {
     FcPattern	    *pat;
     int		    slant = -1;
@@ -1200,7 +1201,8 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
     FcBool	    variable_weight = FcFalse;
     FcBool	    variable_width = FcFalse;
     FcBool	    variable_size = FcFalse;
-    FcLangSet	    *ls;
+    FcCharSet       *cs;
+    FcLangSet       *ls;
 #if 0
     FcChar8	    *family = 0;
 #endif
@@ -1938,10 +1940,14 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
     /*
      * Compute the unicode coverage for the font
      */
-    if (cs)
-	cs = FcCharSetCopy (cs);
+    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;
 
@@ -1985,7 +1991,14 @@ FcFreeTypeQueryFaceInternal (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;
     }
@@ -2061,7 +2074,7 @@ FcFreeTypeQueryFace (const FT_Face  face,
 		     unsigned int   id,
 		     FcBlanks	    *blanks FC_UNUSED)
 {
-    return FcFreeTypeQueryFaceInternal (face, file, id, NULL);
+    return FcFreeTypeQueryFaceInternal (face, file, id, NULL, NULL);
 }
 
 FcPattern *
@@ -2083,7 +2096,7 @@ FcFreeTypeQuery(const FcChar8	*file,
     if (count)
       *count = face->num_faces;
 
-    pat = FcFreeTypeQueryFaceInternal (face, file, id, NULL);
+    pat = FcFreeTypeQueryFaceInternal (face, file, id, NULL, NULL);
 
     FT_Done_Face (face);
 bail:
@@ -2101,6 +2114,7 @@ FcFreeTypeQueryAll(const FcChar8	*file,
     FT_Face face = NULL;
     FT_Library ftLibrary = NULL;
     FcCharSet *cs = NULL;
+    FcLangSet *ls = NULL;
     FT_MM_Var *mm_var = NULL;
     FcBool index_set = id != (unsigned int) -1;
     unsigned int set_face_num = index_set ? id & 0xFFFF : 0;
@@ -2120,7 +2134,6 @@ FcFreeTypeQueryAll(const FcChar8	*file,
 
     if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
 	goto bail;
-    cs = FcFreeTypeCharSet (face, blanks);
 
     num_faces = face->num_faces;
     num_instances = face->style_flags >> 16;
@@ -2160,7 +2173,7 @@ FcFreeTypeQueryAll(const FcChar8	*file,
 	}
 
 	id = ((instance_num << 16) + face_num);
-	pat = FcFreeTypeQueryFaceInternal (face, (const FcChar8 *) file, id, cs);
+	pat = FcFreeTypeQueryFaceInternal (face, (const FcChar8 *) file, id, &cs, &ls);
 
 	if (pat)
 	{
@@ -2179,6 +2192,8 @@ skip:
 	    instance_num = 0x8000; /* variable font */
 	else
 	{
+	    FcLangSetDestroy (ls);
+	    ls = NULL;
 	    FcCharSetDestroy (cs);
 	    cs = NULL;
 	    FT_Done_Face (face);
@@ -2189,11 +2204,11 @@ skip:
 
 	    if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
 	      break;
-	    cs = FcFreeTypeCharSet (face, blanks);
 	}
     } while (!err && (!index_set || face_num == set_face_num) && face_num < num_faces);
 
 bail:
+    FcLangSetDestroy (ls);
     FcCharSetDestroy (cs);
     if (face)
 	FT_Done_Face (face);
diff --git a/src/fclang.c b/src/fclang.c
index 107addb..eadf34b 100644
--- a/src/fclang.c
+++ b/src/fclang.c
@@ -485,6 +485,9 @@ FcLangSetCreate (void)
 void
 FcLangSetDestroy (FcLangSet *ls)
 {
+    if (!ls)
+	return;
+
     if (ls->extra)
 	FcStrSetDestroy (ls->extra);
     free (ls);
@@ -495,6 +498,9 @@ FcLangSetCopy (const FcLangSet *ls)
 {
     FcLangSet	*new;
 
+    if (!ls)
+	return NULL;
+
     new = FcLangSetCreate ();
     if (!new)
 	goto bail0;
diff --git a/src/fcpat.c b/src/fcpat.c
index cc303c6..dd1307d 100644
--- a/src/fcpat.c
+++ b/src/fcpat.c
@@ -1113,6 +1113,9 @@ FcPatternDuplicate (const FcPattern *orig)
     int		    i;
     FcValueListPtr  l;
 
+    if (!orig)
+	return NULL;
+
     new = FcPatternCreate ();
     if (!new)
 	goto bail0;
commit 161c7385477b9520fc4c63e3f09789d217c5cd67
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 27 18:36:25 2017 -0400

    Use binary-search for finding name table entries
    
    VotoSerifGX has over 500 named instances, which means it also has over a thousand
    name table entries.  So we were looking for names for over 500 pattern, looking for
    some thirty different name-ids, and using linear search across the 1000 entries!
    
    Makes scanning VotoSerifGX three times faster.  The rest is probably the lang
    matching, which can also be shared across named-instances.  Upcoming.

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 8021035..4c7d7bd 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1159,6 +1159,32 @@ static const FT_UShort nameid_order[] = {
 
 #define NUM_NAMEID_ORDER  (sizeof (nameid_order) / sizeof (nameid_order[0]))
 
+static FcBool
+FcFreeTypeGetName (const FT_Face face,
+		   unsigned int  platform,
+		   unsigned int  nameid,
+		   FT_SfntName   *sname)
+{
+    int min = 0, max = (int) FT_Get_Sfnt_Name_Count (face) - 1;
+
+    while (min <= max)
+    {
+	int mid = (min + max) / 2;
+
+	if (FT_Get_Sfnt_Name (face, mid, sname) != 0)
+	    return FcFalse;
+
+	if (platform < sname->platform_id || (platform == sname->platform_id && nameid < sname->name_id))
+	    max = mid - 1;
+	else if (platform > sname->platform_id || (platform == sname->platform_id && nameid > sname->name_id))
+	    min = mid + 1;
+	else
+	    return FcTrue;
+    }
+
+    return FcFalse;
+}
+
 static FcPattern *
 FcFreeTypeQueryFaceInternal (const FT_Face  face,
 			     const FcChar8  *file,
@@ -1197,8 +1223,6 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 #endif
     TT_Header	    *head;
     const FcChar8   *exclusiveLang = 0;
-    FT_SfntName	    sname;
-    FT_UInt    	    snamei, snamec;
 
     int		    nfamily = 0;
     int		    nfamily_lang = 0;
@@ -1207,7 +1231,6 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
     int		    nfullname = 0;
     int		    nfullname_lang = 0;
     unsigned int    p, n;
-    int		    platform, nameid;
 
     FcChar8	    *style = 0;
     int		    st;
@@ -1369,10 +1392,9 @@ FcFreeTypeQueryFaceInternal (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++)
     {
-	platform = platform_order[p];
+	int platform = platform_order[p];
 
 	/*
 	 * Order nameids so preferred names appear first
@@ -1380,149 +1402,142 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 	 */
 	for (n = 0; n < NUM_NAMEID_ORDER; n++)
 	{
-	    nameid = nameid_order[n];
+	    FT_SfntName sname;
+	    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++)
-	    {
-		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)
+	    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;
 
-		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 (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)
-		    continue;
+		if (nameid == TT_NAME_ID_FONT_SUBFAMILY)
+		    lookupid = instance->strid;
+	    }
 
-		if (sname.platform_id != platform)
-		    continue;
+	    if (!FcFreeTypeGetName (face, platform, lookupid, &sname))
+		continue;
 
-		switch (sname.name_id) {
+	    switch (nameid) {
 #ifdef TT_NAME_ID_WWS_FAMILY
-		case TT_NAME_ID_WWS_FAMILY:
+	    case TT_NAME_ID_WWS_FAMILY:
 #endif
-		case TT_NAME_ID_PREFERRED_FAMILY:
-		case TT_NAME_ID_FONT_FAMILY:
+	    case TT_NAME_ID_PREFERRED_FAMILY:
+	    case TT_NAME_ID_FONT_FAMILY:
 #if 0	
-		case TT_NAME_ID_UNIQUE_ID:
+	    case TT_NAME_ID_UNIQUE_ID:
 #endif
-		    if (FcDebug () & FC_DBG_SCANV)
-			printf ("found family (n %2d p %d e %d l 0x%04x)",
-				sname.name_id, sname.platform_id,
-				sname.encoding_id, sname.language_id);
-
-		    elt = FC_FAMILY;
-		    eltlang = FC_FAMILYLANG;
-		    np = &nfamily;
-		    nlangp = &nfamily_lang;
-		    break;
-		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)",
-				sname.name_id, sname.platform_id,
-				sname.encoding_id, sname.language_id);
-
-		    elt = FC_FULLNAME;
-		    eltlang = FC_FULLNAMELANG;
-		    np = &nfullname;
-		    nlangp = &nfullname_lang;
-		    break;
+		if (FcDebug () & FC_DBG_SCANV)
+		    printf ("found family (n %2d p %d e %d l 0x%04x)",
+			    sname.name_id, sname.platform_id,
+			    sname.encoding_id, sname.language_id);
+
+		elt = FC_FAMILY;
+		eltlang = FC_FAMILYLANG;
+		np = &nfamily;
+		nlangp = &nfamily_lang;
+		break;
+	    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)",
+			    sname.name_id, sname.platform_id,
+			    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:
+	    case TT_NAME_ID_WWS_SUBFAMILY:
 #endif
-		case TT_NAME_ID_PREFERRED_SUBFAMILY:
-		case TT_NAME_ID_FONT_SUBFAMILY:
-		    if (variable)
-			break;
-		    if (FcDebug () & FC_DBG_SCANV)
-			printf ("found style  (n %2d p %d e %d l 0x%04x) ",
-				sname.name_id, sname.platform_id,
-				sname.encoding_id, sname.language_id);
-
-		    elt = FC_STYLE;
-		    eltlang = FC_STYLELANG;
-		    np = &nstyle;
-		    nlangp = &nstyle_lang;
-		    break;
-		case TT_NAME_ID_TRADEMARK:
-		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);
-		    }
+	    case TT_NAME_ID_PREFERRED_SUBFAMILY:
+	    case TT_NAME_ID_FONT_SUBFAMILY:
+		if (variable)
 		    break;
-		}
-		if (elt)
+		if (FcDebug () & FC_DBG_SCANV)
+		    printf ("found style  (n %2d p %d e %d l 0x%04x) ",
+			    sname.name_id, sname.platform_id,
+			    sname.encoding_id, sname.language_id);
+
+		elt = FC_STYLE;
+		eltlang = FC_STYLELANG;
+		np = &nstyle;
+		nlangp = &nstyle_lang;
+		break;
+	    case TT_NAME_ID_TRADEMARK:
+	    case TT_NAME_ID_MANUFACTURER:
+		/* If the foundry wasn't found in the OS/2 table, look here */
+		if(!foundry)
 		{
-		    FcChar8		*utf8, *pp;
-
+		    FcChar8 *utf8;
 		    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);
-			continue;
-		    }
+		    foundry = FcNoticeFoundry((FT_String *) utf8);
+		    free (utf8);
+		}
+		break;
+	    }
+	    if (elt)
+	    {
+		FcChar8		*utf8, *pp;
 
-		    /* add new element */
-		    if (!FcPatternAddString (pat, elt, utf8))
-		    {
-			free (utf8);
-			goto bail1;
-		    }
+		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);
+		    continue;
+		}
+
+		/* add new element */
+		if (!FcPatternAddString (pat, elt, utf8))
+		{
 		    free (utf8);
-		    if (lang)
+		    goto bail1;
+		}
+		free (utf8);
+		if (lang)
+		{
+		    /* pad lang list with 'und' to line up with elt */
+		    while (*nlangp < *np)
 		    {
-			/* pad lang list with 'und' to line up with elt */
-			while (*nlangp < *np)
-			{
-			    if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "und"))
-				goto bail1;
-			    ++*nlangp;
-			}
-			if (!FcPatternAddString (pat, eltlang, lang))
+			if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "und"))
 			    goto bail1;
 			++*nlangp;
 		    }
-		    ++*np;
+		    if (!FcPatternAddString (pat, eltlang, lang))
+			goto bail1;
+		    ++*nlangp;
 		}
+		++*np;
 	    }
 	}
     }
commit 261464e0e2b0348187448fd86cde7d1e36124fc6
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 27 18:09:31 2017 -0400

    Simplify name-table platform mathcing logic
    
    There's no "all other platforms", there was just ISO left.
    Hardcode it in.

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index e203c75..8021035 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1136,6 +1136,7 @@ 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]))
 
@@ -1369,12 +1370,9 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
      * of them
      */
     snamec = FT_Get_Sfnt_Name_Count (face);
-    for (p = 0; p <= NUM_PLATFORM_ORDER; p++)
+    for (p = 0; p < NUM_PLATFORM_ORDER; p++)
     {
-	if (p < NUM_PLATFORM_ORDER)
-	    platform = platform_order[p];
-	else
-	    platform = 0xffff;
+	platform = platform_order[p];
 
 	/*
 	 * Order nameids so preferred names appear first
@@ -1410,25 +1408,8 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 		if (sname.name_id != nameid)
 		    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;
-		}
+		if (sname.platform_id != platform)
+		    continue;
 
 		switch (sname.name_id) {
 #ifdef TT_NAME_ID_WWS_FAMILY
commit 55d04e25d613b0b63b2b2c33affb6fae34a0ca01
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 27 16:54:24 2017 -0400

    Don't convert nameds to UTF-8 unless we are going to use them

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 5e930dc..e203c75 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1386,7 +1386,6 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 
 	    for (snamei = 0; snamei < snamec; snamei++)
 	    {
-		FcChar8		*utf8, *pp;
 		const FcChar8	*lang;
 		const char	*elt = 0, *eltlang = 0;
 		int		*np = 0, *nlangp = 0;
@@ -1430,11 +1429,6 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 		    if (sp != NUM_PLATFORM_ORDER)
 			continue;
 		}
-		utf8 = FcSfntNameTranscode (&sname);
-		lang = FcSfntNameLanguage (&sname);
-
-		if (!utf8)
-		    continue;
 
 		switch (sname.name_id) {
 #ifdef TT_NAME_ID_WWS_FAMILY
@@ -1446,10 +1440,9 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 		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;
@@ -1459,10 +1452,9 @@ FcFreeTypeQueryFaceInternal (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;
@@ -1477,10 +1469,9 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 		    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;
@@ -1491,11 +1482,27 @@ FcFreeTypeQueryFaceInternal (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 == ' ')
@@ -1535,8 +1542,6 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 		    }
 		    ++*np;
 		}
-		else
-		    free (utf8);
 	    }
 	}
     }
commit f99278112d01d77a4b396ab04616bdb4ade21d88
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 27 16:50:59 2017 -0400

    Whitespace

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index dfa268b..5e930dc 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1497,15 +1497,15 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 		if (elt)
 		{
 		    /* 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;
+		    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))
 		    {
commit 554041d59679d99e9c5ba0a01c3fa743eef7bd7f
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 27 16:50:30 2017 -0400

    Fix whitespace-trimming loop and empty strings...

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 6ff717a..dfa268b 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1502,10 +1502,10 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 			    pp++;
 			len = strlen ((const char *) pp);
 			memmove (utf8, pp, len + 1);
-			pp = utf8 + len - 1;
-			while (*pp == ' ')
+			pp = utf8 + len;
+			while (pp > utf8 && *(pp - 1) == ' ')
 			    pp--;
-			*(pp + 1) = 0;
+			*pp = 0;
 
 		    if (FcStringInPatternElement (pat, elt, utf8))
 		    {
commit a74109a1142a1525a310f95cb44931de545e025f
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 27 16:49:24 2017 -0400

    Move whitespace-trimming code to apply to all name-table strings
    
    If it's good, it's good for everything!

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 4787936..6ff717a 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1476,18 +1476,6 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 		case TT_NAME_ID_FONT_SUBFAMILY:
 		    if (variable)
 			break;
-		    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 (FcDebug () & FC_DBG_SCANV)
 			printf ("found style  (n %2d p %d e %d l 0x%04x) %s\n",
 				sname.name_id, sname.platform_id,
@@ -1508,6 +1496,17 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
 		}
 		if (elt)
 		{
+		    /* Trim surrounding whitespace. */
+			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 (FcStringInPatternElement (pat, elt, utf8))
 		    {
 			free (utf8);
commit 869dfe0bdc5efbaca6baf093eeeb9ac3d18c66e7
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 27 16:26:47 2017 -0400

    [varfonts] Reuse charset for named instances
    
    This didn't give me the speedup I was hoping for, though I do get around 15% for VotoSerifGX.

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index e809865..4787936 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -558,6 +558,9 @@ static const FcMacRomanFake fcMacRomanFake[] = {
 static FcChar8 *
 FcFontCapabilities(FT_Face face);
 
+static int
+FcFreeTypeSpacing (FT_Face face);
+
 #define NUM_FC_MAC_ROMAN_FAKE	(int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
 
 
@@ -1154,11 +1157,12 @@ 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,
-		     unsigned int   id,
-		     FcBlanks	    *blanks FC_UNUSED)
+
+static FcPattern *
+FcFreeTypeQueryFaceInternal (const FT_Face  face,
+			     const FcChar8  *file,
+			     unsigned int   id,
+			     FcCharSet      *cs)
 {
     FcPattern	    *pat;
     int		    slant = -1;
@@ -1169,7 +1173,6 @@ FcFreeTypeQueryFace (const FT_Face  face,
     FcBool	    variable_weight = FcFalse;
     FcBool	    variable_width = FcFalse;
     FcBool	    variable_size = FcFalse;
-    FcCharSet	    *cs;
     FcLangSet	    *ls;
 #if 0
     FcChar8	    *family = 0;
@@ -1935,15 +1938,19 @@ FcFreeTypeQueryFace (const FT_Face  face,
     /*
      * Compute the unicode coverage for the font
      */
-    cs = FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
+    if (cs)
+	cs = FcCharSetCopy (cs);
+    else
+	cs = FcFreeTypeCharSet (face, NULL);
     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 */
@@ -2049,9 +2056,18 @@ bail0:
 }
 
 FcPattern *
+FcFreeTypeQueryFace (const FT_Face  face,
+		     const FcChar8  *file,
+		     unsigned int   id,
+		     FcBlanks	    *blanks FC_UNUSED)
+{
+    return FcFreeTypeQueryFaceInternal (face, file, id, NULL);
+}
+
+FcPattern *
 FcFreeTypeQuery(const FcChar8	*file,
 		unsigned int	id,
-		FcBlanks	*blanks,
+		FcBlanks	*blanks FC_UNUSED,
 		int		*count)
 {
     FT_Face	    face;
@@ -2067,7 +2083,7 @@ FcFreeTypeQuery(const FcChar8	*file,
     if (count)
       *count = face->num_faces;
 
-    pat = FcFreeTypeQueryFace (face, file, id, blanks);
+    pat = FcFreeTypeQueryFaceInternal (face, file, id, NULL);
 
     FT_Done_Face (face);
 bail:
@@ -2084,6 +2100,7 @@ FcFreeTypeQueryAll(const FcChar8	*file,
 {
     FT_Face face = NULL;
     FT_Library ftLibrary = NULL;
+    FcCharSet *cs = NULL;
     FT_MM_Var *mm_var = NULL;
     FcBool index_set = id != (unsigned int) -1;
     unsigned int set_face_num = index_set ? id & 0xFFFF : 0;
@@ -2103,6 +2120,7 @@ FcFreeTypeQueryAll(const FcChar8	*file,
 
     if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
 	goto bail;
+    cs = FcFreeTypeCharSet (face, blanks);
 
     num_faces = face->num_faces;
     num_instances = face->style_flags >> 16;
@@ -2142,7 +2160,7 @@ FcFreeTypeQueryAll(const FcChar8	*file,
 	}
 
 	id = ((instance_num << 16) + face_num);
-	pat = FcFreeTypeQueryFace (face, (const FcChar8 *) file, id, blanks);
+	pat = FcFreeTypeQueryFaceInternal (face, (const FcChar8 *) file, id, cs);
 
 	if (pat)
 	{
@@ -2161,6 +2179,8 @@ skip:
 	    instance_num = 0x8000; /* variable font */
 	else
 	{
+	    FcCharSetDestroy (cs);
+	    cs = NULL;
 	    FT_Done_Face (face);
 	    face = NULL;
 
@@ -2169,10 +2189,12 @@ skip:
 
 	    if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
 	      break;
+	    cs = FcFreeTypeCharSet (face, blanks);
 	}
     } while (!err && (!index_set || face_num == set_face_num) && face_num < num_faces);
 
 bail:
+    FcCharSetDestroy (cs);
     if (face)
 	FT_Done_Face (face);
     FT_Done_FreeType (ftLibrary);
commit bf4d440e7f02f36de37b205092144b335bc40854
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 27 12:31:03 2017 -0400

    Separate charset and spacing code
    
    For variable-font named-instances we want to reuse the same charset and redo the spacing.

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index d8aab73..e809865 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -2263,18 +2263,13 @@ 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)); }
 
-FcCharSet *
-FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spacing)
+static int
+FcFreeTypeSpacing (FT_Face face)
 {
-    FcCharSet	    *fcs;
-    int		    o;
     FT_Int	    load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
     FT_Pos	    advances[3] = {};
-    unsigned int    num_advances = spacing ? 0 : 3;
-
-    fcs = FcCharSetCreate ();
-    if (!fcs)
-	goto bail0;
+    unsigned int    num_advances = 0;
+    int		    o;
 
     /* When using scalable fonts, only report those glyphs
      * which can be scaled; otherwise those fonts will
@@ -2299,18 +2294,65 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spac
 		strike_index = i;
 	}
 
-	if (FT_Select_Size (face, strike_index) != FT_Err_Ok)
-	    goto bail1;
+	FT_Select_Size (face, strike_index);
     }
 #endif
 
+    for (o = 0; o < NUM_DECODE; o++)
+    {
+	FcChar32        ucs4;
+	FT_UInt	 	glyph;
+
+	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;
+    }
+
+    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;
+}
+
+FcCharSet *
+FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks FC_UNUSED)
+{
+    const FT_Int    load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+    FcCharSet	    *fcs;
+    int		    o;
+
+    fcs = FcCharSetCreate ();
+    if (!fcs)
+	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;
+	FcChar32        page, off, ucs4;
+	FcCharLeaf      *leaf;
 	FT_UInt	 	glyph;
 
 	if (FT_Select_Charmap (face, fcFontEncodings[o]) != 0)
@@ -2335,26 +2377,13 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spac
 
 	    if (good)
 	    {
-		if (num_advances < 3)
-		{
-		    FT_Pos advance = 0;
-		    if (!FT_Get_Advance (face, glyph, load_flags, &advance) && advance)
-		    {
-			unsigned int i;
-			for (i = 0; i < num_advances; i++)
-			  if (fc_approximately_equal (advance, advances[i]))
-			    break;
-			if (i == num_advances)
-			  advances[num_advances++] = advance;
-		    }
-		}
-
+		FcCharSetAddChar (fcs, ucs4);
 		if ((ucs4 >> 8) != page)
 		{
 		    page = (ucs4 >> 8);
 		    leaf = FcCharSetFindLeafCreate (fcs, ucs4);
 		    if (!leaf)
-			goto bail1;
+			goto bail;
 		}
 		off = ucs4 & 0xff;
 		leaf->map[off >> 5] |= (1 << (off & 0x1f));
@@ -2395,29 +2424,20 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spac
 	break;
     }
 
-    if (spacing)
-    {
-      if (num_advances <= 1)
-	  *spacing = FC_MONO;
-      else if (num_advances == 2 &&
-	       fc_approximately_equal (fc_min (advances[0], advances[1]) * 2,
-				       fc_max (advances[0], advances[1])))
-	  *spacing = FC_DUAL;
-      else
-	  *spacing = FC_PROPORTIONAL;
-    }
-
     return fcs;
-bail1:
+bail:
     FcCharSetDestroy (fcs);
-bail0:
     return 0;
 }
 
 FcCharSet *
-FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks FC_UNUSED)
+FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spacing)
 {
-    return FcFreeTypeCharSetAndSpacing (face, blanks, NULL);
+
+    if (spacing)
+	*spacing = FcFreeTypeSpacing (face);
+
+    return FcFreeTypeCharSet (face, blanks);
 }
 
 
commit 15b5016ccdf236e51caf2480749d534a7f4b9eda
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 20 19:39:59 2017 -0700

    [varfonts] Don't reopen face for each named instance
    
    Makes scanning of Voto (over 500 named instaces) twice faster.
    
    Next, avoid charset / lang recalculation for each of those.

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index ed9ebb1..d8aab73 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -2082,8 +2082,9 @@ FcFreeTypeQueryAll(const FcChar8	*file,
 		   int			*count,
 		   FcFontSet            *set)
 {
-    FT_Face face;
+    FT_Face face = NULL;
     FT_Library ftLibrary = 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;
@@ -2094,75 +2095,86 @@ FcFreeTypeQueryAll(const FcChar8	*file,
     unsigned int ret = 0;
     int err = 0;
 
+    if (count)
+	*count = 0;
+
     if (FT_Init_FreeType (&ftLibrary))
 	return 0;
 
-    do {
-	FcPattern *pat;
+    if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
+	goto bail;
 
-	id = ((instance_num << 16) + face_num);
-	if (FT_New_Face (ftLibrary, (const char *) file, id & 0x7FFFFFFF, &face))
-	  break;
+    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);
+	assert (mm_var);
+    }
 
-	num_faces = face->num_faces;
-	num_instances = face->style_flags >> 16;
-	pat = FcFreeTypeQueryFace (face, (const FcChar8 *) file, id, blanks);
+    if (count)
+      *count = num_faces;
 
-	if (pat)
+    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)
 	{
-	    /* Skip named-instance that coincides with base instance. */
-	    if (!index_set && instance_num && instance_num != 0x8000)
-	    {
-		unsigned int i;
-		FT_MM_Var *mm_var = NULL;
-		FT_Fixed *coords = NULL;
+	    FT_Var_Named_Style *instance = &mm_var->namedstyle[instance_num - 1];
+	    FT_Fixed *coords = instance->coords;
+	    FcBool nonzero;
+	    unsigned int i;
 
-		if (FT_Get_MM_Var (face, &mm_var) ||
-		    !(coords = (FT_Fixed *) calloc (mm_var->num_axis, sizeof (FT_Fixed))) ||
-		    FT_Get_Var_Blend_Coordinates (face, mm_var->num_axis, coords))
+	    /* 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)
 		{
-		    goto skip;
+		    nonzero = FcTrue;
+		    break;
 		}
+	    if (!nonzero)
+		goto skip;
 
-		for (i = 0; i < mm_var->num_axis; i++)
-		    if (coords[i])
-			goto good;
+	    FT_Set_Var_Design_Coordinates (face, mm_var->num_axis, coords);
+	}
 
-skip:
-		free (coords);
-		FcPatternDestroy (pat);
-		pat = NULL;
-good:
-		;
-	    }
+	id = ((instance_num << 16) + face_num);
+	pat = FcFreeTypeQueryFace (face, (const FcChar8 *) file, id, blanks);
 
-	    if (pat)
-	    {
-		ret++;
-		if (!set || ! FcFontSetAdd (set, pat))
-		    FcPatternDestroy (pat);
-	    }
+	if (pat)
+	{
+
+	    ret++;
+	    if (!set || ! FcFontSetAdd (set, pat))
+		FcPatternDestroy (pat);
 	}
 	else if (instance_num != 0x8000)
 	    err = 1;
 
-	FT_Done_Face (face);
-	face = NULL;
-
-	if (!set_instance_num && instance_num < num_instances)
+skip:
+	if (!index_set && instance_num < num_instances)
 	    instance_num++;
-	else if (!set_instance_num && instance_num == num_instances)
+	else if (!index_set && instance_num == num_instances)
 	    instance_num = 0x8000; /* variable font */
 	else
 	{
+	    FT_Done_Face (face);
+	    face = NULL;
+
 	    face_num++;
 	    instance_num = set_instance_num;
+
+	    if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
+	      break;
 	}
     } while (!err && (!index_set || face_num == set_face_num) && face_num < num_faces);
 
-    if (count)
-      *count = num_faces;
-
+bail:
+    if (face)
+	FT_Done_Face (face);
     FT_Done_FreeType (ftLibrary);
 
     return ret;
commit 2d0063948a446a24ed9b74b5b5a4eb1004b1db8e
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 20 16:25:06 2017 -0700

    [varfonts] Do not set postscriptname for varfont pattern

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 1a67b82..ed9ebb1 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1207,8 +1207,6 @@ FcFreeTypeQueryFace (const FT_Face  face,
 
     FcChar8	    *style = 0;
     int		    st;
-    char	    psname[256];
-    const char	    *tmp;
 
     FcBool	    symbol = FcFalse;
 
@@ -1595,52 +1593,57 @@ FcFreeTypeQueryFace (const FT_Face  face,
     }
 
     /* Add the PostScript name into the cache */
-    tmp = FT_Get_Postscript_Name (face);
-    if (!tmp)
+    if (!variable)
     {
-	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)
+	char	    psname[256];
+	const char	    *tmp;
+	tmp = FT_Get_Postscript_Name (face);
+	if (!tmp)
 	{
-	    if (FcStrCmp (familylang, (const FcChar8 *)"en") == 0)
-		break;
-	    n++;
-	    familylang = NULL;
-	}
-	if (!familylang)
-	    n = 0;
+	    unsigned int i;
+	    FcChar8 *family, *familylang = NULL;
+	    size_t len;
+	    int 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 ";
+	    /* 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 (strchr(exclusive_chars, family[i]) != NULL)
-		psname[i] = '-';
-	    else
-		psname[i] = family[i];
+	    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];
+	    }
+	    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;
commit be735d6a6870dde8879ce08b8927bf224b2614a0
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 20 16:21:28 2017 -0700

    [varfonts] Skip named-instance that is equivalent to base font

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 8154174..1a67b82 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -2089,7 +2089,7 @@ FcFreeTypeQueryAll(const FcChar8	*file,
     unsigned int num_faces = 0;
     unsigned int num_instances = 0;
     unsigned int ret = 0;
-    int		err = 0;
+    int err = 0;
 
     if (FT_Init_FreeType (&ftLibrary))
 	return 0;
@@ -2104,17 +2104,48 @@ FcFreeTypeQueryAll(const FcChar8	*file,
 	num_faces = face->num_faces;
 	num_instances = face->style_flags >> 16;
 	pat = FcFreeTypeQueryFace (face, (const FcChar8 *) file, id, blanks);
-	FT_Done_Face (face);
 
 	if (pat)
 	{
-	    ret++;
-	    if (!set || ! FcFontSetAdd (set, pat))
-	      FcPatternDestroy (pat);
+	    /* Skip named-instance that coincides with base instance. */
+	    if (!index_set && instance_num && instance_num != 0x8000)
+	    {
+		unsigned int i;
+		FT_MM_Var *mm_var = NULL;
+		FT_Fixed *coords = NULL;
+
+		if (FT_Get_MM_Var (face, &mm_var) ||
+		    !(coords = (FT_Fixed *) calloc (mm_var->num_axis, sizeof (FT_Fixed))) ||
+		    FT_Get_Var_Blend_Coordinates (face, mm_var->num_axis, coords))
+		{
+		    goto skip;
+		}
+
+		for (i = 0; i < mm_var->num_axis; i++)
+		    if (coords[i])
+			goto good;
+
+skip:
+		free (coords);
+		FcPatternDestroy (pat);
+		pat = NULL;
+good:
+		;
+	    }
+
+	    if (pat)
+	    {
+		ret++;
+		if (!set || ! FcFontSetAdd (set, pat))
+		    FcPatternDestroy (pat);
+	    }
 	}
 	else if (instance_num != 0x8000)
 	    err = 1;
 
+	FT_Done_Face (face);
+	face = NULL;
+
 	if (!set_instance_num && instance_num < num_instances)
 	    instance_num++;
 	else if (!set_instance_num && instance_num == num_instances)
commit 8183194ae39c43708e60458e94faf73d55b4ec4a
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Mon Sep 18 20:14:33 2017 -0400

    [varfonts] Don't set style for variable-font pattern

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index f1bc809..8154174 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1473,6 +1473,8 @@ FcFreeTypeQueryFace (const FT_Face  face,
 #endif
 		case TT_NAME_ID_PREFERRED_SUBFAMILY:
 		case TT_NAME_ID_FONT_SUBFAMILY:
+		    if (variable)
+			break;
 		    if (utf8)
 		    {
 			pp = utf8;
@@ -1551,7 +1553,7 @@ 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)
commit 131219f9e54fe576c986f80aecc3b1d92c27bb09
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Mon Sep 18 19:27:24 2017 -0400

    [varfonts] Comment

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 0cf3e1f..f1bc809 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1396,8 +1396,9 @@ FcFreeTypeQueryFace (const FT_Face  face,
 
 		if (instance)
 		{
-		    /* For named-instances, we regular style nameIDs,
-		     * and map the instance's strid to FONT_SUBFAMILY. */
+		    /* 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 (sname.name_id == TT_NAME_ID_WWS_SUBFAMILY ||
 			sname.name_id == TT_NAME_ID_PREFERRED_SUBFAMILY ||
 			sname.name_id == TT_NAME_ID_FONT_SUBFAMILY)
@@ -1555,6 +1556,7 @@ FcFreeTypeQueryFace (const FT_Face  face,
     {
 	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"))
commit e85afde2d68574eda904e934ba2e484647606bf4
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Mon Sep 18 15:04:21 2017 -0400

    [varfonts] Minor

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 616da19..0cf3e1f 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1264,21 +1264,21 @@ FcFreeTypeQueryFace (const FT_Face  face,
 		  elt = FC_WEIGHT;
 		  min_value = FcWeightFromOpenType (min_value);
 		  max_value = FcWeightFromOpenType (max_value);
-		  variable = variable_weight = FcTrue;
+		  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 = variable_width = FcTrue;
+		  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 = variable_size = FcTrue;
+		  variable_size = FcTrue;
 		  break;
 	      }
 
@@ -1291,6 +1291,7 @@ FcFreeTypeQueryFace (const FT_Face  face,
 		      goto bail1;
 		  }
 		  FcRangeDestroy (r);
+		  variable = FcTrue;
 	      }
 	  }
 
commit 5ee9c38df7708dfc544973fb7617231eb314b9b9
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Mon Sep 18 15:03:36 2017 -0400

    Revert "[varfonts] Use fvar data even if there's no variation in it"
    
    This reverts commit 57764e3a36449da25bb829c34cb08c54e9e5de90.
    
    For regular font pattern we don't look into fvar, so it doesn't make sense to
    get non-variation from it either.

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index c7984f3..616da19 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1255,7 +1255,7 @@ FcFreeTypeQueryFace (const FT_Face  face,
 	      double max_value = master->axis[i].maximum / (double) (1 << 16);
 	      const char *elt = NULL;
 
-	      if (min_value > def_value || def_value > max_value)
+	      if (min_value > def_value || def_value > max_value || min_value == max_value)
 		  continue;
 
 	      switch (master->axis[i].tag)
@@ -1264,42 +1264,33 @@ FcFreeTypeQueryFace (const FT_Face  face,
 		  elt = FC_WEIGHT;
 		  min_value = FcWeightFromOpenType (min_value);
 		  max_value = FcWeightFromOpenType (max_value);
-		  variable_weight = FcTrue;
+		  variable = 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;
+		  variable = 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;
+		  variable = variable_size = FcTrue;
 		  break;
 	      }
 
 	      if (elt)
 	      {
-		  if (min_value == max_value)
+		  FcRange *r = FcRangeCreateDouble (min_value, max_value);
+		  if (!FcPatternAddRange (pat, elt, r))
 		  {
-		      if (!FcPatternAddDouble (pat, elt, min_value))
-			  goto bail1;
-		  }
-		  else
-		  {
-		      FcRange *r = FcRangeCreateDouble (min_value, max_value);
-		      if (!FcPatternAddRange (pat, elt, r))
-		      {
-			  FcRangeDestroy (r);
-			  goto bail1;
-		      }
 		      FcRangeDestroy (r);
-		      variable = FcTrue;
+		      goto bail1;
 		  }
+		  FcRangeDestroy (r);
 	      }
 	  }
 
commit 7e1b84100d9fff3409a8c3d1b800911bd0643761
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Mon Sep 18 14:53:24 2017 -0400

    Minor

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 0b5127f..c7984f3 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1764,13 +1764,21 @@ FcFreeTypeQueryFace (const FT_Face  face,
 	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
 
commit 01f14de4172f4853c2ca05586aeb073edf560ef4
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Mon Sep 18 14:52:17 2017 -0400

    [varfonts] Use fvar data even if there's no variation in it

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index ac12c1e..0b5127f 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1255,7 +1255,7 @@ FcFreeTypeQueryFace (const FT_Face  face,
 	      double max_value = master->axis[i].maximum / (double) (1 << 16);
 	      const char *elt = NULL;
 
-	      if (min_value > def_value || def_value > max_value || min_value == max_value)
+	      if (min_value > def_value || def_value > max_value)
 		  continue;
 
 	      switch (master->axis[i].tag)
@@ -1264,33 +1264,42 @@ FcFreeTypeQueryFace (const FT_Face  face,
 		  elt = FC_WEIGHT;
 		  min_value = FcWeightFromOpenType (min_value);
 		  max_value = FcWeightFromOpenType (max_value);
-		  variable = variable_weight = FcTrue;
+		  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 = variable_width = FcTrue;
+		  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 = variable_size = FcTrue;
+		  variable_size = FcTrue;
 		  break;
 	      }
 
 	      if (elt)
 	      {
-		  FcRange *r = FcRangeCreateDouble (min_value, max_value);
-		  if (!FcPatternAddRange (pat, elt, r))
+		  if (min_value == max_value)
 		  {
+		      if (!FcPatternAddDouble (pat, elt, min_value))
+			  goto bail1;
+		  }
+		  else
+		  {
+		      FcRange *r = FcRangeCreateDouble (min_value, max_value);
+		      if (!FcPatternAddRange (pat, elt, r))
+		      {
+			  FcRangeDestroy (r);
+			  goto bail1;
+		      }
 		      FcRangeDestroy (r);
-		      goto bail1;
+		      variable = FcTrue;
 		  }
-		  FcRangeDestroy (r);
 	      }
 	  }
 
commit 38a6d6fba0c9d5a189ec706a1df4ceb639c83bd1
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Mon Sep 18 14:33:37 2017 -0400

    Fix possible div-by-zero

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index cf1e196..ac12c1e 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1310,7 +1310,7 @@ FcFreeTypeQueryFace (const FT_Face  face,
 	  {
 	      double value = instance->coords[i] / (double) (1 << 16);
 	      double default_value = master->axis[i].def / (double) (1 << 16);
-	      double mult = value / default_value;
+	      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)
 	      {
commit 0ed241cb3047b0a8ab1949d7ac68e7159fe0984d
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Mon Sep 18 14:59:49 2017 -0400

    Implement more config bool operations for boolean types
    
    Meh.

diff --git a/src/fccfg.c b/src/fccfg.c
index e5bc04c..4b22d48 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -808,6 +808,18 @@ FcConfigCompareValue (const FcValue	*left_o,
 	    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;
 	    }
commit 2544bc5343d84a1f7e793cdae3569150b0ec3d05
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Sat Sep 16 13:45:02 2017 -0400

    Add FcDontCare value to FcBool
    
    This can be used for FC_VARIABLE=FcDontCare for example, to opt into getting
    variable fonts for clients that support using them.

diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index 56091ac..0f4dcb9 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -72,8 +72,9 @@ typedef int		FcBool;
 #define _FC_STRINGIFY(s)    	_FC_STRINGIFY_(s)
 #define FC_CACHE_VERSION    	_FC_STRINGIFY(FC_CACHE_VERSION_NUMBER)
 
-#define FcTrue		1
 #define FcFalse		0
+#define FcTrue		1
+#define FcDontCare	2
 
 #define FC_FAMILY	    "family"		/* String */
 #define FC_STYLE	    "style"		/* String */
diff --git a/src/fccfg.c b/src/fccfg.c
index 4f38af1..e5bc04c 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -796,14 +796,18 @@ FcConfigCompareValue (const FcValue	*left_o,
 	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;
 	    default:
 		break;
 	    }
diff --git a/src/fcdbg.c b/src/fcdbg.c
index 40e0d66..29ff44a 100644
--- a/src/fcdbg.c
+++ b/src/fcdbg.c
@@ -46,7 +46,10 @@ _FcValuePrintFile (FILE *f, const FcValue v)
 	fprintf (f, "\"%s\"", v.u.s);
 	break;
     case FcTypeBool:
-	fprintf (f, "%s", v.u.b ? "True" : "False");
+	fprintf (f,
+		 v.u.b == FcTrue  ? (FcChar8 *) "True" :
+		 v.u.b == FcFalse ? (FcChar8 *) "False" :
+				    (FcChar8 *) "DontCare", 0);
 	break;
     case FcTypeMatrix:
 	fprintf (f, "[%g %g; %g %g]", v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
diff --git a/src/fcmatch.c b/src/fcmatch.c
index f217539..d5eaea7 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -154,8 +154,12 @@ FcCompareBool (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
     if (v2->type != FcTypeBool || v1->type != FcTypeBool)
 	return -1.0;
 
-    *bestValue = FcValueCanonicalize (v2);
-    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
diff --git a/src/fcname.c b/src/fcname.c
index 77e74bc..79e413e 100644
--- a/src/fcname.c
+++ b/src/fcname.c
@@ -258,6 +258,11 @@ FcNameBool (const FcChar8 *v, FcBool *result)
 	*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 *result)
 	    *result = FcFalse;
 	    return FcTrue;
 	}
+	if (c1 == 'r')
+	{
+	    *result = FcDontCare;
+	    return FcTrue;
+	}
     }
     return FcFalse;
 }
@@ -514,7 +524,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);
commit c2fcde498a8b7dec012a8da8ffa78f72a65ac50d
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Fri Sep 15 15:03:46 2017 -0400

    [varfonts] Map from OpenType to Fontconfig weight values
    
    Oops.

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 0d03208..cf1e196 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1262,18 +1262,22 @@ FcFreeTypeQueryFace (const FT_Face  face,
 	      {
 		case FT_MAKE_TAG ('w','g','h','t'):
 		  elt = FC_WEIGHT;
+		  min_value = FcWeightFromOpenType (min_value);
+		  max_value = FcWeightFromOpenType (max_value);
 		  variable = 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 = 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 = variable_size = FcTrue;
 		  break;
 	      }
commit 9efe0689ae130eda75a66ecd853cbe63712378a3
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Fri Sep 15 14:28:12 2017 -0400

    Adjust emboldening logic
    
    Old logic was really bad.  If you requested weight=102 and got a medium
    font (weight=100), it would still enable emboldening...
    
    Adjust it to only embolden if request was >= bold and font was <= regular.

diff --git a/conf.d/90-synthetic.conf b/conf.d/90-synthetic.conf
index b8d1e85..7cd25cf 100644
--- a/conf.d/90-synthetic.conf
+++ b/conf.d/90-synthetic.conf
@@ -40,11 +40,11 @@
 	<match target="font">
 		<!-- check to see if the font is just regular -->
 		<test name="weight" compare="less_eq">
-			<const>medium</const>
+			<const>regular</const>
 		</test>
 		<!-- check to see if the pattern requests bold -->
-		<test target="pattern" name="weight" compare="more">
-			<const>medium</const>
+		<test target="pattern" name="weight" compare="more_eq">
+			<const>bold</const>
 		</test>
 		<!--
 		  set the embolden flag
commit a79f367c3f8b238fecced75e02c956e565af2597
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Fri Sep 15 14:26:17 2017 -0400

    Fix range comparision operators implementation

diff --git a/src/fcrange.c b/src/fcrange.c
index f70226c..8689930 100644
--- a/src/fcrange.c
+++ b/src/fcrange.c
@@ -96,9 +96,6 @@ FcRangePromote (double v, FcValuePromotionBuffer *vbuf)
 FcBool
 FcRangeIsInRange (const FcRange *a, const FcRange *b)
 {
-    if (!a || !b)
-	return FcFalse;
-
     return a->begin >= b->begin && a->end <= b->end;
 }
 
@@ -107,20 +104,22 @@ FcRangeCompare (FcOp op, const FcRange *a, const FcRange *b)
 {
     switch ((int) op) {
     case FcOpEqual:
+	return a->begin == b->begin && a->end == b->end;
     case FcOpContains:
     case FcOpListing:
 	return FcRangeIsInRange (a, b);
     case FcOpNotEqual:
+	return a->begin != b->begin || a->end != b->end;
     case FcOpNotContains:
 	return !FcRangeIsInRange (a, b);
     case FcOpLess:
-	return a->begin < b->begin;
+	return a->end < b->begin;
     case FcOpLessEqual:
-	return a->begin <= b->begin;
+	return a->end <= b->begin;
     case FcOpMore:
-	return a->end > b->end;
+	return a->begin > b->end;
     case FcOpMoreEqual:
-	return a->end >= b->end;
+	return a->begin >= b->end;
     default:
 	break;
     }
commit 5bbdffd2c2efcf684ae787bfad9d154b2fe05fb4
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Fri Sep 15 01:51:46 2017 -0400

    Add separate match compare function for size
    
    Has two distinctions from FcCompareRange():
    1. As best value, it returns query pattern size, even if it's out of font range,
    2. Implements semi-closed interval, as that's what OS/2 v5 table defines

diff --git a/src/fcmatch.c b/src/fcmatch.c
index 03a4e5f..f217539 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -220,6 +220,55 @@ FcCompareRange (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 }
 
 static double
+FcCompareSize (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
+{
+    FcValue value1 = FcValueCanonicalize (v1);
+    FcValue value2 = FcValueCanonicalize (v2);
+    double b1, e1, b2, e2;
+
+    switch ((int) value1.type) {
+    case FcTypeInteger:
+        b1 = e1 = value1.u.i;
+	break;
+    case FcTypeDouble:
+        b1 = e1 = value1.u.d;
+	break;
+    case FcTypeRange:
+	abort();
+	b1 = value1.u.r->begin;
+	e1 = value1.u.r->end;
+	break;
+    default:
+	return -1;
+    }
+    switch ((int) value2.type) {
+    case FcTypeInteger:
+        b2 = e2 = value2.u.i;
+	break;
+    case FcTypeDouble:
+        b2 = e2 = value2.u.d;
+	break;
+    case FcTypeRange:
+	b2 = value2.u.r->begin;
+	e2 = value2.u.r->end;
+	break;
+    default:
+	return -1;
+    }
+
+    bestValue->type = FcTypeDouble;
+    bestValue->u.d = (b1 + e1) * .5;
+
+    /* 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 (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 {
     const FcChar8 *s1 = FcValueString (v1), *s2 = FcValueString (v2);
@@ -250,6 +299,7 @@ FcCompareFilename (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 #define PRI_FcCompareLang(n)		PRI1(n)
 #define PRI_FcComparePostScript(n)	PRI1(n)
 #define PRI_FcCompareRange(n)		PRI1(n)
+#define PRI_FcCompareSize(n)		PRI1(n)
 
 #define FC_OBJECT(NAME, Type, Cmp)	PRI_##Cmp(NAME)
 
diff --git a/src/fcobjs.h b/src/fcobjs.h
index 8101594..e3926cc 100644
--- a/src/fcobjs.h
+++ b/src/fcobjs.h
@@ -31,7 +31,7 @@ FC_OBJECT (FULLNAMELANG,	FcTypeString,	NULL)
 FC_OBJECT (SLANT,		FcTypeInteger,	FcCompareNumber)
 FC_OBJECT (WEIGHT,		FcTypeRange,	FcCompareRange)
 FC_OBJECT (WIDTH,		FcTypeRange,	FcCompareRange)
-FC_OBJECT (SIZE,		FcTypeRange,	FcCompareRange)
+FC_OBJECT (SIZE,		FcTypeRange,	FcCompareSize)
 FC_OBJECT (ASPECT,		FcTypeDouble,	NULL)
 FC_OBJECT (PIXEL_SIZE,		FcTypeDouble,	FcCompareNumber)
 FC_OBJECT (SPACING,		FcTypeInteger,	FcCompareNumber)
commit 2a41738fd7c88e2b6977673f91bdb8d1f7224cf1
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Fri Sep 15 01:11:34 2017 -0400

    [fc-match/fc-list/fc-query/fc-scan] Add --brief that is like --verbose without charset

diff --git a/fc-list/fc-list.c b/fc-list/fc-list.c
index f6c7282..95963e7 100644
--- a/fc-list/fc-list.c
+++ b/fc-list/fc-list.c
@@ -49,6 +49,7 @@
 #include <getopt.h>
 const struct option longopts[] = {
     {"verbose", 0, 0, 'v'},
+    {"brief", 0, 0, 'b'},
     {"format", 1, 0, 'f'},
     {"quiet", 0, 0, 'q'},
     {"version", 0, 0, 'V'},
@@ -67,22 +68,24 @@ usage (char *program, int error)
 {
     FILE *file = error ? stderr : stdout;
 #if HAVE_GETOPT_LONG
-    fprintf (file, "usage: %s [-vqVh] [-f FORMAT] [--verbose] [--format=FORMAT] [--quiet] [--version] [--help] [pattern] {element ...} \n",
+    fprintf (file, "usage: %s [-vbqVh] [-f FORMAT] [--verbose] [--brief] [--format=FORMAT] [--quiet] [--version] [--help] [pattern] {element ...} \n",
 	     program);
 #else
-    fprintf (file, "usage: %s [-vqVh] [-f FORMAT] [pattern] {element ...} \n",
+    fprintf (file, "usage: %s [-vbqVh] [-f FORMAT] [pattern] {element ...} \n",
 	     program);
 #endif
     fprintf (file, "List fonts matching [pattern]\n");
     fprintf (file, "\n");
 #if HAVE_GETOPT_LONG
     fprintf (file, "  -v, --verbose        display entire font pattern verbosely\n");
+    fprintf (file, "  -b, --brief          display entire font pattern briefly\n");
     fprintf (file, "  -f, --format=FORMAT  use the given output format\n");
     fprintf (file, "  -q, --quiet          suppress all normal output, exit 1 if no fonts matched\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, "  -v         (verbose) display entire font pattern verbosely\n");
+    fprintf (file, "  -b         (brief)   display entire font pattern briefly\n");
     fprintf (file, "  -f FORMAT  (format)  use the given output format\n");
     fprintf (file, "  -q,        (quiet)   suppress all normal output, exit 1 if no fonts matched\n");
     fprintf (file, "  -V         (version) display font config version and exit\n");
@@ -95,6 +98,7 @@ int
 main (int argc, char **argv)
 {
     int			verbose = 0;
+    int			brief = 0;
     int			quiet = 0;
     const FcChar8	*format = NULL;
     int			nfont = 0;
@@ -106,15 +110,18 @@ main (int argc, char **argv)
     int			c;
 
 #if HAVE_GETOPT_LONG
-    while ((c = getopt_long (argc, argv, "vf:qVh", longopts, NULL)) != -1)
+    while ((c = getopt_long (argc, argv, "vbf:qVh", longopts, NULL)) != -1)
 #else
-    while ((c = getopt (argc, argv, "vf:qVh")) != -1)
+    while ((c = getopt (argc, argv, "vbf:qVh")) != -1)
 #endif
     {
 	switch (c) {
 	case 'v':
 	    verbose = 1;
 	    break;
+	case 'b':
+	    brief = 1;
+	    break;
 	case 'f':
 	    format = (FcChar8 *) strdup (optarg);
 	    break;
@@ -155,7 +162,7 @@ main (int argc, char **argv)
 	pat = FcPatternCreate ();
     if (quiet && !os)
 	os = FcObjectSetCreate ();
-    if (!verbose && !format && !os)
+    if (!verbose && !brief && !format && !os)
 	os = FcObjectSetBuild (FC_FAMILY, FC_STYLE, FC_FILE, (char *) 0);
     if (!format)
         format = (const FcChar8 *) "%{=fclist}\n";
@@ -171,8 +178,13 @@ main (int argc, char **argv)
 
 	for (j = 0; j < fs->nfont; j++)
 	{
-	    if (verbose)
+	    if (verbose || brief)
 	    {
+		if (brief)
+		{
+		    FcPatternDel (fs->fonts[j], FC_CHARSET);
+		    FcPatternDel (fs->fonts[j], FC_LANG);
+		}
 		FcPatternPrint (fs->fonts[j]);
 	    }
 	    else
diff --git a/fc-match/fc-match.c b/fc-match/fc-match.c
index f96c009..88f4ac8 100644
--- a/fc-match/fc-match.c
+++ b/fc-match/fc-match.c
@@ -52,6 +52,7 @@ static const struct option longopts[] = {
     {"sort", 0, 0, 's'},
     {"all", 0, 0, 'a'},
     {"verbose", 0, 0, 'v'},
+    {"brief", 0, 0, 'b'},
     {"format", 1, 0, 'f'},
     {"version", 0, 0, 'V'},
     {"help", 0, 0, 'h'},
@@ -69,7 +70,7 @@ usage (char *program, int error)
 {
     FILE *file = error ? stderr : stdout;
 #if HAVE_GETOPT_LONG
-    fprintf (file, "usage: %s [-savVh] [-f FORMAT] [--sort] [--all] [--verbose] [--format=FORMAT] [--version] [--help] [pattern] {element...}\n",
+    fprintf (file, "usage: %s [-savbVh] [-f FORMAT] [--sort] [--all] [--verbose] [--brief] [--format=FORMAT] [--version] [--help] [pattern] {element...}\n",
 	     program);
 #else
     fprintf (file, "usage: %s [-savVh] [-f FORMAT] [pattern] {element...}\n",
@@ -81,6 +82,7 @@ usage (char *program, int error)
     fprintf (file, "  -s, --sort           display sorted list of matches\n");
     fprintf (file, "  -a, --all            display unpruned sorted list of matches\n");
     fprintf (file, "  -v, --verbose        display entire font pattern verbosely\n");
+    fprintf (file, "  -b, --brief          display entire font pattern briefly\n");
     fprintf (file, "  -f, --format=FORMAT  use the given output format\n");
     fprintf (file, "  -V, --version        display font config version and exit\n");
     fprintf (file, "  -h, --help           display this help and exit\n");
@@ -88,6 +90,7 @@ usage (char *program, int error)
     fprintf (file, "  -s,        (sort)    display sorted list of matches\n");
     fprintf (file, "  -a         (all)     display unpruned sorted list of matches\n");
     fprintf (file, "  -v         (verbose) display entire font pattern verbosely\n");
+    fprintf (file, "  -b         (brief)   display entire font pattern briefly\n");
     fprintf (file, "  -f FORMAT  (format)  use the given output format\n");
     fprintf (file, "  -V         (version) display font config version and exit\n");
     fprintf (file, "  -h         (help)    display this help and exit\n");
@@ -99,6 +102,7 @@ int
 main (int argc, char **argv)
 {
     int			verbose = 0;
+    int			brief = 0;
     int			sort = 0, all = 0;
     const FcChar8	*format = NULL;
     int			i;
@@ -110,9 +114,9 @@ main (int argc, char **argv)
     int			c;
 
 #if HAVE_GETOPT_LONG
-    while ((c = getopt_long (argc, argv, "asvf:Vh", longopts, NULL)) != -1)
+    while ((c = getopt_long (argc, argv, "asvbf:Vh", longopts, NULL)) != -1)
 #else
-    while ((c = getopt (argc, argv, "asvf:Vh")) != -1)
+    while ((c = getopt (argc, argv, "asvbf:Vh")) != -1)
 #endif
     {
 	switch (c) {
@@ -125,6 +129,9 @@ main (int argc, char **argv)
 	case 'v':
 	    verbose = 1;
 	    break;
+	case 'b':
+	    brief = 1;
+	    break;
 	case 'f':
 	    format = (FcChar8 *) strdup (optarg);
 	    break;
@@ -218,8 +225,13 @@ main (int argc, char **argv)
 
 	    font = FcPatternFilter (fs->fonts[j], os);
 
-	    if (verbose)
+	    if (verbose || brief)
 	    {
+		if (brief)
+		{
+		    FcPatternDel (font, FC_CHARSET);
+		    FcPatternDel (font, FC_LANG);
+		}
 		FcPatternPrint (font);
 	    }
 	    else
diff --git a/fc-query/fc-query.c b/fc-query/fc-query.c
index 9c9900b..8a96da0 100644
--- a/fc-query/fc-query.c
+++ b/fc-query/fc-query.c
@@ -53,6 +53,7 @@
 #include <getopt.h>
 static const struct option longopts[] = {
     {"index", 1, 0, 'i'},
+    {"brief", 0, 0, 'b'},
     {"format", 1, 0, 'f'},
     {"version", 0, 0, 'V'},
     {"help", 0, 0, 'h'},
@@ -70,21 +71,23 @@ usage (char *program, int error)
 {
     FILE *file = error ? stderr : stdout;
 #if HAVE_GETOPT_LONG
-    fprintf (file, "usage: %s [-Vh] [-i index] [-f FORMAT] [--index index] [--format FORMAT] [--version] [--help] font-file...\n",
+    fprintf (file, "usage: %s [-bVh] [-i index] [-f FORMAT] [--index index] [--brief] [--format FORMAT] [--version] [--help] font-file...\n",
 	     program);
 #else
-    fprintf (file, "usage: %s [-Vh] [-i index] [-f FORMAT] font-file...\n",
+    fprintf (file, "usage: %s [-bVh] [-i index] [-f FORMAT] font-file...\n",
 	     program);
 #endif
     fprintf (file, "Query font files and print resulting pattern(s)\n");
     fprintf (file, "\n");
 #if HAVE_GETOPT_LONG
     fprintf (file, "  -i, --index INDEX    display the INDEX face of each font file only\n");
+    fprintf (file, "  -b, --brief          display font pattern briefly\n");
     fprintf (file, "  -f, --format=FORMAT  use the given output format\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, "  -i INDEX   (index)         display the INDEX face of each font file only\n");
+    fprintf (file, "  -b         (brief)         display font pattern briefly\n");
     fprintf (file, "  -f FORMAT  (format)        use the given output format\n");
     fprintf (file, "  -V         (version)       display font config version and exit\n");
     fprintf (file, "  -h         (help)          display this help and exit\n");
@@ -96,6 +99,7 @@ int
 main (int argc, char **argv)
 {
     unsigned int id = (unsigned int) -1;
+    int         brief = 0;
     FcFontSet   *fs;
     FcChar8     *format = NULL;
     int		err = 0;
@@ -104,15 +108,18 @@ main (int argc, char **argv)
     int		c;
 
 #if HAVE_GETOPT_LONG
-    while ((c = getopt_long (argc, argv, "i:f:Vh", longopts, NULL)) != -1)
+    while ((c = getopt_long (argc, argv, "i:bf:Vh", longopts, NULL)) != -1)
 #else
-    while ((c = getopt (argc, argv, "i:f:Vh")) != -1)
+    while ((c = getopt (argc, argv, "i:bf:Vh")) != -1)
 #endif
     {
 	switch (c) {
 	case 'i':
 	    id = (unsigned int) strtol (optarg, NULL, 0); /* strtol() To handle -1. */
 	    break;
+	case 'b':
+	    brief = 1;
+	    break;
 	case 'f':
 	    format = (FcChar8 *) strdup (optarg);
 	    break;
@@ -149,6 +156,12 @@ main (int argc, char **argv)
     {
 	FcPattern *pat = fs->fonts[i];
 
+	if (brief)
+	{
+	    FcPatternDel (pat, FC_CHARSET);
+	    FcPatternDel (pat, FC_LANG);
+	}
+
 	if (format)
 	{
 	    FcChar8 *s;
diff --git a/fc-scan/fc-scan.c b/fc-scan/fc-scan.c
index 58a0b15..41bd260 100644
--- a/fc-scan/fc-scan.c
+++ b/fc-scan/fc-scan.c
@@ -52,6 +52,7 @@
 #define _GNU_SOURCE
 #include <getopt.h>
 static const struct option longopts[] = {
+    {"brief", 0, 0, 'b'},
     {"format", 1, 0, 'f'},
     {"version", 0, 0, 'V'},
     {"help", 0, 0, 'h'},
@@ -69,19 +70,21 @@ usage (char *program, int error)
 {
     FILE *file = error ? stderr : stdout;
 #if HAVE_GETOPT_LONG
-    fprintf (file, "usage: %s [-Vh] [-f FORMAT] [--format FORMAT] [--version] [--help] font-file...\n",
+    fprintf (file, "usage: %s [-bVh] [-f FORMAT] [--brief] [--format FORMAT] [--version] [--help] font-file...\n",
 	     program);
 #else
-    fprintf (file, "usage: %s [-Vh] [-f FORMAT] font-file...\n",
+    fprintf (file, "usage: %s [-bVh] [-f FORMAT] font-file...\n",
 	     program);
 #endif
     fprintf (file, "Scan font files and directories, and print resulting pattern(s)\n");
     fprintf (file, "\n");
 #if HAVE_GETOPT_LONG
+    fprintf (file, "  -b, --brief          display font pattern briefly\n");
     fprintf (file, "  -f, --format=FORMAT  use the given output format\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, "  -b         (brief)         display font pattern briefly\n");
     fprintf (file, "  -f FORMAT  (format)        use the given output format\n");
     fprintf (file, "  -V         (version)       display font config version and exit\n");
     fprintf (file, "  -h         (help)          display this help and exit\n");
@@ -92,6 +95,7 @@ usage (char *program, int error)
 int
 main (int argc, char **argv)
 {
+    int         brief = 0;
     FcChar8     *format = NULL;
     int		i;
     FcFontSet   *fs;
@@ -105,6 +109,9 @@ main (int argc, char **argv)
 #endif
     {
 	switch (c) {
+	case 'b':
+	    brief = 1;
+	    break;
 	case 'f':
 	    format = (FcChar8 *) strdup (optarg);
 	    break;
@@ -152,6 +159,12 @@ main (int argc, char **argv)
     {
 	FcPattern *pat = fs->fonts[i];
 
+	if (brief)
+	{
+	    FcPatternDel (pat, FC_CHARSET);
+	    FcPatternDel (pat, FC_LANG);
+	}
+
 	if (format)
 	{
 	    FcChar8 *s;
commit dc8326d3f116bb2a1425aa68660a332e351b6cb4
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Fri Sep 15 01:20:56 2017 -0400

    [fc-query] Remove --ignore-blanks / -b
    
    Blanks are the new black, err, dead!

diff --git a/fc-query/fc-query.c b/fc-query/fc-query.c
index 2d2825a..9c9900b 100644
--- a/fc-query/fc-query.c
+++ b/fc-query/fc-query.c
@@ -52,7 +52,6 @@
 #define _GNU_SOURCE
 #include <getopt.h>
 static const struct option longopts[] = {
-    {"ignore-blanks", 0, 0, 'b'},
     {"index", 1, 0, 'i'},
     {"format", 1, 0, 'f'},
     {"version", 0, 0, 'V'},
@@ -71,22 +70,20 @@ usage (char *program, int error)
 {
     FILE *file = error ? stderr : stdout;
 #if HAVE_GETOPT_LONG
-    fprintf (file, "usage: %s [-Vbh] [-i index] [-f FORMAT] [--ignore-blanks] [--index index] [--format FORMAT] [--version] [--help] font-file...\n",
+    fprintf (file, "usage: %s [-Vh] [-i index] [-f FORMAT] [--index index] [--format FORMAT] [--version] [--help] font-file...\n",
 	     program);
 #else
-    fprintf (file, "usage: %s [-Vbh] [-i index] [-f FORMAT] font-file...\n",
+    fprintf (file, "usage: %s [-Vh] [-i index] [-f FORMAT] font-file...\n",
 	     program);
 #endif
     fprintf (file, "Query font files and print resulting pattern(s)\n");
     fprintf (file, "\n");
 #if HAVE_GETOPT_LONG
-    fprintf (file, "  -b, --ignore-blanks  ignore blanks to compute langauges\n");
     fprintf (file, "  -i, --index INDEX    display the INDEX face of each font file only\n");
     fprintf (file, "  -f, --format=FORMAT  use the given output format\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, "  -b         (ignore-blanks) ignore blanks to compute languages\n");
     fprintf (file, "  -i INDEX   (index)         display the INDEX face of each font file only\n");
     fprintf (file, "  -f FORMAT  (format)        use the given output format\n");
     fprintf (file, "  -V         (version)       display font config version and exit\n");
@@ -99,25 +96,20 @@ int
 main (int argc, char **argv)
 {
     unsigned int id = (unsigned int) -1;
-    int		ignore_blanks = 0;
     FcFontSet   *fs;
     FcChar8     *format = NULL;
-    FcBlanks    *blanks = NULL;
     int		err = 0;
     int		i;
 #if HAVE_GETOPT_LONG || HAVE_GETOPT
     int		c;
 
 #if HAVE_GETOPT_LONG
-    while ((c = getopt_long (argc, argv, "bi:f:Vh", longopts, NULL)) != -1)
+    while ((c = getopt_long (argc, argv, "i:f:Vh", longopts, NULL)) != -1)
 #else
-    while ((c = getopt (argc, argv, "bi:f:Vh")) != -1)
+    while ((c = getopt (argc, argv, "i:f:Vh")) != -1)
 #endif
     {
 	switch (c) {
-	case 'b':
-	    ignore_blanks = 1;
-	    break;
 	case 'i':
 	    id = (unsigned int) strtol (optarg, NULL, 0); /* strtol() To handle -1. */
 	    break;
@@ -143,12 +135,10 @@ main (int argc, char **argv)
 	usage (argv[0], 1);
 
     fs = FcFontSetCreate ();
-    if (!ignore_blanks)
-	blanks = FcConfigGetBlanks (NULL);
 
     for (; i < argc; i++)
     {
-	if (!FcFreeTypeQueryAll ((FcChar8*) argv[i], id, blanks, NULL, fs))
+	if (!FcFreeTypeQueryAll ((FcChar8*) argv[i], id, NULL, NULL, fs))
 	{
 	    fprintf (stderr, "Can't query face %u of font file %s\n", id, argv[i]);
 	    err = 1;
commit 2db7ca7d5801ba4d3024abedc7d1f11a684879da
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Fri Sep 15 01:01:17 2017 -0400

    In RenderPrepare(), handle ranges smartly
    
    If font claims to support range [100,900], and request is for [250], then
    return [250] in "rendered" pattern.  Previously was returning [100,900].
    
    This is desirable for varfonts weight and width, but probably not for size.
    Will roll back size to return request size always, for non-empty ranges.

diff --git a/src/fcmatch.c b/src/fcmatch.c
index c386ee4..03a4e5f 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -25,7 +25,7 @@
 #include "fcint.h"
 
 static double
-FcCompareNumber (FcValue *value1, FcValue *value2)
+FcCompareNumber (const FcValue *value1, const FcValue *value2, FcValue *bestValue)
 {
     double  v1, v2, v;
 
@@ -52,23 +52,27 @@ FcCompareNumber (FcValue *value1, FcValue *value2)
     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;
@@ -77,13 +81,15 @@ FcCompareFamily (FcValue *v1, FcValue *v2)
 }
 
 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;
@@ -95,7 +101,7 @@ FcComparePostScript (FcValue *v1, FcValue *v2)
 }
 
 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);
@@ -130,6 +136,7 @@ FcCompareLang (FcValue *v1, FcValue *v2)
     default:
 	return -1.0;
     }
+    *bestValue = FcValueCanonicalize (v2);
     switch (result) {
     case FcLangEqual:
 	return 0;
@@ -142,25 +149,28 @@ 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;
+
+    *bestValue = FcValueCanonicalize (v2);
     return (double) v2->u.b != v1->u.b;
 }
 
 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
-FcCompareRange (FcValue *v1, FcValue *v2)
+FcCompareRange (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
 {
     FcValue value1 = FcValueCanonicalize (v1);
     FcValue value2 = FcValueCanonicalize (v2);
-    double b1, e1, b2, e2;
+    double b1, e1, b2, e2, d;
 
     switch ((int) value1.type) {
     case FcTypeInteger:
@@ -192,6 +202,16 @@ FcCompareRange (FcValue *v1, FcValue *v2)
 	return -1;
     }
 
+    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));
@@ -200,9 +220,10 @@ FcCompareRange (FcValue *v1, FcValue *v2)
 }
 
 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)
@@ -280,7 +301,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;
 
@@ -350,7 +371,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;
@@ -360,7 +382,7 @@ FcCompareValueList (FcObject	     object,
 	    if (v < best)
 	    {
 		if (bestValue)
-		    *bestValue = FcValueCanonicalize(&v2->value);
+		    *bestValue = matchValue;
 		best = v;
 		pos = k;
 	    }
@@ -985,7 +1007,8 @@ FcFontSetSort (FcConfig	    *config FC_UNUSED,
 		    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)
commit 6a13a21e408d0eead6909db1b13f9a866f254034
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 13 04:04:56 2017 -0400

    [varfonts] Fetch optical-size for named instances

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index e19afe5..0d03208 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1318,7 +1318,10 @@ FcFreeTypeQueryFace (const FT_Face  face,
 		  width_mult = mult;
 		  break;
 
-		/* TODO optical size! */
+		case FT_MAKE_TAG ('o','p','s','z'):
+		  if (!FcPatternAddDouble (pat, FC_SIZE, value))
+		      goto bail1;
+		  break;
 	    }
 	  }
 	}
commit 0f9bbbcf8f6f8264efb0a2ded4d8d05f3b10f7a4
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 13 04:01:07 2017 -0400

    [varfonts] Query variable font in FcFreeTypeQueryAll()
    
    Returns varfont pattern at the end.

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 995a3b8..e19afe5 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -2092,11 +2092,13 @@ FcFreeTypeQueryAll(const FcChar8	*file,
 	    if (!set || ! FcFontSetAdd (set, pat))
 	      FcPatternDestroy (pat);
 	}
-	else
+	else if (instance_num != 0x8000)
 	    err = 1;
 
-	if (instance_num < num_instances && !set_instance_num)
+	if (!set_instance_num && instance_num < num_instances)
 	    instance_num++;
+	else if (!set_instance_num && instance_num == num_instances)
+	    instance_num = 0x8000; /* variable font */
 	else
 	{
 	    face_num++;
commit 585f08715b9405743e4a2559d537fd06fb8b51d5
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 13 03:57:29 2017 -0400

    Fix instance-num handling in collections
    
    Ouch!

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index de05aa6..995a3b8 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -2100,7 +2100,7 @@ FcFreeTypeQueryAll(const FcChar8	*file,
 	else
 	{
 	    face_num++;
-	    instance_num = 0;
+	    instance_num = set_instance_num;
 	}
     } while (!err && (!index_set || face_num == set_face_num) && face_num < num_faces);
 
commit 83b4161108457019d0d4fbee4ddbce8f2abe869a
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 13 03:35:02 2017 -0400

    [varfonts] Query varfonts if id >> 16 == 0x8000
    
    If "instance-number" part of face id is set to 0x8000, return a pattern
    for variable font as a whole.  This might have a range for weight, width,
    and size.
    
    If no variation is found, NULL is returned.
    
    Not hooked up to FcQueryFaceAll() yet.  For now, can be triggered using
    fc-query -i 0x80000000

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index caca5d9..de05aa6 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1165,6 +1165,10 @@ FcFreeTypeQueryFace (const FT_Face  face,
     int		    weight = -1;
     int		    width = -1;
     FcBool	    decorative = FcFalse;
+    FcBool	    variable = FcFalse;
+    FcBool	    variable_weight = FcFalse;
+    FcBool	    variable_width = FcFalse;
+    FcBool	    variable_size = FcFalse;
     FcCharSet	    *cs;
     FcLangSet	    *ls;
 #if 0
@@ -1206,8 +1210,6 @@ FcFreeTypeQueryFace (const FT_Face  face,
     char	    psname[256];
     const char	    *tmp;
 
-    FcRange	    *r = NULL;
-
     FcBool	    symbol = FcFalse;
 
     FcInitDebug (); /* We might be called with no initizalization whatsoever. */
@@ -1236,20 +1238,70 @@ FcFreeTypeQueryFace (const FT_Face  face,
 	    goto bail1;
     }
 
-    if (!FcPatternAddBool (pat, FC_VARIABLE, FcFalse))
-	goto bail1;
-
     if (id >> 16)
     {
-      unsigned int instance_id = (id >> 16) - 1;
-      if (!FT_Get_MM_Var (face, &master) && instance_id < master->num_namedstyles)
-	instance = &master->namedstyle[instance_id];
+      if (FT_Get_MM_Var (face, &master))
+	  goto bail1;
 
-      if (instance)
+      if (id >> 16 == 0x8000)
+      {
+	  /* Query variable font itself. */
+	  unsigned int i;
+
+	  for (i = 0; i < master->num_axis; i++)
+	  {
+	      double min_value = master->axis[i].minimum / (double) (1 << 16);
+	      double def_value = master->axis[i].def / (double) (1 << 16);
+	      double max_value = master->axis[i].maximum / (double) (1 << 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;
+		  variable = variable_weight = FcTrue;
+		  weight = 0; /* To stop looking for weight. */
+		  break;
+
+		case FT_MAKE_TAG ('w','d','t','h'):
+		  elt = FC_WIDTH;
+		  variable = variable_width = FcTrue;
+		  width = 0; /* To stop looking for width. */
+		  break;
+
+		case FT_MAKE_TAG ('o','p','s','z'):
+		  elt = FC_SIZE;
+		  variable = variable_size = FcTrue;
+		  break;
+	      }
+
+	      if (elt)
+	      {
+		  FcRange *r = FcRangeCreateDouble (min_value, max_value);
+		  if (!FcPatternAddRange (pat, elt, r))
+		  {
+		      FcRangeDestroy (r);
+		      goto bail1;
+		  }
+		  FcRangeDestroy (r);
+	      }
+	  }
+
+	  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];
+
 	  for (i = 0; i < master->num_axis; i++)
 	  {
 	      double value = instance->coords[i] / (double) (1 << 16);
@@ -1273,6 +1325,8 @@ FcFreeTypeQueryFace (const FT_Face  face,
         else
 	    goto bail1;
     }
+    if (!FcPatternAddBool (pat, FC_VARIABLE, variable))
+	goto bail1;
 
     /*
      * Get the OS/2 table
@@ -1685,9 +1739,10 @@ FcFreeTypeQueryFace (const FT_Face  face,
     }
 
 #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;
@@ -1841,10 +1896,10 @@ FcFreeTypeQueryFace (const FT_Face  face,
     if (!FcPatternAddInteger (pat, FC_SLANT, slant))
 	goto bail1;
 
-    if (!FcPatternAddInteger (pat, FC_WEIGHT, weight))
+    if (!variable_weight && !FcPatternAddInteger (pat, FC_WEIGHT, weight))
 	goto bail1;
 
-    if (!FcPatternAddInteger (pat, FC_WIDTH, width))
+    if (!variable_width && !FcPatternAddInteger (pat, FC_WIDTH, width))
 	goto bail1;
 
     if (!FcPatternAddString (pat, FC_FOUNDRY, foundry))
@@ -1983,7 +2038,7 @@ 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;
 
     if (count)
@@ -2023,7 +2078,7 @@ FcFreeTypeQueryAll(const FcChar8	*file,
 	FcPattern *pat;
 
 	id = ((instance_num << 16) + face_num);
-	if (FT_New_Face (ftLibrary, (const char *) file, id, &face))
+	if (FT_New_Face (ftLibrary, (const char *) file, id & 0x7FFFFFFF, &face))
 	  break;
 
 	num_faces = face->num_faces;
commit d3a7c3ce697a8ceb8042bf5bea11c38ac8990553
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 13 03:31:48 2017 -0400

    [varfonts] Change FC_WEIGHT and FC_WIDTH into ranges

diff --git a/src/fcobjs.h b/src/fcobjs.h
index 5efd8d3..8101594 100644
--- a/src/fcobjs.h
+++ b/src/fcobjs.h
@@ -29,8 +29,8 @@ FC_OBJECT (STYLELANG,		FcTypeString,	NULL)
 FC_OBJECT (FULLNAME,		FcTypeString,	NULL)
 FC_OBJECT (FULLNAMELANG,	FcTypeString,	NULL)
 FC_OBJECT (SLANT,		FcTypeInteger,	FcCompareNumber)
-FC_OBJECT (WEIGHT,		FcTypeInteger,	FcCompareNumber)
-FC_OBJECT (WIDTH,		FcTypeInteger,	FcCompareNumber)
+FC_OBJECT (WEIGHT,		FcTypeRange,	FcCompareRange)
+FC_OBJECT (WIDTH,		FcTypeRange,	FcCompareRange)
 FC_OBJECT (SIZE,		FcTypeRange,	FcCompareRange)
 FC_OBJECT (ASPECT,		FcTypeDouble,	NULL)
 FC_OBJECT (PIXEL_SIZE,		FcTypeDouble,	FcCompareNumber)
commit f034c86756d45bed61b86310d9e4e77db2d05df3
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 13 03:29:20 2017 -0400

    Print ranges as closed as opposed to half-open
    
    There's nothing assymetrical about how we match them.  Previously we "considered"
    them half-open because the OS/2 spec had usLowerOpticalPointSize as inclusive
    and usUpperOpticalPointSize as exclusive.  But we do not respect that.
    
    Note that the parsing code accepts both anyway, because of the way our sscanf()
    usage is written...

diff --git a/src/fcdbg.c b/src/fcdbg.c
index c2853ff..40e0d66 100644
--- a/src/fcdbg.c
+++ b/src/fcdbg.c
@@ -62,7 +62,7 @@ _FcValuePrintFile (FILE *f, const FcValue v)
 	fprintf (f, "face");
 	break;
     case FcTypeRange:
-	fprintf (f, "[%g %g)", v.u.r->begin, v.u.r->end);
+	fprintf (f, "[%g %g]", v.u.r->begin, v.u.r->end);
 	break;
     }
 }
diff --git a/src/fcname.c b/src/fcname.c
index 8be36c7..77e74bc 100644
--- a/src/fcname.c
+++ b/src/fcname.c
@@ -318,7 +318,7 @@ FcNameConvert (FcType type, FcChar8 *string)
 	    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)
@@ -526,7 +526,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;
commit a4bd5b7c7a06fe39d1461f9be098af37d364dcc2
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 13 03:27:03 2017 -0400

    [varfonts] Change id argument in FcFreeTypeQuery* to unsigned int
    
    Going to use the top bit to query varfonts.

diff --git a/fc-query/fc-query.c b/fc-query/fc-query.c
index a5b2cda..2d2825a 100644
--- a/fc-query/fc-query.c
+++ b/fc-query/fc-query.c
@@ -98,7 +98,7 @@ usage (char *program, int error)
 int
 main (int argc, char **argv)
 {
-    int		id = -1;
+    unsigned int id = (unsigned int) -1;
     int		ignore_blanks = 0;
     FcFontSet   *fs;
     FcChar8     *format = NULL;
@@ -119,7 +119,7 @@ main (int argc, char **argv)
 	    ignore_blanks = 1;
 	    break;
 	case 'i':
-	    id = atoi (optarg);
+	    id = (unsigned int) strtol (optarg, NULL, 0); /* strtol() To handle -1. */
 	    break;
 	case 'f':
 	    format = (FcChar8 *) strdup (optarg);
@@ -150,7 +150,7 @@ main (int argc, char **argv)
     {
 	if (!FcFreeTypeQueryAll ((FcChar8*) argv[i], id, blanks, NULL, fs))
 	{
-	    fprintf (stderr, "Can't query face %d of font file %s\n", id, argv[i]);
+	    fprintf (stderr, "Can't query face %u of font file %s\n", id, argv[i]);
 	    err = 1;
 	}
     }
diff --git a/fontconfig/fcfreetype.h b/fontconfig/fcfreetype.h
index 753fdf9..20b1128 100644
--- a/fontconfig/fcfreetype.h
+++ b/fontconfig/fcfreetype.h
@@ -51,7 +51,7 @@ FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f);
 FcPublic FcPattern *
 FcFreeTypeQueryFace (const FT_Face  face,
 		     const FcChar8  *file,
-		     int	    id,
+		     unsigned int   id,
 		     FcBlanks	    *blanks);
 
 _FCFUNCPROTOEND
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index c61c502..56091ac 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -577,10 +577,10 @@ FcDirCacheUnload (FcCache *cache);
 
 /* fcfreetype.c */
 FcPublic FcPattern *
-FcFreeTypeQuery (const FcChar8 *file, int id, FcBlanks *blanks, int *count);
+FcFreeTypeQuery (const FcChar8 *file, unsigned int id, FcBlanks *blanks, int *count);
 
 FcPublic unsigned int
-FcFreeTypeQueryAll(const FcChar8 *file, int id, FcBlanks *blanks, int *count, FcFontSet *set);
+FcFreeTypeQueryAll(const FcChar8 *file, unsigned int id, FcBlanks *blanks, int *count, FcFontSet *set);
 
 /* fcfs.c */
 
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 66afdf5..caca5d9 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1157,7 +1157,7 @@ static const FT_UShort nameid_order[] = {
 FcPattern *
 FcFreeTypeQueryFace (const FT_Face  face,
 		     const FcChar8  *file,
-		     int	    id,
+		     unsigned int   id,
 		     FcBlanks	    *blanks FC_UNUSED)
 {
     FcPattern	    *pat;
@@ -1972,7 +1972,7 @@ bail0:
 
 FcPattern *
 FcFreeTypeQuery(const FcChar8	*file,
-		int		id,
+		unsigned int	id,
 		FcBlanks	*blanks,
 		int		*count)
 {
@@ -1999,20 +1999,20 @@ bail:
 
 unsigned int
 FcFreeTypeQueryAll(const FcChar8	*file,
-		   int			id,
+		   unsigned int		id,
 		   FcBlanks		*blanks,
 		   int			*count,
 		   FcFontSet            *set)
 {
     FT_Face face;
     FT_Library ftLibrary = NULL;
-    int index_set = id != -1;
-    int set_face_num = index_set ? id & 0xFFFF : 0;
-    int set_instance_num = index_set ? id >> 16 : 0;
-    int face_num = set_face_num;
-    int instance_num = set_instance_num;
-    int num_faces = 0;
-    int num_instances = 0;
+    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;
 
commit 819d3a5541b3903bda5d1299d48a6760379cac72
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Tue Sep 12 12:21:05 2017 -0400

    [varfonts] Add FC_VARIABLE
    
    For now, we mark all fonts as non-variable.

diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index f4635aa..c61c502 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -99,6 +99,7 @@ typedef int		FcBool;
 #define FC_OUTLINE	    "outline"		/* Bool */
 #define FC_SCALABLE	    "scalable"		/* Bool */
 #define FC_COLOR	    "color"		/* Bool */
+#define FC_VARIABLE	    "variable"		/* Bool */
 #define FC_SCALE	    "scale"		/* double (deprecated) */
 #define FC_SYMBOL	    "symbol"		/* Bool */
 #define FC_DPI		    "dpi"		/* double */
diff --git a/src/fcdefault.c b/src/fcdefault.c
index 10c183a..35973d7 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -39,6 +39,7 @@ static const struct {
     { FC_EMBEDDED_BITMAP_OBJECT,   FcTrue 	},  /* !FC_LOAD_NO_BITMAP */
     { FC_DECORATIVE_OBJECT,	   FcFalse	},
     { FC_SYMBOL_OBJECT,		   FcFalse	},
+    { FC_VARIABLE_OBJECT,	   FcFalse	},
 };
 
 #define NUM_FC_BOOL_DEFAULTS	(int) (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0])
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index df33cf4..66afdf5 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1236,6 +1236,9 @@ FcFreeTypeQueryFace (const FT_Face  face,
 	    goto bail1;
     }
 
+    if (!FcPatternAddBool (pat, FC_VARIABLE, FcFalse))
+	goto bail1;
+
     if (id >> 16)
     {
       unsigned int instance_id = (id >> 16) - 1;
diff --git a/src/fcmatch.c b/src/fcmatch.c
index 113c14a..c386ee4 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -250,6 +250,7 @@ typedef enum _FcMatcherPriorityDummy {
 typedef enum _FcMatcherPriority {
     PRI1(FILE),
     PRI1(FONTFORMAT),
+    PRI1(VARIABLE),
     PRI1(SCALABLE),
     PRI1(COLOR),
     PRI1(FOUNDRY),
diff --git a/src/fcobjs.h b/src/fcobjs.h
index c436a5d..5efd8d3 100644
--- a/src/fcobjs.h
+++ b/src/fcobjs.h
@@ -71,4 +71,5 @@ FC_OBJECT (POSTSCRIPT_NAME,	FcTypeString,	FcComparePostScript)
 FC_OBJECT (COLOR,		FcTypeBool,	FcCompareBool)
 FC_OBJECT (SYMBOL,		FcTypeBool,	FcCompareBool)
 FC_OBJECT (FONT_VARIATIONS,	FcTypeString,	NULL)
+FC_OBJECT (VARIABLE,		FcTypeBool,	FcCompareBool)
 /* ^-------------- Add new objects here. */
commit 80e155c1c042d080772447d92c146501662ab85e
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Tue Sep 12 10:39:20 2017 -0400

    [varfonts] Add FC_FONT_VARIATIONS
    
    This is for clients to passthru font variation settings.  Modeled
    similar to FC_FONT_FEATURES.  Each element value is for one axis
    settings, eg. "abcd=2.3" where 'abcd' is the OpenType Font Variations
    axis tag.
    
    Needs docs update.

diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index f085aa0..f4635aa 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -119,6 +119,7 @@ typedef int		FcBool;
 #define FC_DECORATIVE	    "decorative"	/* Bool - true if style is a decorative variant */
 #define FC_LCD_FILTER	    "lcdfilter"		/* Int */
 #define FC_FONT_FEATURES    "fontfeatures"	/* String */
+#define FC_FONT_VARIATIONS  "fontvariations"	/* String */
 #define FC_NAMELANG	    "namelang"		/* String RFC 3866 langs */
 #define FC_PRGNAME	    "prgname"		/* String */
 #define FC_HASH		    "hash"		/* String (deprecated) */
diff --git a/src/fcobjs.h b/src/fcobjs.h
index 5d3d981..c436a5d 100644
--- a/src/fcobjs.h
+++ b/src/fcobjs.h
@@ -70,4 +70,5 @@ FC_OBJECT (HASH,		FcTypeString,	NULL)	/* deprecated */
 FC_OBJECT (POSTSCRIPT_NAME,	FcTypeString,	FcComparePostScript)
 FC_OBJECT (COLOR,		FcTypeBool,	FcCompareBool)
 FC_OBJECT (SYMBOL,		FcTypeBool,	FcCompareBool)
+FC_OBJECT (FONT_VARIATIONS,	FcTypeString,	NULL)
 /* ^-------------- Add new objects here. */
commit de00bdb01f1c879b4d55d5f7ef31dfea0049a34b
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 13 02:36:33 2017 -0400

    Indent

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 230f289..df33cf4 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1249,21 +1249,21 @@ FcFreeTypeQueryFace (const FT_Face  face,
 
 	  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;
-
-	      case FT_MAKE_TAG ('w','d','t','h'):
-		width_mult = mult;
-		break;
-
-	      /* TODO optical size! */
+	      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;
+
+		case FT_MAKE_TAG ('w','d','t','h'):
+		  width_mult = mult;
+		  break;
+
+		/* TODO optical size! */
 	    }
 	  }
 	}
commit 66f082451d8bd3ae781f6a570c20456d822dd2f1
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Wed Sep 13 02:26:25 2017 -0400

    Check instance-index before accessing array
    
    Ouch!

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 418b7c8..230f289 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1238,8 +1238,9 @@ FcFreeTypeQueryFace (const FT_Face  face,
 
     if (id >> 16)
     {
-      if (!FT_Get_MM_Var (face, &master))
-	instance = &master->namedstyle[(id >> 16) - 1];
+      unsigned int instance_id = (id >> 16) - 1;
+      if (!FT_Get_MM_Var (face, &master) && instance_id < master->num_namedstyles)
+	instance = &master->namedstyle[instance_id];
 
       if (instance)
       {
@@ -1266,6 +1267,8 @@ FcFreeTypeQueryFace (const FT_Face  face,
 	    }
 	  }
 	}
+        else
+	    goto bail1;
     }
 
     /*
commit b6440cbd7fbf965c8f70783bbdc93d592ac12b4e
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Tue Sep 12 19:18:59 2017 -0400

    In FcSubstituteDefault(), handle size range
    
    Takes the midpoint...

diff --git a/src/fcdefault.c b/src/fcdefault.c
index 5afd7ec..10c183a 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -255,7 +255,14 @@ FcDefaultSubstitute (FcPattern *pattern)
 	    FcPatternObjectAddBool (pattern, FcBoolDefaults[i].field, FcBoolDefaults[i].value);
 
     if (FcPatternObjectGetDouble (pattern, FC_SIZE_OBJECT, 0, &size) != FcResultMatch)
-	size = 12.0L;
+    {
+	FcRange *r;
+	double b, e;
+	if (FcPatternObjectGetRange (pattern, FC_SIZE_OBJECT, 0, &r) == FcResultMatch && FcRangeGetDouble (r, &b, &e))
+	    size = (b + e) * .5;
+	else
+	    size = 12.0L;
+    }
     if (FcPatternObjectGetDouble (pattern, FC_SCALE_OBJECT, 0, &scale) != FcResultMatch)
 	scale = 1.0;
     if (FcPatternObjectGetDouble (pattern, FC_DPI_OBJECT, 0, &dpi) != FcResultMatch)
commit b4813436a3bea1945f44f3bf75a4eb02de8d0303
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Tue Sep 12 19:08:36 2017 -0400

    Rewrite FcCompareRange()
    
    Much simpler now.

diff --git a/src/fcmatch.c b/src/fcmatch.c
index a4d3205..113c14a 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -160,42 +160,43 @@ FcCompareRange (FcValue *v1, FcValue *v2)
 {
     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;
+    /* 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
-	ret = FC_MIN (fabs (r1->end - r2->begin), fabs (r1->begin - r2->end));
-
-bail:
-    if (r1)
-	FcRangeDestroy (r1);
-    if (r2)
-	FcRangeDestroy (r2);
-
-    return ret;
+	return 0.0;
 }
 
 static double
commit e7a0a0a99938deb798c007343f01fb751bc9cd3b
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Tue Sep 12 18:55:03 2017 -0400

    Rename FcCompareSizeRange() to FcCompareRange()

diff --git a/src/fcmatch.c b/src/fcmatch.c
index 022fe27..a4d3205 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -156,7 +156,7 @@ FcCompareCharSet (FcValue *v1, FcValue *v2)
 }
 
 static double
-FcCompareSizeRange (FcValue *v1, FcValue *v2)
+FcCompareRange (FcValue *v1, FcValue *v2)
 {
     FcValue value1 = FcValueCanonicalize (v1);
     FcValue value2 = FcValueCanonicalize (v2);
@@ -227,7 +227,7 @@ FcCompareFilename (FcValue *v1, FcValue *v2)
 #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 FC_OBJECT(NAME, Type, Cmp)	PRI_##Cmp(NAME)
 
diff --git a/src/fcobjs.h b/src/fcobjs.h
index 96dc646..5d3d981 100644
--- a/src/fcobjs.h
+++ b/src/fcobjs.h
@@ -31,7 +31,7 @@ FC_OBJECT (FULLNAMELANG,	FcTypeString,	NULL)
 FC_OBJECT (SLANT,		FcTypeInteger,	FcCompareNumber)
 FC_OBJECT (WEIGHT,		FcTypeInteger,	FcCompareNumber)
 FC_OBJECT (WIDTH,		FcTypeInteger,	FcCompareNumber)
-FC_OBJECT (SIZE,		FcTypeRange,	FcCompareSizeRange)
+FC_OBJECT (SIZE,		FcTypeRange,	FcCompareRange)
 FC_OBJECT (ASPECT,		FcTypeDouble,	NULL)
 FC_OBJECT (PIXEL_SIZE,		FcTypeDouble,	FcCompareNumber)
 FC_OBJECT (SPACING,		FcTypeInteger,	FcCompareNumber)
commit 7519c567e13f476c64fe1938fedd0033e7e70833
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Tue Sep 12 18:52:49 2017 -0400

    Remove FcCompareSize()
    
    Use FcCompareNumber().  The FcCompareSize() returns 0 ("perfect match")
    if v2 is zero.  I cannot think of a use-case for this.  The code has been
    there from initial commit in 2002.  I suppose back then Keith had a use
    for size=0 to mean scalable or something.  Anyway, remove and see.

diff --git a/src/fcmatch.c b/src/fcmatch.c
index 40efbd3..022fe27 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -156,39 +156,6 @@ FcCompareCharSet (FcValue *v1, FcValue *v2)
 }
 
 static double
-FcCompareSize (FcValue *value1, FcValue *value2)
-{
-    double  v1, v2, v;
-
-    switch ((int) value1->type) {
-    case FcTypeInteger:
-	v1 = value1->u.i;
-	break;
-    case FcTypeDouble:
-	v1 = value1->u.d;
-	break;
-    default:
-	return -1;
-    }
-    switch ((int) value2->type) {
-    case FcTypeInteger:
-	v2 = value2->u.i;
-	break;
-    case FcTypeDouble:
-	v2 = value2->u.d;
-	break;
-    default:
-	return -1;
-    }
-    if (v2 == 0)
-	return 0;
-    v = v2 - v1;
-    if (v < 0)
-	v = -v;
-    return v;
-}
-
-static double
 FcCompareSizeRange (FcValue *v1, FcValue *v2)
 {
     FcValue value1 = FcValueCanonicalize (v1);
@@ -255,7 +222,6 @@ FcCompareFilename (FcValue *v1, FcValue *v2)
 #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)
diff --git a/src/fcobjs.h b/src/fcobjs.h
index d27864b..96dc646 100644
--- a/src/fcobjs.h
+++ b/src/fcobjs.h
@@ -33,7 +33,7 @@ FC_OBJECT (WEIGHT,		FcTypeInteger,	FcCompareNumber)
 FC_OBJECT (WIDTH,		FcTypeInteger,	FcCompareNumber)
 FC_OBJECT (SIZE,		FcTypeRange,	FcCompareSizeRange)
 FC_OBJECT (ASPECT,		FcTypeDouble,	NULL)
-FC_OBJECT (PIXEL_SIZE,		FcTypeDouble,	FcCompareSize)
+FC_OBJECT (PIXEL_SIZE,		FcTypeDouble,	FcCompareNumber)
 FC_OBJECT (SPACING,		FcTypeInteger,	FcCompareNumber)
 FC_OBJECT (FOUNDRY,		FcTypeString,	FcCompareString)
 FC_OBJECT (ANTIALIAS,		FcTypeBool,	FcCompareBool)
commit 6eb7e5ae811cabbbd3476f8fc392f119a3d7cec5
Author: Behdad Esfahbod <behdad@xxxxxxxxxx>
Date:   Tue Sep 12 18:00:43 2017 -0400

    Accept NULL in for spacing in FcFreeTypeCharSetAndSpacing()

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index a6e7058..418b7c8 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -2140,8 +2140,8 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spac
     FcCharSet	    *fcs;
     int		    o;
     FT_Int	    load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
-    FT_Pos	    advances[3];
-    unsigned int    num_advances = 0;
+    FT_Pos	    advances[3] = {};
+    unsigned int    num_advances = spacing ? 0 : 3;
 
     fcs = FcCharSetCreate ();
     if (!fcs)
@@ -2265,14 +2265,19 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spac
 #endif
 	break;
     }
-    if (num_advances <= 1)
-	*spacing = FC_MONO;
-    else if (num_advances == 2 &&
-	     fc_approximately_equal (fc_min (advances[0], advances[1]) * 2,
-				     fc_max (advances[0], advances[1])))
-        *spacing = FC_DUAL;
-    else
-	*spacing = FC_PROPORTIONAL;
+
+    if (spacing)
+    {
+      if (num_advances <= 1)
+	  *spacing = FC_MONO;
+      else if (num_advances == 2 &&
+	       fc_approximately_equal (fc_min (advances[0], advances[1]) * 2,
+				       fc_max (advances[0], advances[1])))
+	  *spacing = FC_DUAL;
+      else
+	  *spacing = FC_PROPORTIONAL;
+    }
+
     return fcs;
 bail1:
     FcCharSetDestroy (fcs);
@@ -2283,9 +2288,7 @@ bail0:
 FcCharSet *
 FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks FC_UNUSED)
 {
-    int spacing;
-
-    return FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
+    return FcFreeTypeCharSetAndSpacing (face, blanks, NULL);
 }
 
 
_______________________________________________
Fontconfig mailing list
Fontconfig@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/fontconfig




[Index of Archives]     [Fedora Fonts]     [Fedora Users]     [Fedora Cloud]     [Kernel]     [Fedora Packaging]     [Fedora Desktop]     [PAM]     [Gimp Graphics Editor]     [Yosemite News]

  Powered by Linux