diff options
Diffstat (limited to 'libass')
-rw-r--r-- | libass/ass_coretext.c | 47 | ||||
-rw-r--r-- | libass/ass_directwrite.c | 80 | ||||
-rw-r--r-- | libass/ass_fontconfig.c | 23 | ||||
-rw-r--r-- | libass/ass_fontselect.c | 58 | ||||
-rw-r--r-- | libass/ass_fontselect.h | 11 |
5 files changed, 133 insertions, 86 deletions
diff --git a/libass/ass_coretext.c b/libass/ass_coretext.c index 2eacd92..1e74ad1 100644 --- a/libass/ass_coretext.c +++ b/libass/ass_coretext.c @@ -49,13 +49,29 @@ static char *cfstr2buf(CFStringRef string) static void destroy_font(void *priv) { - CFCharacterSetRef set = priv; - SAFE_CFRelease(set); + CTFontDescriptorRef fontd = priv; + SAFE_CFRelease(fontd); +} + +static bool check_postscript(void *priv) +{ + CTFontDescriptorRef fontd = priv; + CFNumberRef cfformat = + CTFontDescriptorCopyAttribute(fontd, kCTFontFormatAttribute); + int format; + + if (!CFNumberGetValue(cfformat, kCFNumberIntType, &format)) + return false; + + return format == kCTFontFormatOpenTypePostScript || + format == kCTFontFormatPostScript; } static bool check_glyph(void *priv, uint32_t code) { - CFCharacterSetRef set = priv; + CTFontDescriptorRef fontd = priv; + CFCharacterSetRef set = + CTFontDescriptorCopyAttribute(fontd, kCTFontCharacterSetAttribute); if (!set) return true; @@ -63,7 +79,9 @@ static bool check_glyph(void *priv, uint32_t code) if (code == 0) return true; - return CFCharacterSetIsLongCharacterMember(set, code); + bool result = CFCharacterSetIsLongCharacterMember(set, code); + SAFE_CFRelease(set); + return result; } static char *get_font_file(CTFontDescriptorRef fontd) @@ -88,19 +106,6 @@ static void get_name(CTFontDescriptorRef fontd, CFStringRef attr, } } -static bool is_postscript(CTFontDescriptorRef fontd) -{ - int format; - CFNumberRef cfformat = - CTFontDescriptorCopyAttribute(fontd, kCTFontFormatAttribute); - - if (!CFNumberGetValue(cfformat, kCFNumberIntType, &format)) - return false; - - return format == kCTFontFormatOpenTypePostScript || - format == kCTFontFormatPostScript; -} - static void get_trait(CFDictionaryRef traits, CFStringRef attribute, float *trait) { @@ -205,11 +210,8 @@ static void process_descriptors(ASS_FontProvider *provider, CFArrayRef fontsd) get_name(fontd, kCTFontNameAttribute, identifiers, &zero); meta.postscript_name = identifiers[0]; - meta.is_postscript = is_postscript(fontd); - - CFCharacterSetRef chset = - CTFontDescriptorCopyAttribute(fontd, kCTFontCharacterSetAttribute); - ass_font_provider_add_font(provider, &meta, path, index, (void*)chset); + 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]); @@ -297,6 +299,7 @@ static void get_substitutions(void *priv, const char *name, } static ASS_FontProviderFuncs coretext_callbacks = { + .check_postscript = check_postscript, .check_glyph = check_glyph, .destroy_font = destroy_font, .match_fonts = match_fonts, diff --git a/libass/ass_directwrite.c b/libass/ass_directwrite.c index cb21dd4..b0ee057 100644 --- a/libass/ass_directwrite.c +++ b/libass/ass_directwrite.c @@ -43,6 +43,7 @@ static const ASS_FontMapping font_substitutions[] = { */ typedef struct { IDWriteFont *font; + IDWriteFontFace *face; IDWriteFontFileStream *stream; } FontPrivate; @@ -224,15 +225,34 @@ static void init_FallbackLogTextRenderer(FallbackLogTextRenderer *r, } /* + * This function is called whenever a font is accessed for the + * first time. It will create a FontFace for metadata access and + * memory reading, which will be stored within the private data. + */ +static bool init_font_private_face(FontPrivate *priv) +{ + HRESULT hr; + IDWriteFontFace *face; + + if (priv->face != NULL) + return true; + + hr = IDWriteFont_CreateFontFace(priv->font, &face); + if (FAILED(hr) || !face) + return false; + + priv->face = face; + return true; +} + +/* * This function is called whenever a font is used for the first * time. It will create a FontStream for memory reading, which * will be stored within the private data. */ -static bool init_font_private(FontPrivate *priv) +static bool init_font_private_stream(FontPrivate *priv) { HRESULT hr = S_OK; - IDWriteFont *font = priv->font; - IDWriteFontFace *face = NULL; IDWriteFontFile *file = NULL; IDWriteFontFileStream *stream = NULL; IDWriteFontFileLoader *loader = NULL; @@ -243,41 +263,34 @@ static bool init_font_private(FontPrivate *priv) if (priv->stream != NULL) return true; - hr = IDWriteFont_CreateFontFace(font, &face); - if (FAILED(hr) || !face) + if (!init_font_private_face(priv)) return false; /* DirectWrite only supports one file per face */ - hr = IDWriteFontFace_GetFiles(face, &n_files, &file); - if (FAILED(hr) || !file) { - IDWriteFontFace_Release(face); + hr = IDWriteFontFace_GetFiles(priv->face, &n_files, &file); + if (FAILED(hr) || !file) return false; - } hr = IDWriteFontFile_GetReferenceKey(file, &refKey, &keySize); if (FAILED(hr)) { IDWriteFontFile_Release(file); - IDWriteFontFace_Release(face); return false; } hr = IDWriteFontFile_GetLoader(file, &loader); if (FAILED(hr) || !loader) { IDWriteFontFile_Release(file); - IDWriteFontFace_Release(face); return false; } hr = IDWriteFontFileLoader_CreateStreamFromKey(loader, refKey, keySize, &stream); if (FAILED(hr) || !stream) { IDWriteFontFile_Release(file); - IDWriteFontFace_Release(face); return false; } priv->stream = stream; IDWriteFontFile_Release(file); - IDWriteFontFace_Release(face); return true; } @@ -297,7 +310,7 @@ static size_t get_data(void *data, unsigned char *buf, size_t offset, const void *fileBuf = NULL; void *fragContext = NULL; - if (!init_font_private(priv)) + if (!init_font_private_stream(priv)) return 0; if (buf == NULL) { @@ -323,6 +336,22 @@ static size_t get_data(void *data, unsigned char *buf, size_t offset, } /* + * Check whether the font contains PostScript outlines. + */ +static bool check_postscript(void *data) +{ + FontPrivate *priv = (FontPrivate *) data; + + if (!init_font_private_face(priv)) + return false; + + DWRITE_FONT_FACE_TYPE type = IDWriteFontFace_GetType(priv->face); + return type == DWRITE_FONT_FACE_TYPE_CFF || + type == DWRITE_FONT_FACE_TYPE_RAW_CFF || + type == DWRITE_FONT_FACE_TYPE_TYPE1; +} + +/* * Check if the passed font has a specific unicode character. */ static bool check_glyph(void *data, uint32_t code) @@ -362,6 +391,8 @@ static void destroy_font(void *data) FontPrivate *priv = (FontPrivate *) data; IDWriteFont_Release(priv->font); + if (priv->face != NULL) + IDWriteFontFace_Release(priv->face); if (priv->stream != NULL) IDWriteFontFileStream_Release(priv->stream); @@ -482,24 +513,6 @@ static int map_width(enum DWRITE_FONT_STRETCH stretch) } } -static bool is_postscript(IDWriteFont *font) -{ - HRESULT hr = S_OK; - IDWriteFontFace *face = NULL; - DWRITE_FONT_FACE_TYPE type; - - hr = IDWriteFont_CreateFontFace(font, &face); - if (FAILED(hr) || !face) - return false; - - type = IDWriteFontFace_GetType(face); - IDWriteFontFace_Release(face); - - return type == DWRITE_FONT_FACE_TYPE_CFF || - type == DWRITE_FONT_FACE_TYPE_RAW_CFF || - type == DWRITE_FONT_FACE_TYPE_TYPE1; -} - static void add_font(IDWriteFont *font, IDWriteFontFamily *fontFamily, ASS_FontProvider *provider) { @@ -613,8 +626,6 @@ static void add_font(IDWriteFont *font, IDWriteFontFamily *fontFamily, } IDWriteLocalizedStrings_Release(familyNames); - meta.is_postscript = is_postscript(font); - FontPrivate *font_priv = (FontPrivate *) calloc(1, sizeof(*font_priv)); if (!font_priv) goto cleanup; @@ -698,6 +709,7 @@ static void get_substitutions(void *priv, const char *name, */ static ASS_FontProviderFuncs directwrite_callbacks = { .get_data = get_data, + .check_postscript = check_postscript, .check_glyph = check_glyph, .destroy_font = destroy_font, .destroy_provider = destroy_provider, diff --git a/libass/ass_fontconfig.c b/libass/ass_fontconfig.c index b3b7100..304598e 100644 --- a/libass/ass_fontconfig.c +++ b/libass/ass_fontconfig.c @@ -40,6 +40,20 @@ typedef struct fc_private { FcCharSet *fallback_chars; } ProviderPrivate; +static bool check_postscript(void *priv) +{ + FcPattern *pat = (FcPattern *)priv; + char *format; + + FcResult result = + FcPatternGetString(pat, FC_FONTFORMAT, 0, (FcChar8 **)&format); + if (result != FcResultMatch) + return false; + + return !strcmp(format, "Type 1") || !strcmp(format, "Type 42") || + !strcmp(format, "CID Type 1") || !strcmp(format, "CFF"); +} + static bool check_glyph(void *priv, uint32_t code) { FcPattern *pat = (FcPattern *)priv; @@ -86,7 +100,6 @@ static void scan_fonts(FcConfig *config, ASS_FontProvider *provider) FcBool outline; int index, weight; char *path; - char *format; char *fullnames[MAX_NAME]; char *families[MAX_NAME]; @@ -139,13 +152,6 @@ static void scan_fonts(FcConfig *config, ASS_FontProvider *provider) FcPatternGetString(pat, FC_POSTSCRIPT_NAME, 0, (FcChar8 **)&meta.postscript_name); - meta.is_postscript = false; - if (FcPatternGetString(pat, FC_FONTFORMAT, 0, - (FcChar8 **)&format) == FcResultMatch) - meta.is_postscript = - !strcmp(format, "Type 1") || !strcmp(format, "Type 42") || - !strcmp(format, "CID Type 1") || !strcmp(format, "CFF"); - ass_font_provider_add_font(provider, &meta, path, index, (void *)pat); } } @@ -268,6 +274,7 @@ cleanup: } static ASS_FontProviderFuncs fontconfig_callbacks = { + .check_postscript = check_postscript, .check_glyph = check_glyph, .destroy_provider = destroy, .get_substitutions = get_substitutions, diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c index e4be338..7f73529 100644 --- a/libass/ass_fontselect.c +++ b/libass/ass_fontselect.c @@ -70,7 +70,6 @@ struct font_info { char *postscript_name; // can be used as an alternative to index to // identify a font inside a collection - bool is_postscript; // font source ASS_FontProvider *provider; @@ -110,6 +109,13 @@ struct font_data_ft { int idx; }; +static bool check_postscript_ft(void *data) +{ + FontDataFT *fd = (FontDataFT *)data; + PS_FontInfoRec postscript_info; + return !FT_Get_PS_Font_Info(fd->face, &postscript_info); +} + static bool check_glyph_ft(void *data, uint32_t codepoint) { FontDataFT *fd = (FontDataFT *)data; @@ -149,13 +155,10 @@ get_data_embedded(void *data, unsigned char *buf, size_t offset, size_t len) } static ASS_FontProviderFuncs ft_funcs = { - get_data_embedded, - check_glyph_ft, - destroy_font_ft, - NULL, - NULL, - NULL, - NULL + .get_data = get_data_embedded, + .check_postscript = check_postscript_ft, + .check_glyph = check_glyph_ft, + .destroy_font = destroy_font_ft, }; static void load_fonts_from_dir(ASS_Library *library, const char *dir) @@ -302,7 +305,6 @@ ass_font_provider_add_font(ASS_FontProvider *provider, info->width = width; info->n_fullname = meta->n_fullname; info->n_family = meta->n_family; - info->is_postscript = meta->is_postscript; info->families = calloc(meta->n_family, sizeof(char *)); if (info->families == NULL) @@ -406,6 +408,14 @@ void ass_font_provider_free(ASS_FontProvider *provider) free(provider); } +static bool check_postscript(ASS_FontInfo *fi) +{ + ASS_FontProvider *provider = fi->provider; + assert(provider && provider->funcs.check_postscript); + + return provider->funcs.check_postscript(fi->priv); +} + /** * \brief Return whether the given font is in the given family. */ @@ -425,17 +435,27 @@ static bool matches_family_name(ASS_FontInfo *f, const char *family) static bool matches_full_or_postscript_name(ASS_FontInfo *f, const char *fullname) { - if (f->is_postscript) { - if (f->postscript_name != NULL && - ass_strcasecmp(f->postscript_name, fullname) == 0) - return true; - } else { - for (int i = 0; i < f->n_fullname; i++) { - if (ass_strcasecmp(f->fullnames[i], fullname) == 0) - return true; + bool matches_fullname = false; + bool matches_postscript_name = false; + + for (int i = 0; i < f->n_fullname; i++) { + if (ass_strcasecmp(f->fullnames[i], fullname) == 0) { + matches_fullname = true; + break; } } - return false; + + if (f->postscript_name != NULL && + ass_strcasecmp(f->postscript_name, fullname) == 0) + matches_postscript_name = true; + + if (matches_fullname == matches_postscript_name) + return matches_fullname; + + if (check_postscript(f)) + return matches_postscript_name; + else + return matches_fullname; } /** @@ -730,7 +750,6 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info) int slant, weight; char *fullnames[MAX_FULLNAME]; char *families[MAX_FULLNAME]; - PS_FontInfoRec postscript_info; // we're only interested in outlines if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) @@ -788,7 +807,6 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info) info->width = 100; // FIXME, should probably query the OS/2 table info->postscript_name = (char *)FT_Get_Postscript_Name(face); - info->is_postscript = !FT_Get_PS_Font_Info(face, &postscript_info); info->families = calloc(sizeof(char *), num_family); if (info->families == NULL) diff --git a/libass/ass_fontselect.h b/libass/ass_fontselect.h index eceb2f0..73d5265 100644 --- a/libass/ass_fontselect.h +++ b/libass/ass_fontselect.h @@ -54,6 +54,14 @@ typedef size_t (*GetDataFunc)(void *font_priv, unsigned char *data, size_t offset, size_t len); /** + * Check whether the font contains PostScript outlines. + * + * \param font_priv font private data + * \return true if the font contains PostScript outlines + */ +typedef bool (*CheckPostscriptFunc)(void *font_priv); + +/** * Check if a glyph is supported by a font. * * \param font_priv font private data @@ -135,6 +143,7 @@ typedef char *(*GetFallbackFunc)(void *priv, typedef struct font_provider_funcs { GetDataFunc get_data; /* optional/mandatory */ + CheckPostscriptFunc check_postscript; /* mandatory */ CheckGlyphFunc check_glyph; /* mandatory */ DestroyFontFunc destroy_font; /* optional */ DestroyProviderFunc destroy_provider; /* optional */ @@ -172,8 +181,6 @@ struct ass_font_provider_meta_data { // See FONT_WEIGHT_* int width; // Font weight in percent, normally 100 // See FONT_WIDTH_* - - bool is_postscript; // Whether the font contains PostScript outlines }; typedef struct ass_font_stream ASS_FontStream; |