FcChar8 *style = 0;
int st;
+ char psname[256];
+ const char *tmp;
FcChar8 *hashstr;
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)
++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;
}
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)
{
FcLangResult result;
#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)
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),
}
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;
do
{
r = *w->src++;
- } while (r == ' ');
+ } while (r != 0 && delims && strchr (delims, r));
if ((r & 0xc0) == 0xc0)
return FcStrCaseWalkerLong (w, r);
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;
}
for (;;)
{
- c1 = FcStrCaseWalkerNext (&w1);
- c2 = FcStrCaseWalkerNext (&w2);
+ c1 = FcStrCaseWalkerNext (&w1, NULL);
+ c2 = FcStrCaseWalkerNext (&w2, NULL);
if (!c1 || (c1 != c2))
break;
}
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;
for (;;)
{
- c1 = FcStrCaseWalkerNextIgnoreBlanks (&w1);
- c2 = FcStrCaseWalkerNextIgnoreBlanks (&w2);
+ c1 = FcStrCaseWalkerNext (&w1, (const char *)delims);
+ c2 = FcStrCaseWalkerNext (&w2, (const char *)delims);
if (!c1 || (c1 != c2))
break;
}
FcChar8 c;
FcStrCaseWalkerInit (s, &w);
- while ((c = FcStrCaseWalkerNext (&w)))
+ while ((c = FcStrCaseWalkerNext (&w, NULL)))
h = ((h << 3) ^ (h >> 3)) ^ c;
return h;
}
for (;;)
{
- c1 = FcStrCaseWalkerNextIgnoreBlanks (&w1);
- c2 = FcStrCaseWalkerNextIgnoreBlanks (&w2);
+ c1 = FcStrCaseWalkerNext (&w1, " ");
+ c2 = FcStrCaseWalkerNext (&w2, " ");
if (!c1 || (c1 != c2))
break;
}
for (;;)
{
- c1 = FcStrCaseWalkerNext (&w1);
- c2 = FcStrCaseWalkerNext (&w2);
+ c1 = FcStrCaseWalkerNext (&w1, NULL);
+ c2 = FcStrCaseWalkerNext (&w2, NULL);
if (!c1 || (c1 != c2))
break;
}
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)
{
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)
for (;;)
{
- c1t = FcStrCaseWalkerNext (&w1t);
- c2t = FcStrCaseWalkerNext (&w2t);
+ c1t = FcStrCaseWalkerNext (&w1t, NULL);
+ c2t = FcStrCaseWalkerNext (&w2t, NULL);
if (!c2t)
return cur;