]> granicus.if.org Git - libass/commitdiff
Use streamed access for memory fonts
authorGrigori Goronzy <greg@chown.ath.cx>
Wed, 24 Aug 2011 12:23:01 +0000 (14:23 +0200)
committerGrigori Goronzy <greg@chown.ath.cx>
Fri, 10 Jul 2015 08:42:40 +0000 (10:42 +0200)
This is faster in many cases, and more suitable for Windows' GetFontData
function.

libass/ass_font.c
libass/ass_font.h
libass/ass_fontselect.c
libass/ass_fontselect.h
libass/ass_types.h

index 1aa8fff4806ec3d60cba63649b06fbac68c10ace..0b6d24bc11bbf021999103f578741f8c8f5989b0 100644 (file)
@@ -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) {
index 06519c68a03586cfecbd558d2c2951634aff7e2a..fb6462be31cecfcfa24f43b3cf0e6fe41050e600 100644 (file)
@@ -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);
index 32d4dfa03825742a4fdc24b71588f17f30887da4..ff2d707efb60a3b0c8e3f4c1a239e60c4feb1fa0 100644 (file)
@@ -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);
 
index 59a447be37e579e678ea4b3750383b0f79f16255..e080ab029a43cf06f8f3ca55d844b7379f6b8a26 100644 (file)
@@ -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
index 01e73061ce217a217a20d426d72dbc4bd539c940..f52e537097db485793c6613ac060a9e2e34332cc 100644 (file)
@@ -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