summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libass/ass_coretext.c47
-rw-r--r--libass/ass_directwrite.c80
-rw-r--r--libass/ass_fontconfig.c23
-rw-r--r--libass/ass_fontselect.c58
-rw-r--r--libass/ass_fontselect.h11
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;