Bug 38737 - Wishlist: support FC_POSTSCRIPT_NAME

Add the PostScript name into the cache and the matcher.
Scoring the better font against the PostScript name by
the forward-matching.
This commit is contained in:
Akira TAGOH 2013-01-18 11:30:10 +09:00
parent c758206e8c
commit b561ff2016
6 changed files with 125 additions and 38 deletions

View File

@ -116,6 +116,7 @@ typedef int FcBool;
#define FC_NAMELANG "namelang" /* String RFC 3866 langs */
#define FC_PRGNAME "prgname" /* String */
#define FC_HASH "hash" /* String */
#define FC_POSTSCRIPT_NAME "postscriptname" /* String */
#define FC_CACHE_SUFFIX ".cache-" FC_CACHE_VERSION
#define FC_DIR_CACHE_FILE "fonts.cache-" FC_CACHE_VERSION

View File

@ -1101,6 +1101,8 @@ FcFreeTypeQueryFace (const FT_Face face,
FcChar8 *style = 0;
int st;
char psname[256];
const char *tmp;
FcChar8 *hashstr;
@ -1201,7 +1203,6 @@ FcFreeTypeQueryFace (const FT_Face face,
case TT_NAME_ID_PREFERRED_FAMILY:
case TT_NAME_ID_FONT_FAMILY:
#if 0
case TT_NAME_ID_PS_NAME:
case TT_NAME_ID_UNIQUE_ID:
#endif
if (FcDebug () & FC_DBG_SCANV)
@ -1347,6 +1348,52 @@ FcFreeTypeQueryFace (const FT_Face face,
++nfamily;
}
/* Add the PostScript name into the cache */
tmp = FT_Get_Postscript_Name (face);
if (!tmp)
{
FcChar8 *family, *familylang = NULL;
size_t len;
int n = 0;
/* Workaround when FT_Get_Postscript_Name didn't give any name.
* try to find out the English family name and convert.
*/
while (FcPatternObjectGetString (pat, FC_FAMILYLANG_OBJECT, n, &familylang) == FcResultMatch)
{
if (FcStrCmp (familylang, (const FcChar8 *)"en") == 0)
break;
n++;
familylang = NULL;
}
if (!familylang)
n = 0;
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;
}
else
{
strcpy (psname, tmp);
}
if (!FcPatternAddString (pat, FC_POSTSCRIPT_NAME, (const FcChar8 *)psname))
goto bail1;
if (!FcPatternAddString (pat, FC_FILE, file))
goto bail1;

View File

@ -1063,6 +1063,9 @@ FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len);
FcPrivate int
FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2);
FcPrivate int
FcStrCmpIgnoreCaseAndDelims (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *delims);
FcPrivate FcBool
FcStrRegexCmp (const FcChar8 *s, const FcChar8 *regex);
@ -1078,6 +1081,9 @@ FcStrContainsIgnoreCase (const FcChar8 *s1, const FcChar8 *s2);
FcPrivate const FcChar8 *
FcStrContainsWord (const FcChar8 *s1, const FcChar8 *s2);
FcPrivate int
FcStrMatchIgnoreCaseAndDelims (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *delims);
FcPrivate FcBool
FcStrUsesHome (const FcChar8 *s);

View File

