summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@chown.ath.cx>2011-08-24 14:23:01 +0200
committerGrigori Goronzy <greg@chown.ath.cx>2015-07-10 10:42:40 +0200
commite87063d873b88427ffad038fcfbbe7e7a0b7437d (patch)
tree3e85316d76dda496da80e9df3eb6a6f9a828c761
parent4f2309430ae2f8086e2b46a45fd4f264a2e0a668 (diff)
downloadlibass-e87063d873b88427ffad038fcfbbe7e7a0b7437d.tar.bz2
libass-e87063d873b88427ffad038fcfbbe7e7a0b7437d.tar.xz
Use streamed access for memory fonts
This is faster in many cases, and more suitable for Windows' GetFontData function.
-rw-r--r--libass/ass_font.c46
-rw-r--r--libass/ass_font.h8
-rw-r--r--libass/ass_fontselect.c32
-rw-r--r--libass/ass_fontselect.h4
-rw-r--r--libass/ass_types.h10
5 files changed, 70 insertions, 30 deletions
diff --git a/libass/ass_font.c b/libass/ass_font.c
index 1aa8fff..0b6d24b 100644
--- a/libass/ass_font.c
+++ b/libass/ass_font.c
@@ -111,6 +111,23 @@ static void buggy_font_workaround(FT_Face face)
}
}
+static unsigned long
+read_stream_font(FT_Stream stream, unsigned long offset, unsigned char *buffer,
+ unsigned long count)
+{
+ ASS_FontStream *font = (ASS_FontStream *)stream->descriptor.pointer;
+
+ font->func(font->priv, buffer, offset, count);
+ return count;
+}
+
+static void
+close_stream_font(FT_Stream stream)
+{
+ free(stream->descriptor.pointer);
+ free(stream);
+}
+
/**
* \brief Select a face with the given charcode and add it to ASS_Font
* \return index of the new face in font->faces, -1 if failed
@@ -119,14 +136,14 @@ static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch)
{
char *path;
int i, index, uid, error;
- ASS_Buffer mem_font = { NULL, 0 };
+ ASS_FontStream stream = { NULL, NULL };
FT_Face face;
if (font->n_faces == ASS_FONT_MAX_FACES)
return -1;
path = ass_font_select(fontsel, font->library, font , &index, &uid,
- &mem_font, ch);
+ &stream, ch);
if (!path)
return -1;
@@ -140,15 +157,32 @@ static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch)
}
}
- if (mem_font.buf) {
- error = FT_New_Memory_Face(font->ftlibrary, mem_font.buf, mem_font.len,
- index, &face);
+ if (stream.func) {
+ FT_Open_Args args;
+ FT_Stream ftstream = calloc(1, sizeof(FT_StreamRec));
+ ASS_FontStream *fs = calloc(1, sizeof(ASS_FontStream));
+
+ *fs = stream;
+ ftstream->size = stream.func(stream.priv, NULL, 0, 0);
+ ftstream->read = read_stream_font;
+ ftstream->close = close_stream_font;
+ ftstream->descriptor.pointer = (void *)fs;
+
+ memset(&args, 0, sizeof(FT_Open_Args));
+ args.flags = FT_OPEN_STREAM;
+ args.stream = ftstream;
+
+ error = FT_Open_Face(font->ftlibrary, &args, index, &face);
+
if (error) {
ass_msg(font->library, MSGL_WARN,
- "Error opening memory font: '%s' (size %d)", path, mem_font.len);
+ "Error opening memory font: '%s'", path);
free(path);
+ free(ftstream);
+ free(fs);
return -1;
}
+
} else {
error = FT_New_Face(font->ftlibrary, path, index, &face);
if (error) {
diff --git a/libass/ass_font.h b/libass/ass_font.h
index 06519c6..fb6462b 100644
--- a/libass/ass_font.h
+++ b/libass/ass_font.h
@@ -26,7 +26,7 @@
typedef struct ass_font ASS_Font;
typedef struct ass_font_desc ASS_FontDesc;
-typedef struct ass_buffer ASS_Buffer;
+typedef struct ass_font_stream ASS_FontStream;
#include "ass.h"
#include "ass_types.h"
@@ -59,9 +59,9 @@ struct ass_font {
double size;
};
-struct ass_buffer {
- void *buf;
- size_t len;
+struct ass_font_stream {
+ GetDataFunc func;
+ void *priv;
};
void charmap_magic(ASS_Library *library, FT_Face face);
diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c
index 32d4dfa..ff2d707 100644
--- a/libass/ass_fontselect.c
+++ b/libass/ass_fontselect.c
@@ -114,6 +114,7 @@ struct font_data_ft {
ASS_Library *lib;
CoverageMap *coverage;
char *name;
+ int idx;
};
static int check_glyph_ft(void *data, uint32_t codepoint)
@@ -165,23 +166,25 @@ static int find_font(ASS_Library *library, char *name)
return -1;
}
-static void *get_face_embedded(void *data, size_t *len)
+static size_t
+get_data_embedded(void *data, unsigned char *buf, size_t offset, size_t len)
{
- int i;
FontDataFT *ft = (FontDataFT *)data;
ASS_Fontdata *fd = ft->lib->fontdata;
+ int i = ft->idx;
- i = find_font(ft->lib, ft->name);
+ if (ft->idx < 0)
+ ft->idx = i = find_font(ft->lib, ft->name);
- if (i < 0)
- return NULL;
+ if (buf == NULL)
+ return fd[i].size;
- *len = fd[i].size;
- return fd[i].data;
+ memcpy(buf, fd[i].data + offset, len);
+ return len;
}
static ASS_FontProviderFuncs ft_funcs = {
- get_face_embedded,
+ get_data_embedded,
check_glyph_ft,
destroy_font_ft,
NULL,
@@ -428,7 +431,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_Buffer *face, uint32_t code)
+ int *index, int *uid, ASS_FontStream *stream,
+ uint32_t code)
{
int num_fonts = priv->n_font;
int idx = 0;
@@ -480,10 +484,11 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library,
if (idx == priv->n_font)
return NULL;
- // if there is no valid path, this is a memory font
+ // if there is no valid path, this is a memory stream 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);
+ stream->func = provider->funcs.get_data;
+ stream->priv = font_infos[idx].priv;
return strdup(font_infos[idx].family);
} else
return strdup(font_infos[idx].path);
@@ -502,8 +507,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_Buffer *data,
- uint32_t code)
+ ASS_Font *font, int *index, int *uid,
+ ASS_FontStream *data, uint32_t code)
{
char *res = 0;
const char *family = font->desc.family;
@@ -710,6 +715,7 @@ static void process_fontdata(ASS_FontProvider *priv, ASS_Library *library,
ft->lib = library;
ft->coverage = get_coverage_map(face);
ft->name = strdup(name);
+ ft->idx = -1;
ass_font_provider_add_font(priv, &info, NULL, face_index, ft);
diff --git a/libass/ass_fontselect.h b/libass/ass_fontselect.h
index 59a447b..e080ab0 100644
--- a/libass/ass_fontselect.h
+++ b/libass/ass_fontselect.h
@@ -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_Buffer *data,
- uint32_t code);
+ ASS_Font *font, int *index, int *uid,
+ ASS_FontStream *data, uint32_t code);
void ass_fontselect_free(ASS_FontSelector *priv);
// Font provider functions
diff --git a/libass/ass_types.h b/libass/ass_types.h
index 01e7306..f52e537 100644
--- a/libass/ass_types.h
+++ b/libass/ass_types.h
@@ -46,13 +46,13 @@ typedef struct font_provider ASS_FontProvider;
/* Font Provider */
-typedef void *(*GetFaceFunc)(void *, size_t *);
-typedef int (*CheckGlyphFunc)(void *, uint32_t);
-typedef void (*DestroyFontFunc)(void *);
-typedef void (*DestroyProviderFunc)(void *);
+typedef size_t (*GetDataFunc)(void *, unsigned char*, size_t, size_t);
+typedef int (*CheckGlyphFunc)(void *, uint32_t);
+typedef void (*DestroyFontFunc)(void *);
+typedef void (*DestroyProviderFunc)(void *);
typedef struct font_provider_funcs {
- GetFaceFunc get_face; // callback for memory fonts
+ GetDataFunc get_data; // callback for memory fonts
CheckGlyphFunc check_glyph; // test codepoint for coverage
DestroyFontFunc destroy_font; // destroy a single font
DestroyProviderFunc destroy_provider; // destroy provider only