summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@blackbox>2011-06-27 21:04:12 +0200
committerGrigori Goronzy <greg@blackbox>2011-06-27 21:04:12 +0200
commit2a97a6cfc2c99a8998d4464d765530e08f9751ae (patch)
treeced694d216fb36787cce62f3e72cb2e9a0a7dbfd
parentfd1acd2373662a14f3131d1a20b587ba5e4aa393 (diff)
downloadlibass-2a97a6cfc2c99a8998d4464d765530e08f9751ae.tar.bz2
libass-2a97a6cfc2c99a8998d4464d765530e08f9751ae.tar.xz
cache: unified bitmap cache
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.
-rw-r--r--libass/ass_cache.c25
-rw-r--r--libass/ass_cache.h11
-rw-r--r--libass/ass_cache_template.h11
-rw-r--r--libass/ass_render.c57
4 files changed, 68 insertions, 36 deletions
diff --git a/libass/ass_cache.c b/libass/ass_cache.c
index 6c34539..8a18e0a 100644
--- a/libass/ass_cache.c
+++ b/libass/ass_cache.c
@@ -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)
{
diff --git a/libass/ass_cache.h b/libass/ass_cache.h
index 05903e7..077e081 100644
--- a/libass/ass_cache.h
+++ b/libass/ass_cache.h
@@ -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);
diff --git a/libass/ass_cache_template.h b/libass/ass_cache_template.h
index 495ccbd..f2080a6 100644
--- a/libass/ass_cache_template.h
+++ b/libass/ass_cache_template.h
@@ -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)
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 456ca02..39c41d2 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -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);