]> granicus.if.org Git - libass/commitdiff
cache: unified bitmap cache
authorGrigori Goronzy <greg@blackbox>
Mon, 27 Jun 2011 19:04:12 +0000 (21:04 +0200)
committerGrigori Goronzy <greg@blackbox>
Mon, 27 Jun 2011 19:04:12 +0000 (21:04 +0200)
Similarly to the glyph cache, subclass the bitmap cache to allow both
outline bitmaps and clipping mask bitmaps to coexist in the same cache
in a much cleaner way.

libass/ass_cache.c
libass/ass_cache.h
libass/ass_cache_template.h
libass/ass_render.c

index 6c345397862c6ac46477f7390de014d71f9dc573..8a18e0af11ef550e8ff127fdb37592b78a891b94 100644 (file)
@@ -76,12 +76,15 @@ static void font_destruct(void *key, void *value)
 static void bitmap_destruct(void *key, void *value)
 {
     BitmapHashValue *v = value;
+    BitmapHashKey *k = key;
     if (v->bm)
         ass_free_bitmap(v->bm);
     if (v->bm_o)
         ass_free_bitmap(v->bm_o);
     if (v->bm_s)
         ass_free_bitmap(v->bm_s);
+    if (k->type == BITMAP_CLIP)
+        free(k->u.clip.text);
     free(key);
     free(value);
 }
@@ -96,6 +99,28 @@ static size_t bitmap_size(void *value, size_t value_size)
     return 0;
 }
 
+static unsigned bitmap_hash(void *key, size_t key_size)
+{
+    BitmapHashKey *k = key;
+    switch (k->type) {
+        case BITMAP_OUTLINE: return outline_bitmap_hash(&k->u, key_size);
+        case BITMAP_CLIP: return clip_bitmap_hash(&k->u, key_size);
+        default: return 0;
+    }
+}
+
+static unsigned bitmap_compare (void *a, void *b, size_t key_size)
+{
+    BitmapHashKey *ak = a;
+    BitmapHashKey *bk = b;
+    if (ak->type != bk->type) return 0;
+    switch (ak->type) {
+        case BITMAP_OUTLINE: return outline_bitmap_compare(&ak->u, &bk->u, key_size);
+        case BITMAP_CLIP: return clip_bitmap_compare(&ak->u, &bk->u, key_size);
+        default: return 0;
+    }
+}
+
 // composite cache
 static void composite_destruct(void *key, void *value)
 {
index 05903e72e0ac002bbd8eb16d1c16b38b9a6bafe8..077e081c5e7f4550223ffb95bda41b27a3018024 100644 (file)
@@ -71,6 +71,17 @@ typedef struct outline_hash_key {
     } u;
 } OutlineHashKey;
 
+typedef struct bitmap_hash_key {
+    enum {
+        BITMAP_OUTLINE,
+        BITMAP_CLIP,
+    } type;
+    union {
+        OutlineBitmapHashKey outline;
+        ClipMaskHashKey clip;
+    } u;
+} BitmapHashKey;
+
 Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func,
                         CacheItemDestructor destruct_func, ItemSize size_func,
                         size_t key_size, size_t value_size);
index 495ccbd56b4a01dfea8992f1c298d778d69415d5..f2080a653eb37d277288e353de3e64a9a006cb3e 100644 (file)
@@ -59,8 +59,8 @@
 
 
 
-// describes a bitmap; bitmaps with equivalents structs are considered identical
-START(bitmap, bitmap_hash_key)
+// describes an outline bitmap
+START(outline_bitmap, outline_bitmap_hash_key)
     GENERIC(OutlineHashValue *, outline)
     GENERIC(char, be) // blur edges
     GENERIC(double, blur) // gaussian blur
@@ -76,7 +76,12 @@ START(bitmap, bitmap_hash_key)
     GENERIC(int, shift_y)
     FTVECTOR(advance) // subpixel shift vector
     FTVECTOR(shadow_offset) // shadow subpixel shift
-END(BitmapHashKey)
+END(OutlineBitmapHashKey)
+
+// describe a clip mask bitmap
+START(clip_bitmap, clip_bitmap_hash_key)
+    STRING(text)
+END(ClipMaskHashKey)
 
 // describes an outline glyph
 START(glyph, glyph_hash_key)
index 456ca02f8946207ea4732b9e24e3160fb3e88d54..39c41d2140a5721e59df53e2e1346e641f988f6a 100644 (file)
@@ -536,27 +536,23 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
     Bitmap *clip_bm = NULL;
     ASS_Image *cur;
     ASS_Drawing *drawing = render_priv->state.clip_drawing;
-    //GlyphHashKey key;
-    //GlyphHashValue *val;
+    BitmapHashKey key;
+    BitmapHashValue *val;
     int error;
 
     if (!drawing)
         return;
 
-    // FIXME: reimplement cache
-#if 0
     // Try to get mask from cache
-    ass_drawing_hash(drawing);
     memset(&key, 0, sizeof(key));
