summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/fcfreetype.c293
1 files changed, 185 insertions, 108 deletions
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 36f5aed4..9302aed1 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1136,30 +1136,65 @@ 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)
+typedef struct
+{
+ unsigned int platform_id;
+ unsigned int name_id;
+ unsigned int encoding_id;
+ unsigned int language_id;
+ unsigned int idx;
+} FcNameMapping;
+
+static int
+name_mapping_cmp (const void *pa, const void *pb)
{
- int min = 0, max = (int) FT_Get_Sfnt_Name_Count (face) - 1;
+ const FcNameMapping *a = (const FcNameMapping *) pa;
+ const FcNameMapping *b = (const FcNameMapping *) pb;
+
+ if (a->platform_id != b->platform_id) return (int) a->platform_id - (int) b->platform_id;
+ if (a->name_id != b->name_id) return (int) a->name_id - (int) b->name_id;
+ if (a->encoding_id != b->encoding_id) return (int) a->encoding_id - (int) b->encoding_id;
+ if (a->language_id != b->language_id) return (int) a->language_id - (int) b->language_id;
+ if (a->idx != b->idx) return (int) a->idx - (int) b->idx;
+
+ return 0;
+}
+
+static int
+FcFreeTypeGetFirstName (const FT_Face face,
+ unsigned int platform,
+ unsigned int nameid,
+ FcNameMapping *mapping,
+ unsigned int count,
+ FT_SfntName *sname)
+{
+ int min = 0, max = (int) count - 1;
while (min <= max)
{
int mid = (min + max) / 2;
- if (FT_Get_Sfnt_Name (face, mid, sname) != 0)
+ if (FT_Get_Sfnt_Name (face, mapping[mid].idx, sname) != 0)
return FcFalse;
- if (platform < sname->platform_id || (platform == sname->platform_id && nameid < sname->name_id))
+ if (platform < sname->platform_id ||
+ (platform == sname->platform_id &&
+ (nameid < sname->name_id ||
+ (nameid == sname->name_id &&
+ (mid &&
+ platform == mapping[mid - 1].platform_id &&
+ nameid == mapping[mid - 1].name_id
+ )))))
max = mid - 1;
- else if (platform > sname->platform_id || (platform == sname->platform_id && nameid > sname->name_id))
+ else if (platform > sname->platform_id ||
+ (platform == sname->platform_id &&
+ nameid > sname->name_id))
min = mid + 1;
else
- return FcTrue;
+ return mid;
}
- return FcFalse;
+ return -1;
}
static FcPattern *
@@ -1180,6 +1215,7 @@ FcFreeTypeQueryFaceInternal (const FT_Face face,
FcBool variable_size = FcFalse;
FcCharSet *cs;
FcLangSet *ls;
+ FcNameMapping *name_mapping = 0;
#if 0
FcChar8 *family = 0;
#endif
@@ -1203,6 +1239,7 @@ FcFreeTypeQueryFaceInternal (const FT_Face face,
TT_Header *head;
const FcChar8 *exclusiveLang = 0;
+ int name_count = 0;
int nfamily = 0;
int nfamily_lang = 0;
int nstyle = 0;
@@ -1369,6 +1406,36 @@ FcFreeTypeQueryFaceInternal (const FT_Face face,
* and style names. FreeType makes quite a hash
* of them
*/
+ name_count = FT_Get_Sfnt_Name_Count (face);
+ if (!name_mapping)
+ {
+ int i = 0;
+ name_mapping = malloc (name_count * sizeof (FcNameMapping));
+ if (!name_mapping)
+ name_count = 0;
+ for (i = 0; i < name_count; i++)
+ {
+ FcNameMapping *p = &name_mapping[i];
+ FT_SfntName sname;
+ if (FT_Get_Sfnt_Name (face, i, &sname) == 0)
+ {
+ p->platform_id = sname.platform_id;
+ p->name_id = sname.name_id;
+ p->encoding_id = sname.encoding_id;
+ p->language_id = sname.language_id;
+ p->idx = i;
+ }
+ else
+ {
+ p->platform_id =
+ p->name_id =
+ p->encoding_id =
+ p->language_id =
+ p->idx = (unsigned int) -1;
+ }
+ }
+ qsort (name_mapping, name_count, sizeof(FcNameMapping), name_mapping_cmp);
+ }
for (p = 0; p < NUM_PLATFORM_ORDER; p++)
{
int platform = platform_order[p];
@@ -1380,6 +1447,7 @@ FcFreeTypeQueryFaceInternal (const FT_Face face,
for (n = 0; n < NUM_NAMEID_ORDER; n++)
{
FT_SfntName sname;
+ int nameidx;
const FcChar8 *lang;
const char *elt = 0, *eltlang = 0;
int *np = 0, *nlangp = 0;
@@ -1401,119 +1469,128 @@ FcFreeTypeQueryFaceInternal (const FT_Face face,
lookupid = instance->strid;
}
- if (!FcFreeTypeGetName (face, platform, lookupid, &sname))
+ nameidx = FcFreeTypeGetFirstName (face, platform, lookupid,
+ name_mapping, name_count,
+ &sname);
+ if (nameidx == -1)
continue;
-
- switch (nameid) {
- case TT_NAME_ID_WWS_FAMILY:
- case TT_NAME_ID_PREFERRED_FAMILY:
- case TT_NAME_ID_FONT_FAMILY:
+ do
+ {
+ switch (nameid) {
+ case TT_NAME_ID_WWS_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;
- case TT_NAME_ID_WWS_SUBFAMILY:
- case TT_NAME_ID_PREFERRED_SUBFAMILY:
- case TT_NAME_ID_FONT_SUBFAMILY:
- if (variable)
+ 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;
+ case TT_NAME_ID_WWS_SUBFAMILY:
+ 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);
+ }
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);
}
- 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 == ' ')
- 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))
+ if (elt)
{
- free (utf8);
- continue;
- }
+ FcChar8 *utf8, *pp;
- /* add new element */
- if (!FcPatternAddString (pat, elt, 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;
+ }
+
+ /* add new element */
+ if (!FcPatternAddString (pat, elt, utf8))
+ {
+ free (utf8);
+ goto bail1;
+ }
free (utf8);
- goto bail1;
- }
- free (utf8);
- if (lang)
- {
- /* pad lang list with 'und' to line up with elt */
- while (*nlangp < *np)
+ if (lang)
{
- if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "und"))
+ /* 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))
goto bail1;
++*nlangp;
}
- if (!FcPatternAddString (pat, eltlang, lang))
- goto bail1;
- ++*nlangp;
+ ++*np;
}
- ++*np;
}
+ while (++nameidx < name_count &&
+ FT_Get_Sfnt_Name (face, name_mapping[nameidx].idx, &sname) == 0 &&
+ platform == sname.platform_id && lookupid == sname.name_id);
}
}
+ free (name_mapping);
if (!nfamily && face->family_name &&
FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->family_name, (FcChar8 *) "") != 0)