]> granicus.if.org Git - libass/commitdiff
Cache HarfBuzz fonts
authorGrigori Goronzy <greg@blackbox>
Thu, 14 Jul 2011 22:49:50 +0000 (00:49 +0200)
committerGrigori Goronzy <greg@blackbox>
Fri, 15 Jul 2011 13:00:14 +0000 (15:00 +0200)
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.

libass/ass_font.c
libass/ass_font.h
libass/ass_shaper.c
libass/ass_shaper.h

index 0f53d8a1c96d4ef604d3fcc0cceaa80e981d763f..954040e0dc1edb8273d4bcbdbc8d62c7006c0303 100644 (file)
@@ -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);
 }
index 6b45adf5319c44a1596ee74aadf3609d62b5ab14..06fda21d775e65b348b73e86ec820a820d1b17a7 100644 (file)
@@ -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
index 9a4e8d547a2665cd98ab33bb6b36d172274882b9..55bcaae7d544f70927d2f47c2bffe83d7d3fe2e3 100644 (file)
@@ -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
  */
@@ -126,6 +139,28 @@ static void set_run_features(ASS_Shaper *shaper, GlyphInfo *info)
             shaper->features[VERT].value = shaper->features[VKNA].value = 0;
 }
 
+/**
+ * \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
@@ -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);
     }
 
 }
index a5bb462055e2a97cafea2aef898eefc1dbd09386..894822d7511f2e558032b2b53c3950778c867b26 100644 (file)
@@ -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