diff options
author | Grigori Goronzy <greg@blackbox> | 2011-07-15 00:49:50 +0200 |
---|---|---|
committer | Grigori Goronzy <greg@blackbox> | 2011-07-15 15:00:14 +0200 |
commit | dd340a43024966d284f73cce0db9aa20e78cdbdd (patch) | |
tree | c42f55785e7efa7c665caf3a8f9da736e5b4a960 | |
parent | fa291a3269ee0fa76a17c976439a900b29084314 (diff) | |
download | libass-dd340a43024966d284f73cce0db9aa20e78cdbdd.tar.bz2 libass-dd340a43024966d284f73cce0db9aa20e78cdbdd.tar.xz |
Cache HarfBuzz fonts
Add a new opaque data structure to store shaper-specific font data in
an ASS_Font. At the moment, this is used for caching HarfBuzz fonts,
to reduce allocation and font initialization overhead.
-rw-r--r-- | libass/ass_font.c | 4 | ||||
-rw-r--r-- | libass/ass_font.h | 3 | ||||
-rw-r--r-- | libass/ass_shaper.c | 39 | ||||
-rw-r--r-- | libass/ass_shaper.h | 2 |
4 files changed, 45 insertions, 3 deletions
diff --git a/libass/ass_font.c b/libass/ass_font.c index 0f53d8a..954040e 100644 --- a/libass/ass_font.c +++ b/libass/ass_font.c @@ -32,6 +32,7 @@ #include "ass_font.h" #include "ass_fontconfig.h" #include "ass_utils.h" +#include "ass_shaper.h" #define VERTICAL_LOWER_BOUND 0x02f1 @@ -181,6 +182,7 @@ ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library, font.library = library; font.ftlibrary = ftlibrary; + font.shaper_priv = NULL; font.n_faces = 0; font.desc.family = strdup(desc->family); font.desc.treat_family_as_pattern = desc->treat_family_as_pattern; @@ -603,6 +605,8 @@ void ass_font_free(ASS_Font *font) for (i = 0; i < font->n_faces; ++i) if (font->faces[i]) FT_Done_Face(font->faces[i]); + if (font->shaper_priv) + ass_shaper_font_data_free(font->shaper_priv); free(font->desc.family); free(font); } diff --git a/libass/ass_font.h b/libass/ass_font.h index 6b45adf..06fda21 100644 --- a/libass/ass_font.h +++ b/libass/ass_font.h @@ -31,6 +31,8 @@ #define DECO_UNDERLINE 1 #define DECO_STRIKETHROUGH 2 +typedef struct ass_shaper_font_data ASS_ShaperFontData; + typedef struct { char *family; unsigned bold; @@ -44,6 +46,7 @@ typedef struct { ASS_Library *library; FT_Library ftlibrary; FT_Face faces[ASS_FONT_MAX_FACES]; + ASS_ShaperFontData *shaper_priv; int n_faces; double scale_x, scale_y; // current transform FT_Vector v; // current shift diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c index 9a4e8d5..55bcaae 100644 --- a/libass/ass_shaper.c +++ b/libass/ass_shaper.c @@ -46,6 +46,10 @@ struct ass_shaper { hb_feature_t *features; }; +struct ass_shaper_font_data { + hb_font_t *fonts[ASS_FONT_MAX_FACES]; +}; + /** * \brief Print version information */ @@ -114,6 +118,15 @@ void ass_shaper_free(ASS_Shaper *shaper) free(shaper); } +void ass_shaper_font_data_free(ASS_ShaperFontData *priv) +{ + int i; + for (i = 0; i < ASS_FONT_MAX_FACES; i++) + if (priv->fonts[i]) + hb_font_destroy(priv->fonts[i]); + free(priv); +} + /** * \brief Set features depending on properties of the run */ @@ -127,6 +140,28 @@ static void set_run_features(ASS_Shaper *shaper, GlyphInfo *info) } /** + * \brief Retrieve HarfBuzz font from cache. + * Create it from FreeType font, if needed. + * \param info glyph cluster + * \return HarfBuzz font + */ +static hb_font_t *get_hb_font(GlyphInfo *info) +{ + ASS_Font *font = info->font; + hb_font_t **hb_fonts; + + if (!font->shaper_priv) + font->shaper_priv = calloc(sizeof(ASS_ShaperFontData), 1); + + hb_fonts = font->shaper_priv->fonts; + if (!hb_fonts[info->face_index]) + hb_fonts[info->face_index] = + hb_ft_font_create(font->faces[info->face_index], NULL); + + return hb_fonts[info->face_index]; +} + +/** * \brief Shape event text with HarfBuzz. Full OpenType shaping. * \param glyphs glyph clusters * \param len number of clusters @@ -151,11 +186,10 @@ static void shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) while (i < (len - 1) && level == glyphs[i+1].shape_run_id) i++; //printf("run %d from %d to %d with level %d\n", run, k, i, level); - FT_Face run_font = glyphs[k].font->faces[glyphs[k].face_index]; runs[run].offset = k; runs[run].end = i; runs[run].buf = hb_buffer_create(i - k + 1); - runs[run].font = hb_ft_font_create(run_font, NULL); + runs[run].font = get_hb_font(glyphs + k); set_run_features(shaper, glyphs + k); hb_buffer_set_direction(runs[run].buf, direction ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); @@ -219,7 +253,6 @@ static void shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) // Free runs and associated data for (i = 0; i < run; i++) { hb_buffer_destroy(runs[i].buf); - hb_font_destroy(runs[i].font); } } diff --git a/libass/ass_shaper.h b/libass/ass_shaper.h index a5bb462..894822d 100644 --- a/libass/ass_shaper.h +++ b/libass/ass_shaper.h @@ -36,4 +36,6 @@ void ass_shaper_cleanup(ASS_Shaper *shaper, TextInfo *text_info); FriBidiStrIndex *ass_shaper_reorder(ASS_Shaper *shaper, TextInfo *text_info); FriBidiParType resolve_base_direction(int font_encoding); +void ass_shaper_font_data_free(ASS_ShaperFontData *priv); + #endif |