Browse Source

more robust SFNT name, support preferred family name

OSes will register the font with the preferred family name instead of
the family name if the preferred entry is present
master
Caleb Hearon 9 years ago
committed by Caleb Hearon
parent
commit
1abcbe5e2b
  1. 34
      src/register_font.cc

34
src/register_font.cc

@ -33,6 +33,9 @@
#define IS_PREFERRED_ENC(X) \ #define IS_PREFERRED_ENC(X) \
X.platform_id == PREFERRED_PLATFORM_ID && X.encoding_id == PREFERRED_ENCODING_ID X.platform_id == PREFERRED_PLATFORM_ID && X.encoding_id == PREFERRED_ENCODING_ID
#define GET_NAME_RANK(X) \
(IS_PREFERRED_ENC(X) ? 1 : 0) + (X.name_id == TT_NAME_ID_PREFERRED_FAMILY ? 1 : 0)
/* /*
* Return a UTF-8 encoded string given a TrueType name buf+len * Return a UTF-8 encoded string given a TrueType name buf+len
* and its platform and encoding * and its platform and encoding
@ -89,29 +92,42 @@ to_utf8(FT_Byte* buf, FT_UInt len, FT_UShort pid, FT_UShort eid) {
* system, fall back to the other * system, fall back to the other
*/ */
typedef struct _NameDef {
const char *buf;
int rank; // the higher the more desirable
} NameDef;
gint
_name_def_compare(gconstpointer a, gconstpointer b) {
return ((NameDef*)a)->rank > ((NameDef*)b)->rank ? -1 : 1;
}
char * char *
get_family_name(FT_Face face) { get_family_name(FT_Face face) {
FT_SfntName name; FT_SfntName name;
GList *list = NULL;
char *utf8name = NULL; char *utf8name = NULL;
for (unsigned i = 0; i < FT_Get_Sfnt_Name_Count(face); ++i) { for (unsigned i = 0; i < FT_Get_Sfnt_Name_Count(face); ++i) {
FT_Get_Sfnt_Name(face, i, &name); FT_Get_Sfnt_Name(face, i, &name);
if (name.name_id == TT_NAME_ID_FONT_FAMILY) { if (name.name_id == TT_NAME_ID_FONT_FAMILY || name.name_id == TT_NAME_ID_PREFERRED_FAMILY) {
char *utf8candidate = to_utf8(name.string, name.string_len, name.platform_id, name.encoding_id); char *buf = to_utf8(name.string, name.string_len, name.platform_id, name.encoding_id);
if (utf8candidate) { if (buf) {
if (utf8name) free(utf8name); NameDef *d = (NameDef*)malloc(sizeof(NameDef));
d->buf = (const char*)buf;
d->rank = GET_NAME_RANK(name);
if (IS_PREFERRED_ENC(name)) { list = g_list_insert_sorted(list, (gpointer)d, _name_def_compare);
return utf8candidate;
} else {
utf8name = utf8candidate;
}
} }
} }
} }
GList *best_def = g_list_first(list);
if (best_def) utf8name = (char*) strdup(((NameDef*)best_def->data)->buf);
if (list) g_list_free_full(list, free);
return utf8name; return utf8name;
} }

Loading…
Cancel
Save