summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@blackbox>2011-07-15 00:49:50 +0200
committerGrigori Goronzy <greg@blackbox>2011-07-15 15:00:14 +0200
commitdd340a43024966d284f73cce0db9aa20e78cdbdd (patch)
treec42f55785e7efa7c665caf3a8f9da736e5b4a960
parentfa291a3269ee0fa76a17c976439a900b29084314 (diff)
downloadlibass-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.c4
-rw-r--r--libass/ass_font.h3
-rw-r--r--libass/ass_shaper.c39
-rw-r--r--libass/ass_shaper.h2
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