-    key.ch = -2;
-    key.drawing_hash = drawing->hash;
-    val = ass_cache_get(render_priv->cache.glyph_cache, &key);
+    key.type = BITMAP_CLIP;
+    key.u.clip.text = strdup(drawing->text);
+    val = ass_cache_get(render_priv->cache.bitmap_cache, &key);
 
     if (val) {
-        clip_bm = (FT_BitmapGlyph) val->glyph;
+        clip_bm = val->bm;
     } else {
-#endif
-        //GlyphHashValue v;
+        BitmapHashValue v;
 
         // Not found in cache, parse and rasterize it
         outline = ass_drawing_parse(drawing, 1);
@@ -587,15 +583,11 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
                 "Clip vector rasterization failed: %d. Skipping.", error);
         }
 
-        //clip_bm = (FT_BitmapGlyph) glyph;
-
-#if 0
         // Add to cache
         memset(&v, 0, sizeof(v));
-        v.glyph = glyph;
-        ass_cache_put(render_priv->cache.glyph_cache, &key, &v);
+        v.bm = clip_bm;
+        ass_cache_put(render_priv->cache.bitmap_cache, &key, &v);
     }
-#endif
 blend_vector_error:
 
     if (!clip_bm) goto blend_vector_exit;
@@ -678,7 +670,6 @@ blend_vector_error:
     }
 
 blend_vector_exit:
-    ass_free_bitmap(clip_bm);
     ass_drawing_free(render_priv->state.clip_drawing);
     render_priv->state.clip_drawing = 0;
 }
@@ -1059,7 +1050,7 @@ get_outline_glyph(ASS_Renderer *render_priv, int symbol, GlyphInfo *info,
     fill_glyph_hash(render_priv, &key, drawing, symbol);
     val = ass_cache_get(render_priv->cache.outline_cache, &key);
     if (val) {
-        info->hash_key.outline = val;
+        info->hash_key.u.outline.outline = val;
         info->outline = val->outline;
         info->border = val->border;
         info->bbox = val->bbox_scaled;
@@ -1130,7 +1121,7 @@ get_outline_glyph(ASS_Renderer *render_priv, int symbol, GlyphInfo *info,
             v.asc = drawing->asc;
             v.desc = drawing->desc;
         }
-        info->hash_key.outline =
+        info->hash_key.u.outline.outline =
             ass_cache_put(render_priv->cache.outline_cache, &key, &v);
     }
 }
@@ -1222,7 +1213,7 @@ static void
 get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
 {
     BitmapHashValue *val;
-    BitmapHashKey *key = &info->hash_key;
+    OutlineBitmapHashKey *key = &info->hash_key.u.outline;
 
     val = ass_cache_get(render_priv->cache.bitmap_cache, key);
 
@@ -1599,7 +1590,7 @@ static void get_base_point(DBBox *bbox, int alignment, double *bx, double *by)
  * Prepare bitmap hash key of a glyph
  */
 static void
-fill_bitmap_hash(ASS_Renderer *priv, BitmapHashKey *hash_key)
+fill_bitmap_hash(ASS_Renderer *priv, OutlineBitmapHashKey *hash_key)
 {
     hash_key->frx = rot_key(priv->state.frx);
     hash_key->fry = rot_key(priv->state.fry);
@@ -1779,7 +1770,8 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
         }
 
         // fill bitmap hash
-        fill_bitmap_hash(render_priv, &glyphs[text_info->length].hash_key);
+        glyphs[text_info->length].hash_key.type = BITMAP_OUTLINE;
+        fill_bitmap_hash(render_priv, &glyphs[text_info->length].hash_key.u.outline);
 
         text_info->length++;
 
@@ -1990,16 +1982,14 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
 
         for (i = 0; i < text_info->length; ++i) {
             GlyphInfo *info = glyphs + i;
+            OutlineBitmapHashKey *key = &info->hash_key.u.outline;
 
-            if (info->hash_key.frx || info->hash_key.fry
-                || info->hash_key.frz || info->hash_key.fax
-                || info->hash_key.fay) {
-                info->hash_key.shift_x = info->pos.x + double_to_d6(device_x - center.x);
-                info->hash_key.shift_y =
-                    -(info->pos.y + double_to_d6(device_y - center.y));
+            if (key->frx || key->fry || key->frz || key->fax || key->fay) {
+                key->shift_x = info->pos.x + double_to_d6(device_x - center.x);
+                key->shift_y = -(info->pos.y + double_to_d6(device_y - center.y));
             } else {
-                info->hash_key.shift_x = 0;
-                info->hash_key.shift_y = 0;
+                key->shift_x = 0;
+                key->shift_y = 0;
             }
         }
     }
@@ -2008,11 +1998,12 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
     device_x *= render_priv->font_scale_x;
     for (i = 0; i < text_info->length; ++i) {
         GlyphInfo *g = glyphs + i;
+        OutlineBitmapHashKey *key = &g->hash_key.u.outline;
         g->pos.x *= render_priv->font_scale_x;
-        g->hash_key.advance.x =
+        key->advance.x =
             double_to_d6(device_x - (int) device_x +
             d6_to_double(g->pos.x & SUBPIXEL_MASK)) & ~SUBPIXEL_ACCURACY;
-        g->hash_key.advance.y =
+        key->advance.y =
             double_to_d6(device_y - (int) device_y +
             d6_to_double(g->pos.y & SUBPIXEL_MASK)) & ~SUBPIXEL_ACCURACY;
         get_bitmap_glyph(render_priv, glyphs + i);