summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@chown.ath.cx>2011-08-20 17:46:03 +0200
committerGrigori Goronzy <greg@chown.ath.cx>2015-07-10 10:42:40 +0200
commitf69ec6e0c038fe32cc5f91cc62cba52fe3934885 (patch)
tree9cc33785a996b0fe334db78941f218fef7991d77 /libass
parentdef7a0c702ad1e1ecb03045acd785bd16e8a71f1 (diff)
downloadlibass-f69ec6e0c038fe32cc5f91cc62cba52fe3934885.tar.bz2
libass-f69ec6e0c038fe32cc5f91cc62cba52fe3934885.tar.xz
Memory font support
Allow memory fonts with the get_face_data callback. This feature is used for embedded fonts, but can be used by any font provider.
Diffstat (limited to 'libass')
-rw-r--r--libass/ass_font.c31
-rw-r--r--libass/ass_font.h6
-rw-r--r--libass/ass_fontselect.c107
-rw-r--r--libass/ass_fontselect.h5
4 files changed, 98 insertions, 51 deletions
diff --git a/libass/ass_font.c b/libass/ass_font.c
index a6d1b5b..ce42781 100644
--- a/libass/ass_font.c
+++ b/libass/ass_font.c
@@ -92,18 +92,6 @@ uint32_t ass_font_index_magic(FT_Face face, uint32_t symbol)
}
}
-/**
- * \brief find a memory font by name
- */
-static int find_font(ASS_Library *library, char *name)
-{
- int i;
- for (i = 0; i < library->num_fontdata; ++i)
- if (strcasecmp(name, library->fontdata[i].name) == 0)
- return i;
- return -1;
-}
-
static void buggy_font_workaround(FT_Face face)
{
// Some fonts have zero Ascender/Descender fields in 'hhea' table.
@@ -130,14 +118,15 @@ static void buggy_font_workaround(FT_Face face)
static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch)
{
char *path;
- int i, index, uid;
- int error, mem_idx;
+ int i, index, uid, error;
+ ASS_Buffer mem_font = { NULL, 0 };
FT_Face face;
if (font->n_faces == ASS_FONT_MAX_FACES)
return -1;
- path = ass_font_select(fontsel, font->library, font , &index, &uid, ch);
+ path = ass_font_select(fontsel, font->library, font , &index, &uid,
+ &mem_font, ch);
if (!path)
return -1;
@@ -151,14 +140,9 @@ static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch)
}
}
- mem_idx = find_font(font->library, path);
- if (mem_idx >= 0) {
- error =
- FT_New_Memory_Face(font->ftlibrary,
- (unsigned char *) font->library->
- fontdata[mem_idx].data,
- font->library->fontdata[mem_idx].size, index,
- &face);
+ if (mem_font.buf) {
+ error = FT_New_Memory_Face(font->ftlibrary, mem_font.buf, mem_font.len,
+ index, &face);
if (error) {
ass_msg(font->library, MSGL_WARN,
"Error opening memory font: '%s'", path);
@@ -174,6 +158,7 @@ static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch)
return -1;
}
}
+
charmap_magic(font->library, face);
buggy_font_workaround(face);
diff --git a/libass/ass_font.h b/libass/ass_font.h
index 693cabf..06519c6 100644
--- a/libass/ass_font.h
+++ b/libass/ass_font.h
@@ -26,6 +26,7 @@
typedef struct ass_font ASS_Font;
typedef struct ass_font_desc ASS_FontDesc;
+typedef struct ass_buffer ASS_Buffer;
#include "ass.h"
#include "ass_types.h"
@@ -58,6 +59,11 @@ struct ass_font {
double size;
};
+struct ass_buffer {
+ void *buf;
+ size_t len;
+};
+
void charmap_magic(ASS_Library *library, FT_Face face);
ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library,
FT_Library ftlibrary, ASS_FontSelector *fontsel,
diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c
index efd4a39..bb9ec80 100644
--- a/libass/ass_fontselect.c
+++ b/libass/ass_fontselect.c
@@ -65,8 +65,8 @@ struct font_info {
int weight; // TrueType scale, 100-900
// how to access this face
- char *path;
- int index;
+ char *path; // absolute path
+ int index; // font index inside font collections
// similarity score
unsigned score;
@@ -109,10 +109,17 @@ struct coverage_map {
uint32_t *codepoints;
};
+typedef struct font_data_ft FontDataFT;
+struct font_data_ft {
+ ASS_Library *lib;
+ CoverageMap *coverage;
+ char *name;
+};
+
static int check_glyph_ft(void *data, uint32_t codepoint)
{
int i;
- CoverageMap *coverage = (CoverageMap *)data;
+ CoverageMap *coverage = ((FontDataFT *)data)->coverage;
if (!codepoint)
return 1;
@@ -133,10 +140,50 @@ static void coverage_map_destroy(void *data)
free(coverage);
}
+static void destroy_font_ft(void *data)
+{
+ FontDataFT *fd = (FontDataFT *)data;
+
+ if (fd->coverage)
+ coverage_map_destroy(fd->coverage);
+
+ free(fd->name);
+ free(fd);
+}
+
+/**
+ * \brief find a memory font by name
+ * \param library ASS library
+ * \param name font name
+ */
+static int find_font(ASS_Library *library, char *name)
+{
+ int i;
+ for (i = 0; i < library->num_fontdata; ++i)
+ if (strcasecmp(name, library->fontdata[i].name) == 0)
+ return i;
+ return -1;
+}
+
+static void *get_face_embedded(void *data, size_t *len)
+{
+ int i;
+ FontDataFT *ft = (FontDataFT *)data;
+ ASS_Fontdata *fd = ft->lib->fontdata;
+
+ i = find_font(ft->lib, ft->name);
+
+ if (i < 0)
+ return NULL;
+
+ *len = fd[i].size;
+ return fd[i].data;
+}
+
static ASS_FontProviderFuncs ft_funcs = {
- NULL,
+ get_face_embedded,
check_glyph_ft,
- coverage_map_destroy,
+ destroy_font_ft,
NULL,
};
@@ -179,10 +226,6 @@ ass_font_provider_add_font(ASS_FontProvider *provider,
ASS_FontSelector *selector = provider->parent;
ASS_FontInfo *info;
- // XXX: there's no support for memory fonts yet
- if (!path)
- return 0;
-
weight = meta->weight;
slant = meta->slant;
@@ -385,7 +428,7 @@ 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, uint32_t code)
+ int *index, int *uid, ASS_Buffer *face, uint32_t code)
{
int num_fonts = priv->n_font;
int idx = 0;
@@ -430,14 +473,20 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library,
free(req.fullnames[0]);
free(req.family);
- // return best match
- if (idx == priv->n_font)
- return NULL;
- if (!font_infos[idx].path)
- return NULL;
*index = font_infos[idx].index;
*uid = font_infos[idx].uid;
- return strdup(font_infos[idx].path);
+
+ // nothing found
+ if (idx == priv->n_font)
+ return NULL;
+
+ // if there is no valid path, this is a memory font
+ if (font_infos[idx].path == NULL) {
+ ASS_FontProvider *provider = font_infos[idx].provider;
+ face->buf = provider->funcs.get_face(font_infos[idx].priv, &face->len);
+ return strdup(""); // empty string indicates a memory font
+ } else
+ return strdup(font_infos[idx].path);
}
@@ -453,7 +502,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, uint32_t code)
+ ASS_Font *font, int *index, int *uid, ASS_Buffer *data,
+ uint32_t code)
{
char *res = 0;
const char *family = font->desc.family;
@@ -461,15 +511,16 @@ 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, code);
+ res = select_font(priv, library, family, bold, italic, index, uid,
+ data, code);
if (!res && priv->family_default) {
res = select_font(priv, library, priv->family_default, bold,
- italic, index, uid, code);
+ italic, index, 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);
+ family, bold, italic, res[0] ? res : "<memory>", *index);
}
if (!res && priv->path_default) {
@@ -482,17 +533,17 @@ char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library,
if (!res) {
res = select_font(priv, library, "Arial", bold, italic,
- index, uid, code);
+ index, 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);
+ italic, res[0] ? res : "<memory>", *index);
}
if (res)
ass_msg(library, MSGL_V,
"fontselect: (%s, %d, %d) -> %s, %d", family, bold,
- italic, res, *index);
+ italic, res[0] ? res : "<memory>", *index);
return res;
}
@@ -635,7 +686,7 @@ static void process_fontdata(ASS_FontProvider *priv, ASS_Library *library,
for (face_index = 0; face_index < num_faces; ++face_index) {
ASS_FontProviderMetaData info;
- CoverageMap *coverage;
+ FontDataFT *ft;
rc = FT_New_Memory_Face(ftlibrary, (unsigned char *) data,
data_size, face_index, &face);
@@ -655,8 +706,12 @@ static void process_fontdata(ASS_FontProvider *priv, ASS_Library *library,
continue;
}
- coverage = get_coverage_map(face);
- ass_font_provider_add_font(priv, &info, name, face_index, coverage);
+ ft = calloc(1, sizeof(FontDataFT));
+ ft->lib = library;
+ ft->coverage = get_coverage_map(face);
+ ft->name = strdup(name);
+
+ ass_font_provider_add_font(priv, &info, NULL, face_index, ft);
free_font_info(&info);
FT_Done_Face(face);
diff --git a/libass/ass_fontselect.h b/libass/ass_fontselect.h
index 8e41c45..ec4c793 100644
--- a/libass/ass_fontselect.h
+++ b/libass/ass_fontselect.h
@@ -33,7 +33,7 @@ typedef struct font_info ASS_FontInfo;
#include "ass_font.h"
// get face data
-typedef void *(*GetFaceFunc)(void *);
+typedef void *(*GetFaceFunc)(void *, size_t *);
// check for a glyph
typedef int (*CheckGlyphFunc)(void *, uint32_t);
@@ -69,7 +69,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, uint32_t code);
+ ASS_Font *font, int *index, int *uid, ASS_Buffer *data,
+ uint32_t code);
void ass_fontselect_free(ASS_FontSelector *priv);
// Font provider functions