From be0d1613f79a95073d18d96a60e1394abf9316a2 Mon Sep 17 00:00:00 2001 From: Rodger Combs Date: Thu, 11 Oct 2018 02:32:50 -0500 Subject: [PATCH] coretext: replace CT attr reads with freetype lookups This makes results much more consistent with other platforms, particularly around cases where fonts have multiple conflicting names. --- libass/ass_coretext.c | 136 ++++++++---------------------------------- 1 file changed, 24 insertions(+), 112 deletions(-) diff --git a/libass/ass_coretext.c b/libass/ass_coretext.c index 5885477..59a8a2d 100644 --- a/libass/ass_coretext.c +++ b/libass/ass_coretext.c @@ -103,118 +103,31 @@ static char *get_font_file(CTFontDescriptorRef fontd) return buffer; } -static void get_name(CTFontDescriptorRef fontd, CFStringRef attr, - char **array, int *idx) +static char *get_name(CTFontDescriptorRef fontd, CFStringRef attr) { - + char *ret = NULL; CFStringRef name = CTFontDescriptorCopyAttribute(fontd, attr); if (name) { - array[*idx] = cfstr2buf(name); + ret = cfstr2buf(name); SAFE_CFRelease(name); - *idx += 1; } + return ret; } -static void get_trait(CFDictionaryRef traits, CFStringRef attribute, - double *trait) -{ - CFNumberRef cftrait = CFDictionaryGetValue(traits, attribute); - *trait = 0.0; - CFNumberGetValue(cftrait, kCFNumberDoubleType, trait); -} - -// These are available as kCTFontWeightUltraLight, etc. in newer SDKs. -// For some reason they switched the terms "ultra light" and "thin" -#define FontWeightUltraLight -0.8 -#define FontWeightThin -0.6 -#define FontWeightLight -0.4 -#define FontWeightRegular 0 -#define FontWeightMedium 0.23 -#define FontWeightSemibold 0.3 -#define FontWeightBold 0.4 -#define FontWeightHeavy 0.56 -#define FontWeightBlack 0.62 - -#define AVG(x, y) ((x + y) / 2.) - -static void get_font_traits(CTFontDescriptorRef fontd, - ASS_FontProviderMetaData *meta) -{ - double weight, slant, width; - - CFDictionaryRef traits = - CTFontDescriptorCopyAttribute(fontd, kCTFontTraitsAttribute); - - get_trait(traits, kCTFontWeightTrait, &weight); - get_trait(traits, kCTFontSlantTrait, &slant); - get_trait(traits, kCTFontWidthTrait, &width); - - SAFE_CFRelease(traits); - - // Printed all of my system fonts (see if'deffed code below). Here is how - // CoreText 'normalized' weights maps to CSS/libass: - - // opentype: 0 100 200 300 400 500 600 700 800 900 - // css: LIGHT REG MED SBOLD BOLD BLACK EXTRABL - // libass: LIGHT MEDIUM BOLD - // coretext: -0.4 0.0 0.23 0.3 0.4 0.62 - - if (weight >= AVG(FontWeightHeavy, FontWeightBlack)) - meta->weight = 900; - else if (weight >= AVG(FontWeightBold, FontWeightHeavy)) - meta->weight = 800; - else if (weight >= AVG(FontWeightSemibold, FontWeightBold)) - meta->weight = 700; - else if (weight >= AVG(FontWeightMedium, FontWeightSemibold)) - meta->weight = 600; - else if (weight >= AVG(FontWeightRegular, FontWeightMedium)) - meta->weight = 500; - else if (weight >= AVG(FontWeightLight, FontWeightMedium)) - meta->weight = 400; - else if (weight >= AVG(FontWeightThin, FontWeightLight)) - meta->weight = 300; - else if (weight >= AVG(FontWeightUltraLight, FontWeightThin)) - meta->weight = 200; - else - meta->weight = 100; - - if (slant > 0.03) - meta->slant = FONT_SLANT_ITALIC; - else - meta->slant = FONT_SLANT_NONE; - - if (width <= -0.2) - meta->width = FONT_WIDTH_CONDENSED; - else if (width >= 0.2) - meta->width = FONT_WIDTH_EXPANDED; - else - meta->width = FONT_WIDTH_NORMAL; - -#if 0 - char *name[1]; - int idx = 0; - get_name(fontd, kCTFontDisplayNameAttribute, name, &idx); - char *file = get_font_file(fontd); - printf( - "Font traits for: %-40s [%-50s] " - ", , \n", - name[0], file, - slant, meta->slant, weight, meta->weight, width, meta->width); - free(name[0]); - free(file); -#endif -} - -static void process_descriptors(ASS_FontProvider *provider, CFArrayRef fontsd) +static void process_descriptors(ASS_Library *lib, ASS_FontProvider *provider, + CFArrayRef fontsd) { ASS_FontProviderMetaData meta; - char *families[1]; - char *identifiers[1]; - char *fullnames[1]; if (!fontsd) return; + FT_Library ftlib; + if (FT_Init_FreeType(&ftlib)) { + ass_msg(lib, MSGL_WARN, "Failed to create FT lib"); + return; + } + for (int i = 0; i < CFArrayGetCount(fontsd); i++) { CTFontDescriptorRef fontd = CFArrayGetValueAtIndex(fontsd, i); int index = -1; @@ -227,20 +140,13 @@ static void process_descriptors(ASS_FontProvider *provider, CFArrayRef fontsd) } memset(&meta, 0, sizeof(meta)); - get_font_traits(fontd, &meta); - - get_name(fontd, kCTFontFamilyNameAttribute, families, &meta.n_family); - meta.families = families; - get_name(fontd, kCTFontDisplayNameAttribute, fullnames, &meta.n_fullname); - meta.fullnames = fullnames; + char *ps_name = get_name(fontd, kCTFontNameAttribute); - int zero = 0; - get_name(fontd, kCTFontNameAttribute, identifiers, &zero); - meta.postscript_name = identifiers[0]; - - CFRetain(fontd); - ass_font_provider_add_font(provider, &meta, path, index, (void*)fontd); + if (ass_get_font_info(lib, ftlib, path, ps_name, -1, &meta)) { + CFRetain(fontd); + ass_font_provider_add_font(provider, &meta, path, index, (void*)fontd); + } for (int j = 0; j < meta.n_family; j++) free(meta.families[j]); @@ -248,10 +154,16 @@ static void process_descriptors(ASS_FontProvider *provider, CFArrayRef fontsd) for (int j = 0; j < meta.n_fullname; j++) free(meta.fullnames[j]); + free(meta.families); + free(meta.fullnames); + free(meta.postscript_name); + free(ps_name); free(path); } + + FT_Done_FreeType(ftlib); } static void match_fonts(ASS_Library *lib, ASS_FontProvider *provider, @@ -284,7 +196,7 @@ static void match_fonts(ASS_Library *lib, ASS_FontProvider *provider, CFArrayRef fontsd = CTFontCollectionCreateMatchingFontDescriptors(ctcoll); - process_descriptors(provider, fontsd); + process_descriptors(lib, provider, fontsd); SAFE_CFRelease(fontsd); SAFE_CFRelease(ctcoll); -- 2.40.0