From e87063d873b88427ffad038fcfbbe7e7a0b7437d Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Wed, 24 Aug 2011 14:23:01 +0200 Subject: Use streamed access for memory fonts This is faster in many cases, and more suitable for Windows' GetFontData function. --- libass/ass_font.c | 46 ++++++++++++++++++++++++++++++++++++++++------ libass/ass_font.h | 8 ++++---- libass/ass_fontselect.c | 32 +++++++++++++++++++------------- libass/ass_fontselect.h | 4 ++-- libass/ass_types.h | 10 +++++----- 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 -- cgit v1.2.3