diff options
author | Stefano Pigozzi <stefano.pigozzi@gmail.com> | 2013-11-02 12:07:07 +0100 |
---|---|---|
committer | Grigori Goronzy <greg@chown.ath.cx> | 2015-07-10 10:42:40 +0200 |
commit | 9014b275e9e90d796bee95249a6059e4a55f3cf9 (patch) | |
tree | cb8972dc534a88fd4dc2bf3ee88a0735cdc53035 | |
parent | d9585a81add0a41f6a59f3c7f95bcc6182732059 (diff) | |
download | libass-9014b275e9e90d796bee95249a6059e4a55f3cf9.tar.bz2 libass-9014b275e9e90d796bee95249a6059e4a55f3cf9.tar.xz |
fontselect: coretext: allow selection based on PostScript name
Up until now fontselect used the face index to identify which font to load
from a font collection. While this pretty convenient when using something
freetype based like fontconfig, it seems to be somewhat freetype specific.
CoreText uses the PostScript name as the unique identifier of a font. This
commit allows to use that instead of the index to decide which face to open
with FT_New_Face. To use the PostScript name the provider must return a -1
index and the PostScript name.
-rw-r--r-- | libass/ass.h | 3 | ||||
-rw-r--r-- | libass/ass_coretext.c | 15 | ||||
-rw-r--r-- | libass/ass_font.c | 24 | ||||
-rw-r--r-- | libass/ass_fontconfig.c | 3 | ||||
-rw-r--r-- | libass/ass_fontselect.c | 50 | ||||
-rw-r--r-- | libass/ass_fontselect.h | 4 |
6 files changed, 68 insertions, 31 deletions
diff --git a/libass/ass.h b/libass/ass.h index d6728ed..1f8a506 100644 --- a/libass/ass.h +++ b/libass/ass.h @@ -453,6 +453,7 @@ ass_create_font_provider(ASS_Renderer *priv, ASS_FontProviderFuncs *funcs, * \param meta font metadata. See struct definition for more information. * \param path absolute path to font, or NULL for memory-based fonts * \param index index inside a font collection file + * \param psname PostScript name of the face (overrides index if present) * \param data private data for font callbacks * \return success * @@ -460,7 +461,7 @@ ass_create_font_provider(ASS_Renderer *priv, ASS_FontProviderFuncs *funcs, int ass_font_provider_add_font(ASS_FontProvider *provider, ASS_FontProviderMetaData *meta, const char *path, - unsigned int index, void *data); + unsigned int index, const char *psname, void *data); /** * \brief Free font provider and associated fonts. diff --git a/libass/ass_coretext.c b/libass/ass_coretext.c index f970226..802b511 100644 --- a/libass/ass_coretext.c +++ b/libass/ass_coretext.c @@ -32,7 +32,7 @@ static char *cfstr2buf(CFStringRef string) return strdup(buf_ptr); } else { size_t buf_len = CFStringGetLength(string) + 1; - char *buf = calloc(buf_len, sizeof(char)); + char *buf = malloc(buf_len); CFStringGetCString(string, buf, buf_len, kCFStringEncodingUTF8); return buf; } @@ -153,14 +153,15 @@ static void scan_fonts(ASS_Library *lib, ASS_FontProvider *provider) { ASS_FontProviderMetaData meta; char *families[1]; - char *fullnames[2]; + char *identifiers[1]; + char *fullnames[1]; CTFontCollectionRef coll = CTFontCollectionCreateFromAvailableFonts(NULL); CFArrayRef fontsd = CTFontCollectionCreateMatchingFontDescriptors(coll); for (int i = 0; i < CFArrayGetCount(fontsd); i++) { CTFontDescriptorRef fontd = CFArrayGetValueAtIndex(fontsd, i); - int index = 0; + int index = -1; char *path = get_font_file(fontd); if (strcmp("", path) == 0) { @@ -175,13 +176,15 @@ static void scan_fonts(ASS_Library *lib, ASS_FontProvider *provider) get_name(fontd, kCTFontFamilyNameAttribute, families, &meta.n_family); meta.families = families; + int zero = 0; + get_name(fontd, kCTFontNameAttribute, identifiers, &zero); get_name(fontd, kCTFontDisplayNameAttribute, fullnames, &meta.n_fullname); - get_name(fontd, kCTFontNameAttribute, fullnames, &meta.n_fullname); meta.fullnames = fullnames; CFCharacterSetRef chset = CTFontDescriptorCopyAttribute(fontd, kCTFontCharacterSetAttribute); - ass_font_provider_add_font(provider, &meta, path, index, (void*)chset); + ass_font_provider_add_font(provider, &meta, path, index, + identifiers[0], (void*)chset); for (int j = 0; j < meta.n_family; j++) free(meta.families[j]); @@ -189,6 +192,8 @@ static void scan_fonts(ASS_Library *lib, ASS_FontProvider *provider) for (int j = 0; j < meta.n_fullname; j++) free(meta.fullnames[j]); + free(identifiers[0]); + free(path); } diff --git a/libass/ass_font.c b/libass/ass_font.c index 0b6d24b..9a81dca 100644 --- a/libass/ass_font.c +++ b/libass/ass_font.c @@ -135,6 +135,7 @@ close_stream_font(FT_Stream stream) static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch) { char *path; + char *postscript_name; int i, index, uid, error; ASS_FontStream stream = { NULL, NULL }; FT_Face face; @@ -142,8 +143,8 @@ static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch) if (font->n_faces == ASS_FONT_MAX_FACES) return -1; - path = ass_font_select(fontsel, font->library, font , &index, &uid, - &stream, ch); + path = ass_font_select(fontsel, font->library, font , &index, + &postscript_name, &uid, &stream, ch); if (!path) return -1; @@ -191,6 +192,25 @@ static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch) free(path); return -1; } + + if (postscript_name && index < 0 && face->num_faces > 0) { + // The font provider gave us a post_script name and is not sure + // about the face index.. so use the postscript name to find the + // correct face_index in the collection! + for (int i = 0; face->num_faces; i++) { + FT_Done_Face(face); + error = FT_New_Face(font->ftlibrary, path, i, &face); + if (error) { + ass_msg(font->library, MSGL_WARN, + "Error opening font: '%s', %d", path, i); + free(path); + return -1; + } + + if (strcmp(FT_Get_Postscript_Name(face), postscript_name) == 0) + break; + } + } } charmap_magic(font->library, face); diff --git a/libass/ass_fontconfig.c b/libass/ass_fontconfig.c index 6080359..4fefa23 100644 --- a/libass/ass_fontconfig.c +++ b/libass/ass_fontconfig.c @@ -120,7 +120,8 @@ static void scan_fonts(FcConfig *config, ASS_FontProvider *provider) meta.n_fullname++; meta.fullnames = fullnames; - ass_font_provider_add_font(provider, &meta, path, index, (void *)pat); + ass_font_provider_add_font(provider, &meta, path, index, NULL, + (void *)pat); } } diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c index 9ef0ace..799ad02 100644 --- a/libass/ass_fontselect.c +++ b/libass/ass_fontselect.c @@ -68,8 +68,10 @@ struct font_info { int width; // how to access this face - char *path; // absolute path - int index; // font index inside font collections + char *path; // absolute path + int index; // font index inside font collections + char *postscript_name; // can be used as an alternative to index to + // identify a font inside a collection // similarity score unsigned score; @@ -219,13 +221,14 @@ ass_font_provider_new(ASS_FontSelector *selector, ASS_FontProviderFuncs *funcs, * \param meta basic metadata of the font * \param path path to the font file, or NULL * \param index face index inside the file + * \param psname PostScript name of the face (overrides index if present) * \param data private data for the font * \return success */ int ass_font_provider_add_font(ASS_FontProvider *provider, ASS_FontProviderMetaData *meta, const char *path, - unsigned int index, void *data) + unsigned int index, const char *psname, void *data) { int i; int weight, slant, width; @@ -275,6 +278,9 @@ ass_font_provider_add_font(ASS_FontProvider *provider, if (path) info->path = strdup(path); + if (psname) + info->postscript_name = strdup(psname); + info->index = index; info->priv = data; info->provider = provider; @@ -331,6 +337,9 @@ void ass_font_provider_free(ASS_FontProvider *provider) if (info->path) free(info->path); + if (info->postscript_name) + free(info->postscript_name); + if (info->provider->funcs.destroy_font) info->provider->funcs.destroy_font(info->priv); @@ -451,8 +460,8 @@ static int font_info_compare(const void *av, const void *bv) static char *select_font(ASS_FontSelector *priv, ASS_Library *library, const char *family, unsigned bold, unsigned italic, - int *index, int *uid, ASS_FontStream *stream, - uint32_t code) + int *index, char **postscript_name, int *uid, + ASS_FontStream *stream, uint32_t code) { int num_fonts = priv->n_font; int idx = 0; @@ -494,6 +503,7 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library, free(req.fullnames[0]); + *postscript_name = font_infos[idx].postscript_name; *index = font_infos[idx].index; *uid = font_infos[idx].uid; @@ -526,8 +536,8 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library, * \return font file path */ char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library, - ASS_Font *font, int *index, int *uid, - ASS_FontStream *data, uint32_t code) + ASS_Font *font, int *index, char **postscript_name, + int *uid, ASS_FontStream *data, uint32_t code) { char *res = 0; const char *family = font->desc.family; @@ -535,41 +545,41 @@ char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library, unsigned italic = font->desc.italic; if (family && *family) - res = select_font(priv, library, family, bold, italic, index, uid, - data, code); + res = select_font(priv, library, family, bold, italic, index, + postscript_name, uid, data, code); if (!res && priv->family_default) { res = select_font(priv, library, priv->family_default, bold, - italic, index, uid, data, code); + italic, index, postscript_name, uid, data, code); if (res) ass_msg(library, MSGL_WARN, "fontselect: Using default " - "font family: (%s, %d, %d) -> %s, %d", - family, bold, italic, res, *index); + "font family: (%s, %d, %d) -> %s, %d, %s", + family, bold, italic, res, *index, *postscript_name); } if (!res && priv->path_default) { res = strdup(priv->path_default); *index = priv->index_default; ass_msg(library, MSGL_WARN, "fontselect: Using default font: " - "(%s, %d, %d) -> %s, %d", family, bold, italic, - res, *index); + "(%s, %d, %d) -> %s, %d, %s", family, bold, italic, + res, *index, *postscript_name); } // FIXME: not sure if that is needed, we cannot reach this path at the // moment, either select_font returns or a font or the default one is used if (!res) { res = select_font(priv, library, "Arial", bold, italic, - index, uid, data, code); + index, postscript_name, uid, data, code); if (res) ass_msg(library, MSGL_WARN, "fontselect: Using 'Arial' " - "font family: (%s, %d, %d) -> %s, %d", family, bold, - italic, res, *index); + "font family: (%s, %d, %d) -> %s, %d, %s", family, bold, + italic, res, *index, *postscript_name); } if (res) ass_msg(library, MSGL_V, - "fontselect: (%s, %d, %d) -> %s, %d", family, bold, - italic, res, *index); + "fontselect: (%s, %d, %d) -> %s, %d, %s", family, bold, + italic, res, *index, *postscript_name); return res; } @@ -753,7 +763,7 @@ static void process_fontdata(ASS_FontProvider *priv, ASS_Library *library, ft->name = strdup(name); ft->idx = -1; - ass_font_provider_add_font(priv, &info, NULL, face_index, ft); + ass_font_provider_add_font(priv, &info, NULL, face_index, NULL, ft); free_font_info(&info); FT_Done_Face(face); diff --git a/libass/ass_fontselect.h b/libass/ass_fontselect.h index e080ab0..c1371dd 100644 --- a/libass/ass_fontselect.h +++ b/libass/ass_fontselect.h @@ -36,8 +36,8 @@ ass_fontselect_init(ASS_Library *library, FT_Library ftlibrary, const char *family, const char *path, const char *config, int fc); char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library, - ASS_Font *font, int *index, int *uid, - ASS_FontStream *data, uint32_t code); + ASS_Font *font, int *index, char **postscript_name, + int *uid, ASS_FontStream *data, uint32_t code); void ass_fontselect_free(ASS_FontSelector *priv); // Font provider functions |