]> granicus.if.org Git - libass/commitdiff
fontselect: find fonts with PostScript outlines by PostScript name
authorOleg Oshmyan <chortos@inbox.lv>
Tue, 20 Oct 2015 21:51:34 +0000 (00:51 +0300)
committerOleg Oshmyan <chortos@inbox.lv>
Thu, 22 Oct 2015 23:36:53 +0000 (02:36 +0300)
Fonts without PostScript outlines (such as TrueType fonts) are unaffected,
and their PostScript names continue to be ignored when searching for fonts.

This matches the behavior of GDI and hence VSFilter.

libass/ass_coretext.c
libass/ass_directwrite.c
libass/ass_fontconfig.c
libass/ass_fontselect.c
libass/ass_fontselect.h
libass/dwrite_c.h

index a2cd77f50f065ad0d74d127b44876000aa15e9e6..006547bff787fd2865c1f5e31e4db0f36f353d94 100644 (file)
@@ -88,6 +88,19 @@ 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)
 {
@@ -192,6 +205,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);
index 6b6b623df19543af2d4520725b19b503d2a6168a..8388f1c677b3e2acb7ddcfbe8b9e430e95c96115 100644 (file)
@@ -483,6 +483,24 @@ 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;
+}
+
 /*
  * Scan every system font on the current machine and add it
  * to the libass lookup. Stores the FontPrivate as private data
@@ -616,6 +634,8 @@ static void scan_fonts(IDWriteFactory *factory,
             }
             IDWriteLocalizedStrings_Release(familyNames);
 
+            meta.is_postscript = is_postscript(font);
+
             FontPrivate *font_priv = (FontPrivate *) calloc(1, sizeof(*font_priv));
             font_priv->font = font;
 
index c9bb2f9d79d355948f52d5f95e7f230e1614cf0d..8b0824bc5748513fbdb5c52fec7369128f7acb08 100644 (file)
@@ -86,6 +86,7 @@ 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];
 
@@ -138,6 +139,13 @@ 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);
     }
 }
index 39d4d5d46dbbdbfb60dcae2e939895575f1f1a6c..2f577f1073eeb263072a16b4728e5286a3f7db80 100644 (file)
@@ -35,6 +35,7 @@
 #include FT_FREETYPE_H
 #include FT_SFNT_NAMES_H
 #include FT_TRUETYPE_IDS_H
+#include FT_TYPE1_TABLES_H
 
 #include "ass_utils.h"
 #include "ass.h"
@@ -66,8 +67,10 @@ struct font_info {
     // how to access this face
     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
+    bool is_postscript;
 
     // font source
     ASS_FontProvider *provider;
@@ -294,21 +297,23 @@ ass_font_provider_add_font(ASS_FontProvider *provider,
     // set uid
     info->uid = selector->uid++;
 
-    info->slant       = slant;
-    info->weight      = weight;
-    info->width       = width;
-    info->n_fullname  = meta->n_fullname;
-    info->n_family    = meta->n_family;
-    info->families    = calloc(meta->n_family, sizeof(char *));
+    info->slant         = slant;
+    info->weight        = weight;
+    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)
+        goto error;
+
     if (meta->n_fullname) {
         info->fullnames = calloc(meta->n_fullname, sizeof(char *));
         if (info->fullnames == NULL)
             goto error;
     }
 
-    if (info->families == NULL)
-        goto error;
-
     for (i = 0; i < info->n_family; i++) {
         info->families[i] = strdup(meta->families[i]);
         if (info->families[i] == NULL)
@@ -425,6 +430,18 @@ static bool matches_fullname(ASS_FontInfo *f, const char *fullname)
     return false;
 }
 
+/**
+ * \brief Return whether the given font has the given PostScript name.
+ */
+static bool matches_postscript_name(ASS_FontInfo *f, const char *name)
+{
+    if (f->is_postscript && f->postscript_name) {
+        if (ass_strcasecmp(f->postscript_name, name) == 0)
+            return true;
+    }
+    return false;
+}
+
 /**
  * \brief Compare attributes of font (a) against a font request (req). Returns
  * a matching score - the lower the better.
@@ -510,7 +527,8 @@ find_font(ASS_FontSelector *priv, ASS_Library *library,
                 // to determine best match in that particular family
                 score = font_attributes_similarity(font, &req);
                 *name_match = true;
-            } else if (matches_fullname(font, fullname)) {
+            } else if (matches_fullname(font, fullname) ||
+                       matches_postscript_name(font, fullname)) {
                 // If we don't have any match, compare fullnames against request
                 // if there is a match now, assign lowest score possible. This means
                 // the font should be chosen instantly, without further search.
@@ -720,6 +738,7 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info)
     char *fullnames[MAX_FULLNAME];
     char *families[MAX_FULLNAME];
     char *postscript_name = NULL;
+    PS_FontInfoRec postscript_info;
 
     // we're only interested in outlines
     if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
@@ -779,12 +798,13 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info)
     info->slant  = slant;
     info->weight = weight;
     info->width  = 100;     // FIXME, should probably query the OS/2 table
+
     info->postscript_name = postscript_name;
-    info->families = calloc(sizeof(char *), num_family);
+    info->is_postscript = !FT_Get_PS_Font_Info(face, &postscript_info);
 
+    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;
 
index f1e2933221b061084fe2cae680bb78e675b8eaec..09749ad6ffb6c14aa8dd41fab809e2edf4766ca8 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef LIBASS_FONTCONFIG_H
 #define LIBASS_FONTCONFIG_H
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -171,6 +172,8 @@ 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;
index ac7f4a2742bec5c1a1f5979762e2edf2ef2f6a64..ffdf1109a583e325bbcc6c46a2553a507f747faf 100644 (file)
@@ -59,6 +59,15 @@ typedef enum DWRITE_FACTORY_TYPE {
   DWRITE_FACTORY_TYPE_ISOLATED 
 } DWRITE_FACTORY_TYPE;
 
+typedef enum DWRITE_FONT_FACE_TYPE {
+  DWRITE_FONT_FACE_TYPE_CFF = 0,
+  DWRITE_FONT_FACE_TYPE_TRUETYPE,
+  DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION,
+  DWRITE_FONT_FACE_TYPE_TYPE1,
+  DWRITE_FONT_FACE_TYPE_VECTOR,
+  DWRITE_FONT_FACE_TYPE_BITMAP,
+  DWRITE_FONT_FACE_TYPE_UNKNOWN 
+} DWRITE_FONT_FACE_TYPE;
 
 typedef enum DWRITE_FONT_SIMULATIONS {
   DWRITE_FONT_SIMULATIONS_NONE      = 0x0000,
@@ -319,7 +328,7 @@ DECLARE_INTERFACE_(IDWriteFontFace,IUnknown)
 #endif
 
     /* IDWriteFontFace methods */
-    STDMETHOD(dummy1)(THIS);
+    STDMETHOD_(DWRITE_FONT_FACE_TYPE, GetType)(THIS) PURE;
 
     STDMETHOD(GetFiles)(THIS_
         UINT32 *numberOfFiles,