@ -76,6 +76,24 @@ FcCompareFamily (FcValue *v1, FcValue *v2)
return (double) FcStrCmpIgnoreBlanksAndCase (v1_string, v2_string) != 0;
}
static double
FcComparePostScript (FcValue *v1, FcValue *v2)
{
const FcChar8 *v1_string = FcValueString (v1);
const FcChar8 *v2_string = FcValueString (v2);
int n;
size_t len;
if (FcToLower (*v1_string) != FcToLower (*v2_string) &&
*v1_string != ' ' && *v2_string != ' ')
return 1.0;
n = FcStrMatchIgnoreCaseAndDelims (v1_string, v2_string, (const FcChar8 *)" -");
len = strlen ((const char *)v1_string);
return (double)(len - n) / (double)len;
}
static double
FcCompareLang (FcValue *v1, FcValue *v2)
{
@ -198,6 +216,7 @@ FcCompareFilename (FcValue *v1, FcValue *v2)
#define PRI_FcCompareFilename(n) PRI1(n)
#define PRI_FcCompareCharSet(n) PRI1(n)
#define PRI_FcCompareLang(n) PRI1(n)
#define PRI_FcComparePostScript(n) PRI1(n)
#define FC_OBJECT(NAME, Type, Cmp) PRI_##Cmp(NAME)
@ -219,8 +238,10 @@ typedef enum _FcMatcherPriority {
PRI1(CHARSET),
PRI_FAMILY_STRONG,
PRI_LANG_STRONG,
PRI_POSTSCRIPT_NAME_STRONG,
PRI_LANG_WEAK,
PRI_FAMILY_WEAK,
PRI_POSTSCRIPT_NAME_WEAK,
PRI1(SPACING),
PRI1(PIXEL_SIZE),
PRI1(STYLE),

View File

@ -44,4 +44,5 @@ FC_OBJECT (NAMELANG, FcTypeString, NULL)
FC_OBJECT (FONT_FEATURES, FcTypeString, NULL)
FC_OBJECT (PRGNAME, FcTypeString, NULL)
FC_OBJECT (HASH, FcTypeString, FcCompareString)
FC_OBJECT (POSTSCRIPT_NAME, FcTypeString, FcComparePostScript)
/* ^-------------- Add new objects here. */

View File

@ -137,27 +137,7 @@ FcStrCaseWalkerLong (FcCaseWalker *w, FcChar8 r)
}
static FcChar8
FcStrCaseWalkerNext (FcCaseWalker *w)
{
FcChar8 r;
if (w->read)
{
if ((r = *w->read++))
return r;
w->read = 0;
}
r = *w->src++;
if ((r & 0xc0) == 0xc0)
return FcStrCaseWalkerLong (w, r);
if ('A' <= r && r <= 'Z')
r = r - 'A' + 'a';
return r;
}
static FcChar8
FcStrCaseWalkerNextIgnoreBlanks (FcCaseWalker *w)
FcStrCaseWalkerNext (FcCaseWalker *w, const char *delims)
{
FcChar8 r;
@ -170,7 +150,7 @@ FcStrCaseWalkerNextIgnoreBlanks (FcCaseWalker *w)
do
{
r = *w->src++;
} while (r == ' ');
} while (r != 0 && delims && strchr (delims, r));
if ((r & 0xc0) == 0xc0)
return FcStrCaseWalkerLong (w, r);
@ -187,13 +167,13 @@ FcStrDowncase (const FcChar8 *s)
FcChar8 *dst, *d;
FcStrCaseWalkerInit (s, &w);
while (FcStrCaseWalkerNext (&w))
while (FcStrCaseWalkerNext (&w, NULL))
len++;
d = dst = malloc (len + 1);
if (!d)
return 0;
FcStrCaseWalkerInit (s, &w);
while ((*d++ = FcStrCaseWalkerNext (&w)));
while ((*d++ = FcStrCaseWalkerNext (&w, NULL)));
return dst;
}
@ -210,8 +190,8 @@ FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
for (;;)
{
c1 = FcStrCaseWalkerNext (&w1);
c2 = FcStrCaseWalkerNext (&w2);
c1 = FcStrCaseWalkerNext (&w1, NULL);
c2 = FcStrCaseWalkerNext (&w2, NULL);
if (!c1 || (c1 != c2))
break;
}
@ -220,6 +200,12 @@ FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
int
FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
{
return FcStrCmpIgnoreCaseAndDelims (s1, s2, (const FcChar8 *)" ");
}
int
FcStrCmpIgnoreCaseAndDelims (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *delims)
{
FcCaseWalker w1, w2;
FcChar8 c1, c2;
@ -231,8 +217,8 @@ FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
for (;;)
{
c1 = FcStrCaseWalkerNextIgnoreBlanks (&w1);
c2 = FcStrCaseWalkerNextIgnoreBlanks (&w2);
c1 = FcStrCaseWalkerNext (&w1, (const char *)delims);
c2 = FcStrCaseWalkerNext (&w2, (const char *)delims);
if (!c1 || (c1 != c2))
break;
}
@ -317,7 +303,7 @@ FcStrHashIgnoreCase (const FcChar8 *s)
FcChar8 c;
FcStrCaseWalkerInit (s, &w);
while ((c = FcStrCaseWalkerNext (&w)))
while ((c = FcStrCaseWalkerNext (&w, NULL)))
h = ((h << 3) ^ (h >> 3)) ^ c;
return h;
}
@ -337,8 +323,8 @@ FcStrIsAtIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
for (;;)
{
c1 = FcStrCaseWalkerNextIgnoreBlanks (&w1);
c2 = FcStrCaseWalkerNextIgnoreBlanks (&w2);
c1 = FcStrCaseWalkerNext (&w1, " ");
c2 = FcStrCaseWalkerNext (&w2, " ");
if (!c1 || (c1 != c2))
break;
}
@ -396,8 +382,8 @@ FcStrIsAtIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
for (;;)
{
c1 = FcStrCaseWalkerNext (&w1);
c2 = FcStrCaseWalkerNext (&w2);
c1 = FcStrCaseWalkerNext (&w1, NULL);
c2 = FcStrCaseWalkerNext (&w2, NULL);
if (!c1 || (c1 != c2))
break;
}
@ -448,6 +434,31 @@ FcStrContainsWord (const FcChar8 *s1, const FcChar8 *s2)
return 0;
}
/*
* returns the number of strings (ignoring delimitors and case) being matched
*/
int
FcStrMatchIgnoreCaseAndDelims (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *delims)
{
FcCaseWalker w1, w2;
FcChar8 c1, c2;
if (s1 == s2) return 0;
FcStrCaseWalkerInit (s1, &w1);
FcStrCaseWalkerInit (s2, &w2);
for (;;)
{
c1 = FcStrCaseWalkerNext (&w1, (const char *)delims);
c2 = FcStrCaseWalkerNext (&w2, (const char *)delims);
if (!c1 || (c1 != c2))
break;
}
return w1.src - s1 - 1;
}
const FcChar8 *
FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
{
@ -464,12 +475,12 @@ FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
FcStrCaseWalkerInit (s1, &w1);
FcStrCaseWalkerInit (s2, &w2);
c2 = FcStrCaseWalkerNext (&w2);
c2 = FcStrCaseWalkerNext (&w2, NULL);
for (;;)
{
cur = w1.src;
c1 = FcStrCaseWalkerNext (&w1);
c1 = FcStrCaseWalkerNext (&w1, NULL);
if (!c1)
break;
if (c1 == c2)
@ -480,8 +491,8 @@ FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
for (;;)
{
c1t = FcStrCaseWalkerNext (&w1t);
c2t = FcStrCaseWalkerNext (&w2t);
c1t = FcStrCaseWalkerNext (&w1t, NULL);
c2t = FcStrCaseWalkerNext (&w2t, NULL);
if (!c2t)
return cur;