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_NAMELANG "namelang" /* String RFC 3866 langs */
|
||||||
#define FC_PRGNAME "prgname" /* String */
|
#define FC_PRGNAME "prgname" /* String */
|
||||||
#define FC_HASH "hash" /* String */
|
#define FC_HASH "hash" /* String */
|
||||||
|
#define FC_POSTSCRIPT_NAME "postscriptname" /* String */
|
||||||
|
|
||||||
#define FC_CACHE_SUFFIX ".cache-" FC_CACHE_VERSION
|
#define FC_CACHE_SUFFIX ".cache-" FC_CACHE_VERSION
|
||||||
#define FC_DIR_CACHE_FILE "fonts.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;
|
FcChar8 *style = 0;
|
||||||
int st;
|
int st;
|
||||||
|
char psname[256];
|
||||||
|
const char *tmp;
|
||||||
|
|
||||||
FcChar8 *hashstr;
|
FcChar8 *hashstr;
|
||||||
|
|
||||||
|
@ -1201,7 +1203,6 @@ FcFreeTypeQueryFace (const FT_Face face,
|
||||||
case TT_NAME_ID_PREFERRED_FAMILY:
|
case TT_NAME_ID_PREFERRED_FAMILY:
|
||||||
case TT_NAME_ID_FONT_FAMILY:
|
case TT_NAME_ID_FONT_FAMILY:
|
||||||
#if 0
|
#if 0
|
||||||
case TT_NAME_ID_PS_NAME:
|
|
||||||
case TT_NAME_ID_UNIQUE_ID:
|
case TT_NAME_ID_UNIQUE_ID:
|
||||||
#endif
|
#endif
|
||||||
if (FcDebug () & FC_DBG_SCANV)
|
if (FcDebug () & FC_DBG_SCANV)
|
||||||
|
@ -1347,6 +1348,52 @@ FcFreeTypeQueryFace (const FT_Face face,
|
||||||
++nfamily;
|
++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))
|
if (!FcPatternAddString (pat, FC_FILE, file))
|
||||||
goto bail1;
|
goto bail1;
|
||||||
|
|
||||||
|
|
|
@ -1063,6 +1063,9 @@ FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len);
|
||||||
FcPrivate int
|
FcPrivate int
|
||||||
FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2);
|
FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2);
|
||||||
|
|
||||||
|
FcPrivate int
|
||||||
|
FcStrCmpIgnoreCaseAndDelims (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *delims);
|
||||||
|
|
||||||
FcPrivate FcBool
|
FcPrivate FcBool
|
||||||
FcStrRegexCmp (const FcChar8 *s, const FcChar8 *regex);
|
FcStrRegexCmp (const FcChar8 *s, const FcChar8 *regex);
|
||||||
|
|
||||||
|
@ -1078,6 +1081,9 @@ FcStrContainsIgnoreCase (const FcChar8 *s1, const FcChar8 *s2);
|
||||||
FcPrivate const FcChar8 *
|
FcPrivate const FcChar8 *
|
||||||
FcStrContainsWord (const FcChar8 *s1, const FcChar8 *s2);
|
FcStrContainsWord (const FcChar8 *s1, const FcChar8 *s2);
|
||||||
|
|
||||||
|
FcPrivate int
|
||||||
|
FcStrMatchIgnoreCaseAndDelims (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *delims);
|
||||||
|
|
||||||
FcPrivate FcBool
|
FcPrivate FcBool
|
||||||
FcStrUsesHome (const FcChar8 *s);
|
FcStrUsesHome (const FcChar8 *s);
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,24 @@ FcCompareFamily (FcValue *v1, FcValue *v2)
|
||||||
return (double) FcStrCmpIgnoreBlanksAndCase (v1_string, v2_string) != 0;
|
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
|
static double
|
||||||
FcCompareLang (FcValue *v1, FcValue *v2)
|
FcCompareLang (FcValue *v1, FcValue *v2)
|
||||||
{
|
{
|
||||||
|
@ -198,6 +216,7 @@ FcCompareFilename (FcValue *v1, FcValue *v2)
|
||||||
#define PRI_FcCompareFilename(n) PRI1(n)
|
#define PRI_FcCompareFilename(n) PRI1(n)
|
||||||
#define PRI_FcCompareCharSet(n) PRI1(n)
|
#define PRI_FcCompareCharSet(n) PRI1(n)
|
||||||
#define PRI_FcCompareLang(n) PRI1(n)
|
#define PRI_FcCompareLang(n) PRI1(n)
|
||||||
|
#define PRI_FcComparePostScript(n) PRI1(n)
|
||||||
|
|
||||||
#define FC_OBJECT(NAME, Type, Cmp) PRI_##Cmp(NAME)
|
#define FC_OBJECT(NAME, Type, Cmp) PRI_##Cmp(NAME)
|
||||||
|
|
||||||
|
@ -219,8 +238,10 @@ typedef enum _FcMatcherPriority {
|
||||||
PRI1(CHARSET),
|
PRI1(CHARSET),
|
||||||
PRI_FAMILY_STRONG,
|
PRI_FAMILY_STRONG,
|
||||||
PRI_LANG_STRONG,
|
PRI_LANG_STRONG,
|
||||||
|
PRI_POSTSCRIPT_NAME_STRONG,
|
||||||
PRI_LANG_WEAK,
|
PRI_LANG_WEAK,
|
||||||
PRI_FAMILY_WEAK,
|
PRI_FAMILY_WEAK,
|
||||||
|
PRI_POSTSCRIPT_NAME_WEAK,
|
||||||
PRI1(SPACING),
|
PRI1(SPACING),
|
||||||
PRI1(PIXEL_SIZE),
|
PRI1(PIXEL_SIZE),
|
||||||
PRI1(STYLE),
|
PRI1(STYLE),
|
||||||
|
|
|
@ -44,4 +44,5 @@ FC_OBJECT (NAMELANG, FcTypeString, NULL)
|
||||||
FC_OBJECT (FONT_FEATURES, FcTypeString, NULL)
|
FC_OBJECT (FONT_FEATURES, FcTypeString, NULL)
|
||||||
FC_OBJECT (PRGNAME, FcTypeString, NULL)
|
FC_OBJECT (PRGNAME, FcTypeString, NULL)
|
||||||
FC_OBJECT (HASH, FcTypeString, FcCompareString)
|
FC_OBJECT (HASH, FcTypeString, FcCompareString)
|
||||||
|
FC_OBJECT (POSTSCRIPT_NAME, FcTypeString, FcComparePostScript)
|
||||||
/* ^-------------- Add new objects here. */
|
/* ^-------------- Add new objects here. */
|
||||||
|
|
85
src/fcstr.c
85
src/fcstr.c
|
@ -137,27 +137,7 @@ FcStrCaseWalkerLong (FcCaseWalker *w, FcChar8 r)
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcChar8
|
static FcChar8
|
||||||
FcStrCaseWalkerNext (FcCaseWalker *w)
|
FcStrCaseWalkerNext (FcCaseWalker *w, const char *delims)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
FcChar8 r;
|
FcChar8 r;
|
||||||
|
|
||||||
|
@ -170,7 +150,7 @@ FcStrCaseWalkerNextIgnoreBlanks (FcCaseWalker *w)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
r = *w->src++;
|
r = *w->src++;
|
||||||
} while (r == ' ');
|
} while (r != 0 && delims && strchr (delims, r));
|
||||||
|
|
||||||
if ((r & 0xc0) == 0xc0)
|
if ((r & 0xc0) == 0xc0)
|
||||||
return FcStrCaseWalkerLong (w, r);
|
return FcStrCaseWalkerLong (w, r);
|
||||||
|
@ -187,13 +167,13 @@ FcStrDowncase (const FcChar8 *s)
|
||||||
FcChar8 *dst, *d;
|
FcChar8 *dst, *d;
|
||||||
|
|
||||||
FcStrCaseWalkerInit (s, &w);
|
FcStrCaseWalkerInit (s, &w);
|
||||||
while (FcStrCaseWalkerNext (&w))
|
while (FcStrCaseWalkerNext (&w, NULL))
|
||||||
len++;
|
len++;
|
||||||
d = dst = malloc (len + 1);
|
d = dst = malloc (len + 1);
|
||||||
if (!d)
|
if (!d)
|
||||||
return 0;
|
return 0;
|
||||||
FcStrCaseWalkerInit (s, &w);
|
FcStrCaseWalkerInit (s, &w);
|
||||||
while ((*d++ = FcStrCaseWalkerNext (&w)));
|
while ((*d++ = FcStrCaseWalkerNext (&w, NULL)));
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,8 +190,8 @@ FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
c1 = FcStrCaseWalkerNext (&w1);
|
c1 = FcStrCaseWalkerNext (&w1, NULL);
|
||||||
c2 = FcStrCaseWalkerNext (&w2);
|
c2 = FcStrCaseWalkerNext (&w2, NULL);
|
||||||
if (!c1 || (c1 != c2))
|
if (!c1 || (c1 != c2))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -220,6 +200,12 @@ FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
|
|
||||||
int
|
int
|
||||||
FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
|
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;
|
FcCaseWalker w1, w2;
|
||||||
FcChar8 c1, c2;
|
FcChar8 c1, c2;
|
||||||
|
@ -231,8 +217,8 @@ FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
c1 = FcStrCaseWalkerNextIgnoreBlanks (&w1);
|
c1 = FcStrCaseWalkerNext (&w1, (const char *)delims);
|
||||||
c2 = FcStrCaseWalkerNextIgnoreBlanks (&w2);
|
c2 = FcStrCaseWalkerNext (&w2, (const char *)delims);
|
||||||
if (!c1 || (c1 != c2))
|
if (!c1 || (c1 != c2))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -317,7 +303,7 @@ FcStrHashIgnoreCase (const FcChar8 *s)
|
||||||
FcChar8 c;
|
FcChar8 c;
|
||||||
|
|
||||||
FcStrCaseWalkerInit (s, &w);
|
FcStrCaseWalkerInit (s, &w);
|
||||||
while ((c = FcStrCaseWalkerNext (&w)))
|
while ((c = FcStrCaseWalkerNext (&w, NULL)))
|
||||||
h = ((h << 3) ^ (h >> 3)) ^ c;
|
h = ((h << 3) ^ (h >> 3)) ^ c;
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
@ -337,8 +323,8 @@ FcStrIsAtIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
c1 = FcStrCaseWalkerNextIgnoreBlanks (&w1);
|
c1 = FcStrCaseWalkerNext (&w1, " ");
|
||||||
c2 = FcStrCaseWalkerNextIgnoreBlanks (&w2);
|
c2 = FcStrCaseWalkerNext (&w2, " ");
|
||||||
if (!c1 || (c1 != c2))
|
if (!c1 || (c1 != c2))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -396,8 +382,8 @@ FcStrIsAtIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
c1 = FcStrCaseWalkerNext (&w1);
|
c1 = FcStrCaseWalkerNext (&w1, NULL);
|
||||||
c2 = FcStrCaseWalkerNext (&w2);
|
c2 = FcStrCaseWalkerNext (&w2, NULL);
|
||||||
if (!c1 || (c1 != c2))
|
if (!c1 || (c1 != c2))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -448,6 +434,31 @@ FcStrContainsWord (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
return 0;
|
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 *
|
const FcChar8 *
|
||||||
FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
|
FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
{
|
{
|
||||||
|
@ -464,12 +475,12 @@ FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
FcStrCaseWalkerInit (s1, &w1);
|
FcStrCaseWalkerInit (s1, &w1);
|
||||||
FcStrCaseWalkerInit (s2, &w2);
|
FcStrCaseWalkerInit (s2, &w2);
|
||||||
|
|
||||||
c2 = FcStrCaseWalkerNext (&w2);
|
c2 = FcStrCaseWalkerNext (&w2, NULL);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
cur = w1.src;
|
cur = w1.src;
|
||||||
c1 = FcStrCaseWalkerNext (&w1);
|
c1 = FcStrCaseWalkerNext (&w1, NULL);
|
||||||
if (!c1)
|
if (!c1)
|
||||||
break;
|
break;
|
||||||
if (c1 == c2)
|
if (c1 == c2)
|
||||||
|
@ -480,8 +491,8 @@ FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
c1t = FcStrCaseWalkerNext (&w1t);
|
c1t = FcStrCaseWalkerNext (&w1t, NULL);
|
||||||
c2t = FcStrCaseWalkerNext (&w2t);
|
c2t = FcStrCaseWalkerNext (&w2t, NULL);
|
||||||
|
|
||||||
if (!c2t)
|
if (!c2t)
|
||||||
return cur;
|
return cur;
|
||||||
|
|
Loading…
Reference in New Issue