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