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:
parent
c758206e8c
commit
b561ff2016
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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. */
|
||||
|
|
85
src/fcstr.c
85
src/fcstr.c
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue