diff options
Diffstat (limited to 'libass/ass_cache.c')
-rw-r--r-- | libass/ass_cache.c | 212 |
1 files changed, 132 insertions, 80 deletions
diff --git a/libass/ass_cache.c b/libass/ass_cache.c index 44aaee9..87e6cc2 100644 --- a/libass/ass_cache.c +++ b/libass/ass_cache.c @@ -63,37 +63,20 @@ static unsigned font_compare(void *key1, void *key2, size_t key_size) return 1; } -static void font_destruct(void *key, void *value) +static bool font_key_copy(void *dst, void *src, size_t key_size) { - ass_font_clear(value); + memcpy(dst, src, key_size); + ASS_FontDesc *d = dst, *s = src; + d->family = strdup(s->family); + return d->family; } -// bitmap cache -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); - switch (k->type) { - case BITMAP_OUTLINE: ass_cache_dec_ref(k->u.outline.outline); break; - case BITMAP_CLIP: free(k->u.clip.text); break; - } -} - -static size_t bitmap_size(void *value, size_t value_size) +static void font_destruct(void *key, void *value) { - BitmapHashValue *val = value; - size_t size = sizeof(BitmapHashKey) + sizeof(BitmapHashValue); - if (val->bm) - size += sizeof(Bitmap) + val->bm->stride * val->bm->h; - if (val->bm_o) - size += sizeof(Bitmap) + val->bm_o->stride * val->bm_o->h; - return size; + ass_font_clear(value); } +// bitmap cache static unsigned bitmap_hash(void *key, size_t key_size) { BitmapHashKey *k = key; @@ -116,35 +99,49 @@ static unsigned bitmap_compare(void *a, void *b, size_t key_size) } } -// composite cache -static void composite_destruct(void *key, void *value) +static bool bitmap_key_copy(void *dst, void *src, size_t key_size) { - CompositeHashValue *v = value; - CompositeHashKey *k = key; + memcpy(dst, src, key_size); + BitmapHashKey *d = dst, *s = src; + switch (s->type) { + case BITMAP_OUTLINE: + ass_cache_inc_ref(s->u.outline.outline); + break; + case BITMAP_CLIP: + d->u.clip.text = strdup(s->u.clip.text); + if (!d->u.clip.text) + return false; + break; + } + return true; +} + +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); - for (size_t i = 0; i < k->bitmap_count; i++) - ass_cache_dec_ref(k->bitmaps[i].image); - free(k->bitmaps); + switch (k->type) { + case BITMAP_OUTLINE: ass_cache_dec_ref(k->u.outline.outline); break; + case BITMAP_CLIP: free(k->u.clip.text); break; + } } -static size_t composite_size(void *value, size_t value_size) +static size_t bitmap_size(void *value, size_t value_size) { - CompositeHashValue *val = value; - size_t size = sizeof(CompositeHashKey) + sizeof(CompositeHashValue); + BitmapHashValue *val = value; + size_t size = sizeof(BitmapHashKey) + sizeof(BitmapHashValue); if (val->bm) size += sizeof(Bitmap) + val->bm->stride * val->bm->h; if (val->bm_o) size += sizeof(Bitmap) + val->bm_o->stride * val->bm_o->h; - if (val->bm_s) - size += sizeof(Bitmap) + val->bm_s->stride * val->bm_s->h; return size; } +// composite cache static unsigned composite_hash(void *key, size_t key_size) { CompositeHashKey *k = key; @@ -172,8 +169,44 @@ static unsigned composite_compare(void *a, void *b, size_t key_size) return filter_compare(&ak->filter, &bk->filter, key_size); } -// outline cache +static bool composite_key_copy(void *dst, void *src, size_t key_size) +{ + memcpy(dst, src, key_size); + CompositeHashKey *k = src; + for (size_t i = 0; i < k->bitmap_count; i++) + ass_cache_inc_ref(k->bitmaps[i].image); + return true; +} +static void composite_destruct(void *key, void *value) +{ + CompositeHashValue *v = value; + CompositeHashKey *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); + for (size_t i = 0; i < k->bitmap_count; i++) + ass_cache_dec_ref(k->bitmaps[i].image); + free(k->bitmaps); +} + +static size_t composite_size(void *value, size_t value_size) +{ + CompositeHashValue *val = value; + size_t size = sizeof(CompositeHashKey) + sizeof(CompositeHashValue); + if (val->bm) + size += sizeof(Bitmap) + val->bm->stride * val->bm->h; + if (val->bm_o) + size += sizeof(Bitmap) + val->bm_o->stride * val->bm_o->h; + if (val->bm_s) + size += sizeof(Bitmap) + val->bm_s->stride * val->bm_s->h; + return size; +} + +// outline cache static unsigned outline_hash(void *key, size_t key_size) { OutlineHashKey *k = key; @@ -196,6 +229,23 @@ static unsigned outline_compare(void *a, void *b, size_t key_size) } } +static bool outline_key_copy(void *dst, void *src, size_t key_size) +{ + memcpy(dst, src, key_size); + OutlineHashKey *d = dst, *s = src; + switch (s->type) { + case OUTLINE_GLYPH: + ass_cache_inc_ref(s->u.glyph.font); + break; + case OUTLINE_DRAWING: + d->u.drawing.text = strdup(s->u.drawing.text); + if (!d->u.drawing.text) + return false; + break; + } + return true; +} + static void outline_destruct(void *key, void *value) { OutlineHashValue *v = value; @@ -212,6 +262,14 @@ static void outline_destruct(void *key, void *value) // glyph metric cache +static bool glyph_metric_key_copy(void *dst, void *src, size_t key_size) +{ + memcpy(dst, src, key_size); + GlyphMetricsHashKey *k = src; + ass_cache_inc_ref(k->font); + return true; +} + static void glyph_metric_destruct(void *key, void *value) { GlyphMetricsHashKey *k = key; @@ -236,6 +294,7 @@ struct cache { HashFunction hash_func; ItemSize size_func; HashCompare compare_func; + CacheKeyCopy copy_func; CacheItemDestructor destruct_func; size_t key_size; size_t value_size; @@ -271,6 +330,13 @@ static unsigned compare_simple(void *a, void *b, size_t key_size) return memcmp(a, b, key_size) == 0; } +// Default copy function +static bool copy_simple(void *dst, void *src, size_t key_size) +{ + memcpy(dst, src, key_size); + return true; +} + // Default destructor static void destruct_simple(void *key, void *value) { @@ -279,24 +345,19 @@ static void destruct_simple(void *key, void *value) // Create a cache with type-specific hash/compare/destruct/size functions Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func, - CacheItemDestructor destruct_func, ItemSize size_func, - size_t key_size, size_t value_size) + CacheKeyCopy copy_func, CacheItemDestructor destruct_func, + ItemSize size_func, size_t key_size, size_t value_size) { Cache *cache = calloc(1, sizeof(*cache)); if (!cache) return NULL; cache->buckets = 0xFFFF; cache->queue_last = &cache->queue_first; - cache->hash_func = hash_simple; - cache->compare_func = compare_simple; - cache->destruct_func = destruct_simple; + cache->hash_func = hash_func ? hash_func : hash_simple; + cache->compare_func = compare_func ? compare_func : compare_simple; + cache->copy_func = copy_func ? copy_func : copy_simple; + cache->destruct_func = destruct_func ? destruct_func : destruct_simple; cache->size_func = size_func; - if (hash_func) - cache->hash_func = hash_func; - if (compare_func) - cache->compare_func = compare_func; - if (destruct_func) - cache->destruct_func = destruct_func; cache->key_size = key_size; cache->value_size = value_size; cache->map = calloc(cache->buckets, sizeof(CacheItem *)); @@ -338,12 +399,16 @@ bool ass_cache_get(Cache *cache, void *key, void *value_ptr) item = malloc(key_offs + cache->key_size); if (!item) { *value = NULL; - return 0; + return false; } item->size = 0; item->cache = cache; + if (!cache->copy_func((char *) item + key_offs, key, cache->key_size)) { + free(item); + *value = NULL; + return false; + } *value = (char *) item + CACHE_ITEM_SIZE; - memcpy((char *) item + key_offs, key, cache->key_size); CacheItem **bucketptr = &cache->map[bucket]; if (*bucketptr) @@ -364,7 +429,6 @@ bool ass_cache_get(Cache *cache, void *key, void *value_ptr) void *ass_cache_get_key(void *value) { CacheItem *item = value_to_item(value); - assert(!item->size); return (char *) value + align_cache(item->cache->value_size); } @@ -382,21 +446,6 @@ void ass_cache_commit(void *value) cache->cache_size += item->size; } -void ass_cache_cancel(void *value) -{ - CacheItem *item = value_to_item(value); - assert(!item->size); - - if (item->queue_next) - item->queue_next->queue_prev = item->queue_prev; - *item->queue_prev = item->queue_next; - - if (item->next) - item->next->prev = item->prev; - *item->prev = item->next; - free(item); -} - static inline void destroy_item(Cache *cache, CacheItem *item) { assert(item->cache == cache); @@ -502,32 +551,35 @@ void ass_cache_done(Cache *cache) // Type-specific creation function Cache *ass_font_cache_create(void) { - return ass_cache_create(font_hash, font_compare, font_destruct, - (ItemSize)NULL, sizeof(ASS_FontDesc), sizeof(ASS_Font)); + return ass_cache_create(font_hash, font_compare, + font_key_copy, font_destruct, NULL, + sizeof(ASS_FontDesc), sizeof(ASS_Font)); } Cache *ass_outline_cache_create(void) { - return ass_cache_create(outline_hash, outline_compare, outline_destruct, - NULL, sizeof(OutlineHashKey), sizeof(OutlineHashValue)); + return ass_cache_create(outline_hash, outline_compare, + outline_key_copy, outline_destruct, NULL, + sizeof(OutlineHashKey), sizeof(OutlineHashValue)); } Cache *ass_glyph_metrics_cache_create(void) { - return ass_cache_create(glyph_metrics_hash, glyph_metrics_compare, glyph_metric_destruct, - (ItemSize) NULL, sizeof(GlyphMetricsHashKey), - sizeof(GlyphMetricsHashValue)); + return ass_cache_create(glyph_metrics_hash, glyph_metrics_compare, + glyph_metric_key_copy, glyph_metric_destruct, NULL, + sizeof(GlyphMetricsHashKey), sizeof(GlyphMetricsHashValue)); } Cache *ass_bitmap_cache_create(void) { - return ass_cache_create(bitmap_hash, bitmap_compare, bitmap_destruct, - bitmap_size, sizeof(BitmapHashKey), sizeof(BitmapHashValue)); + return ass_cache_create(bitmap_hash, bitmap_compare, + bitmap_key_copy, bitmap_destruct, bitmap_size, + sizeof(BitmapHashKey), sizeof(BitmapHashValue)); } Cache *ass_composite_cache_create(void) { return ass_cache_create(composite_hash, composite_compare, - composite_destruct, composite_size, sizeof(CompositeHashKey), - sizeof(CompositeHashValue)); + composite_key_copy, composite_destruct, composite_size, + sizeof(CompositeHashKey), sizeof(CompositeHashValue)); } |