summaryrefslogtreecommitdiffstats
path: root/libass/ass_coretext.c
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2021-03-27 04:12:58 +0200
committerOleg Oshmyan <chortos@inbox.lv>2021-04-29 03:18:15 +0300
commitdb85ef4736108c12bf3e12939447840815c246ec (patch)
tree6667d39c78164b4790f4f82e1d4d837ad64035be /libass/ass_coretext.c
parent2d2be3237d3422cd9ef7beebd1134b7cc5b3b474 (diff)
downloadlibass-db85ef4736108c12bf3e12939447840815c246ec.tar.bz2
libass-db85ef4736108c12bf3e12939447840815c246ec.tar.xz
fontselect: coretext: get fallback font family name via FreeType
Since commit be0d1613f79a95073d18d96a60e1394abf9316a2, get_fallback can return a name from Core Text that is different from all names that match_fonts registers for the same font. This causes font fallback to fail as find_fonts fails to find any font having the name received from get_fallback. (Moreover, libass will keep retrying fallback for other glyphs, and the coretext match_fonts will keep readding the same fonts over and over again.) Commit 152d0484e98f118d01987138695cf40579c9e297 attempted to fix font fallback by getting a full name from Core Text instead of a family name when it was noticed that Core Text's family name can come from TT_NAME_ID_TYPOGRAPHIC_FAMILY in addition to TT_NAME_ID_FONT_FAMILY, which we fetch in get_font_info, but the problem goes deeper: Core Text can return Macintosh-platform names that don't match Microsoft-platform names, or the font might have no Microsoft-platform names at all. Furthermore, returning a full name breaks style matching: get_fallback does not know about weight, slant etc. and is expected to return a whole family of fonts that will be lazy-loaded in its entirety (if applicable) and searched through for the best stylistic match by find_fonts. To fix fallback while preserving maximum name portability in the spirit of be0d1613f79a95073d18d96a60e1394abf9316a2, use the same API in get_fallback as is used in match_fonts to look up a family name. Note: this could be more efficient if ass_get_font_info could be told to return just an arbitrary family name. This fixes https://github.com/libass/libass/issues/457.
Diffstat (limited to 'libass/ass_coretext.c')
-rw-r--r--libass/ass_coretext.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/libass/ass_coretext.c b/libass/ass_coretext.c
index 49a96ff..f1063ba 100644
--- a/libass/ass_coretext.c
+++ b/libass/ass_coretext.c
@@ -246,8 +246,11 @@ static void match_fonts(void *priv, ASS_Library *lib, ASS_FontProvider *provider
SAFE_CFRelease(cfname);
}
-static char *get_fallback(void *priv, const char *family, uint32_t codepoint)
+static char *get_fallback(void *priv, ASS_Library *lib,
+ const char *family, uint32_t codepoint)
{
+ FT_Library ftlib = priv;
+
CFStringRef name = CFStringCreateWithBytes(
0, (UInt8 *)family, strlen(family), kCFStringEncodingUTF8, false);
CTFontRef font = CTFontCreateWithName(name, 0, NULL);
@@ -256,17 +259,32 @@ static char *get_fallback(void *priv, const char *family, uint32_t codepoint)
0, (UInt8*)&codepointle, sizeof(codepointle),
kCFStringEncodingUTF32LE, false);
CTFontRef fb = CTFontCreateForString(font, r, CFRangeMake(0, 1));
- CFNumberRef cfformat = CTFontCopyAttribute(fb, kCTFontFormatAttribute);
- CFStringRef cfname = is_postscript_font_format(cfformat) ?
- CTFontCopyPostScriptName(fb) : CTFontCopyFullName(fb);
- char *res_name = cfstr2buf(cfname);
+ CTFontDescriptorRef fontd = CTFontCopyFontDescriptor(fb);
+
+ char *res_name = NULL;
+ char *path = NULL;
+ ASS_FontProviderMetaData meta = {0};
+ if (get_font_info_ct(lib, ftlib, fontd, &path, &meta))
+ res_name = meta.families[0];
+
+ for (int i = 1 /* skip res_name */; i < meta.n_family; i++)
+ free(meta.families[i]);
+
+ for (int i = 0; i < meta.n_fullname; i++)
+ free(meta.fullnames[i]);
+
+ free(meta.families);
+ free(meta.fullnames);
+
+ free(meta.postscript_name);
+
+ free(path);
SAFE_CFRelease(name);
SAFE_CFRelease(font);
SAFE_CFRelease(r);
SAFE_CFRelease(fb);
- SAFE_CFRelease(cfformat);
- SAFE_CFRelease(cfname);
+ SAFE_CFRelease(fontd);
return res_name;
}