summaryrefslogtreecommitdiffstats
path: root/libass/ass_fontselect.c
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/ass_fontselect.c
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/ass_fontselect.c')
-rw-r--r--libass/ass_fontselect.c107
1 files changed, 81 insertions, 26 deletions
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);