From 2d2be3237d3422cd9ef7beebd1134b7cc5b3b474 Mon Sep 17 00:00:00 2001 From: Oleg Oshmyan Date: Sat, 27 Mar 2021 04:11:07 +0200 Subject: fontselect: coretext: ask Core Text for family name as last resort If a font contains no recognized Microsoft-platform family names, use the family name reported by Core Text. Skip FreeType's face->family_name because it is an ASCII bastardization of a family name and may not exist at all. --- libass/ass_coretext.c | 56 +++++++++++++++++++++++++++++++++++++++---------- libass/ass_fontselect.c | 40 ++++++++++++++++++++--------------- libass/ass_fontselect.h | 2 ++ 3 files changed, 70 insertions(+), 28 deletions(-) diff --git a/libass/ass_coretext.c b/libass/ass_coretext.c index b6870a6..49a96ff 100644 --- a/libass/ass_coretext.c +++ b/libass/ass_coretext.c @@ -125,6 +125,49 @@ static char *get_name(CTFontDescriptorRef fontd, CFStringRef attr) return ret; } +static bool fill_family_name(CTFontDescriptorRef fontd, + ASS_FontProviderMetaData *info) +{ + if (info->n_family) + return true; + + char *family_name = get_name(fontd, kCTFontFamilyNameAttribute); + if (!family_name) + return false; + + info->families = malloc(sizeof(char *)); + if (!info->families) { + free(family_name); + return false; + } + + info->families[0] = family_name; + info->n_family++; + return true; +} + +static bool get_font_info_ct(ASS_Library *lib, FT_Library ftlib, + CTFontDescriptorRef fontd, + char **path_out, + ASS_FontProviderMetaData *info) +{ + char *path = get_font_file(fontd); + *path_out = path; + if (!path || !*path) { + // skip the font if the URL field in the font descriptor is empty + return false; + } + + char *ps_name = get_name(fontd, kCTFontNameAttribute); + if (!ps_name) + return false; + + bool got_info = ass_get_font_info(lib, ftlib, path, ps_name, -1, false, info); + free(ps_name); + + return got_info && fill_family_name(fontd, info); +} + static void process_descriptors(ASS_Library *lib, FT_Library ftlib, ASS_FontProvider *provider, CFArrayRef fontsd) { @@ -136,16 +179,8 @@ static void process_descriptors(ASS_Library *lib, FT_Library ftlib, CTFontDescriptorRef fontd = CFArrayGetValueAtIndex(fontsd, i); int index = -1; - char *path = get_font_file(fontd); - if (!path || !*path) { - // skip the font if the URL field in the font descriptor is empty - free(path); - continue; - } - - char *ps_name = get_name(fontd, kCTFontNameAttribute); - - if (ass_get_font_info(lib, ftlib, path, ps_name, -1, &meta)) { + char *path = NULL; + if (get_font_info_ct(lib, ftlib, fontd, &path, &meta)) { CFRetain(fontd); ass_font_provider_add_font(provider, &meta, path, index, (void*)fontd); } @@ -161,7 +196,6 @@ static void process_descriptors(ASS_Library *lib, FT_Library ftlib, free(meta.postscript_name); - free(ps_name); free(path); } } diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c index b75920f..6b62511 100644 --- a/libass/ass_fontselect.c +++ b/libass/ass_fontselect.c @@ -756,7 +756,8 @@ char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library, * \return success */ static bool -get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info) +get_font_info(FT_Library lib, FT_Face face, bool require_family_name, + ASS_FontProviderMetaData *info) { int i; int num_fullname = 0; @@ -800,18 +801,20 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info) } - // check if we got a valid family - if not use whatever FreeType gives us - if (num_family == 0 && face->family_name) { - families[0] = strdup(face->family_name); - if (families[0] == NULL) + if (require_family_name) { + // check if we got a valid family - if not use whatever FreeType gives us + if (num_family == 0 && face->family_name) { + families[0] = strdup(face->family_name); + if (families[0] == NULL) + goto error; + num_family++; + } + + // we absolutely need a name + if (num_family == 0) goto error; - num_family++; } - // we absolutely need a name - if (num_family == 0) - goto error; - // calculate sensible slant and weight from style attributes slant = 110 * !!(face->style_flags & FT_STYLE_FLAG_ITALIC); weight = ass_face_get_weight(face); @@ -823,11 +826,13 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info) info->postscript_name = (char *)FT_Get_Postscript_Name(face); - info->families = calloc(sizeof(char *), num_family); - if (info->families == NULL) - goto error; - memcpy(info->families, &families, sizeof(char *) * num_family); - info->n_family = num_family; + if (num_family) { + info->families = calloc(sizeof(char *), num_family); + if (info->families == NULL) + goto error; + memcpy(info->families, &families, sizeof(char *) * num_family); + info->n_family = num_family; + } if (num_fullname) { info->fullnames = calloc(sizeof(char *), num_fullname); @@ -857,6 +862,7 @@ error: bool ass_get_font_info(ASS_Library *lib, FT_Library ftlib, const char *path, const char *postscript_name, int index, + bool require_family_name, ASS_FontProviderMetaData *info) { bool ret = false; @@ -887,7 +893,7 @@ bool ass_get_font_info(ASS_Library *lib, FT_Library ftlib, const char *path, } if (face) { - ret = get_font_info(ftlib, face, info); + ret = get_font_info(ftlib, face, require_family_name, info); if (ret) info->postscript_name = strdup(info->postscript_name); FT_Done_Face(face); @@ -952,7 +958,7 @@ static void process_fontdata(ASS_FontProvider *priv, ASS_Library *library, charmap_magic(library, face); memset(&info, 0, sizeof(ASS_FontProviderMetaData)); - if (!get_font_info(ftlibrary, face, &info)) { + if (!get_font_info(ftlibrary, face, true, &info)) { ass_msg(library, MSGL_WARN, "Error getting metadata for embedded font '%s'", name); FT_Done_Face(face); diff --git a/libass/ass_fontselect.h b/libass/ass_fontselect.h index 2cb5672..d029b0b 100644 --- a/libass/ass_fontselect.h +++ b/libass/ass_fontselect.h @@ -273,12 +273,14 @@ ass_font_provider_add_font(ASS_FontProvider *provider, * \param path the path to the font file to read * \param postscript_name the PS name of the specific face to read (set either this or index) * \param index the face index to read, or -1 if not applicable + * \param require_family_name whether to try a fallback family name and fail if none found * \param info the struct to store results into * \return success * */ bool ass_get_font_info(ASS_Library *lib, FT_Library ftlib, const char *path, const char *postscript_name, int index, + bool require_family_name, ASS_FontProviderMetaData *info); /** -- cgit v1.2.3