]> granicus.if.org Git - libass/commitdiff
fontselect: coretext: allow selection based on PostScript name
authorStefano Pigozzi <stefano.pigozzi@gmail.com>
Sat, 2 Nov 2013 11:07:07 +0000 (12:07 +0100)
committerGrigori Goronzy <greg@chown.ath.cx>
Fri, 10 Jul 2015 08:42:40 +0000 (10:42 +0200)
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.

libass/ass.h
libass/ass_coretext.c
libass/ass_font.c
libass/ass_fontconfig.c
libass/ass_fontselect.c
libass/ass_fontselect.h

index d6728eddbd1a8f0c7ae8869ad9052dc8873272b1..1f8a506bb7eb2bdc0ebabcb3a509c938dc6f9cee 100644 (file)
@@ -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.
index f970226dccc4ed1ba7b21ccaa5f74fa3070c1022..802b511893e688fa84ca5ccf716e28f1feafacec 100644 (file)
@@ -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);
     }
 
index 0b6d24bc11bbf021999103f578741f8c8f5989b0..9a81dca7cd6429bf5b7a3959be69d224d61f5122 100644 (file)
@@ -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);
index 6080359c4bf7581c9ff9c748531a832cf1e3cb54..4fefa23d2a7eee211e75607907d575693ec76930 100644 (file)
@@ -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);
     }
 }
 
index 9ef0acef12a88fd28fb5e63e31ef45ca51cc6067..799ad02d61ffc8ff9d3dd02cc66faf4e6b0f15b7 100644 (file)
@@ -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);
index e080ab029a43cf06f8f3ca55d844b7379f6b8a26..c1371ddc2ffbe3fc66de66c823c2756a9367408b 100644 (file)
@@ -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