Skip to content

Commit

Permalink
select fonts via postscript name on Linux
Browse files Browse the repository at this point in the history
greatly improves font matching accuracy

Fixes Automattic#1572
  • Loading branch information
chearon committed Aug 7, 2021
1 parent 205319c commit d921b83
Showing 1 changed file with 53 additions and 2 deletions.
55 changes: 53 additions & 2 deletions src/register_font.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <windows.h>
#else
#include <fontconfig/fontconfig.h>
#include <pango/pangofc-fontmap.h>
#endif

#include <ft2build.h>
Expand All @@ -36,8 +37,19 @@
#define IS_PREFERRED_ENC(X) \
X.platform_id == PREFERRED_PLATFORM_ID && X.encoding_id == PREFERRED_ENCODING_ID

#if defined(__APPLE) || defined(_WIN32)
#define GET_NAME_RANK(X) \
(IS_PREFERRED_ENC(X) ? 1 : 0) + (X.name_id == TT_NAME_ID_PREFERRED_FAMILY ? 1 : 0)
((IS_PREFERRED_ENC(X) ? 1 : 0) << 1) | \
(X.name_id == TT_NAME_ID_PREFERRED_FAMILY ? 1 : 0)
#else
// On Linux-like OSes using FontConfig, the PostScript name ranks higher than
// preferred family and family name since we'll use it to get perfect font
// matching (see fc_font_map_substitute_hook)
#define GET_NAME_RANK(X) \
((IS_PREFERRED_ENC(X) ? 1 : 0) << 2) | \
((X.name_id == TT_NAME_ID_PS_NAME ? 1 : 0) << 1) | \
(X.name_id == TT_NAME_ID_PREFERRED_FAMILY ? 1 : 0)
#endif

/*
* Return a UTF-8 encoded string given a TrueType name buf+len
Expand Down Expand Up @@ -105,7 +117,13 @@ get_family_name(FT_Face face) {
for (unsigned i = 0; i < FT_Get_Sfnt_Name_Count(face); ++i) {
FT_Get_Sfnt_Name(face, i, &name);

if (name.name_id == TT_NAME_ID_FONT_FAMILY || name.name_id == TT_NAME_ID_PREFERRED_FAMILY) {
if (
name.name_id == TT_NAME_ID_FONT_FAMILY ||
#if !defined(__APPLE) && !defined(_WIN32)
name.name_id == TT_NAME_ID_PS_NAME ||
#endif
name.name_id == TT_NAME_ID_PREFERRED_FAMILY
) {
char *buf = to_utf8(name.string, name.string_len, name.platform_id, name.encoding_id);

if (buf) {
Expand All @@ -114,6 +132,18 @@ get_family_name(FT_Face face) {
best_rank = rank;
if (best_buf) free(best_buf);
best_buf = buf;

#if !defined(__APPLE) && !defined(_WIN32)
// Prepend an '@' to the family name
if (name.name_id == TT_NAME_ID_PS_NAME) {
size_t len = strlen(buf);
best_buf = (char *)malloc(len + 2);
best_buf[0] = '@';
strncpy(best_buf + 1, buf, len);
best_buf[len + 1] = '\0';
free(buf);
}
#endif
} else {
free(buf);
}
Expand Down Expand Up @@ -210,6 +240,21 @@ get_pango_font_description(unsigned char* filepath) {
return NULL;
}

#if !defined(__APPLE) && !defined(_WIN32)
static void
fc_font_map_substitute_hook(FcPattern *pat, gpointer data) {
FcChar8 *family;

for (int i = 0; FcPatternGetString(pat, FC_FAMILY, i, &family) == FcResultMatch; i++) {
if (family[0] == '@') {
FcPatternAddString(pat, FC_POSTSCRIPT_NAME, (FcChar8 *)family + 1);
FcPatternRemove(pat, FC_FAMILY, i);
i -= 1;
}
}
}
#endif

/*
* Register font with the OS
*/
Expand All @@ -234,6 +279,12 @@ register_font(unsigned char *filepath) {
// font families.
pango_cairo_font_map_set_default(NULL);

#if !defined(__APPLE) && !defined(_WIN32)
PangoFontMap* map = pango_cairo_font_map_get_default();
PangoFcFontMap* fc_map = PANGO_FC_FONT_MAP(map);
pango_fc_font_map_set_default_substitute(fc_map, fc_font_map_substitute_hook, NULL, NULL);
#endif

return true;
}

Expand Down

0 comments on commit d921b83

Please sign in to comment.