summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDr.Smile <vabnick@gmail.com>2015-09-19 03:08:29 +0300
committerDr.Smile <vabnick@gmail.com>2016-06-30 23:13:53 +0300
commit96601ede589799cb84cec4a616467c9e08412509 (patch)
tree7ccafe0cd9a325d23c6f4aeb7a5645518262ab9f
parent954c0163a7c7669c0c54527d4fe66745a0f572ef (diff)
downloadlibass-96601ede589799cb84cec4a616467c9e08412509.tar.bz2
libass-96601ede589799cb84cec4a616467c9e08412509.tar.xz
cache: keep ref_count of all active objects nonzero
-rw-r--r--libass/ass_cache.c115
-rw-r--r--libass/ass_cache.h6
-rw-r--r--libass/ass_font.c11
-rw-r--r--libass/ass_parse.c2
-rw-r--r--libass/ass_render.c78
-rw-r--r--libass/ass_render.h4
-rw-r--r--libass/ass_shaper.c54
7 files changed, 164 insertions, 106 deletions
diff --git a/libass/ass_cache.c b/libass/ass_cache.c
index ce742e6..18904d2 100644
--- a/libass/ass_cache.c
+++ b/libass/ass_cache.c
@@ -63,12 +63,14 @@ static unsigned font_compare(void *key1, void *key2, size_t key_size)
return 1;
}
-static bool font_key_copy(void *dst, void *src, size_t key_size)
+static bool font_key_move(void *dst, void *src, size_t key_size)
{
- memcpy(dst, src, key_size);
- ASS_FontDesc *d = dst, *s = src;
- d->family = strdup(s->family);
- return d->family;
+ ASS_FontDesc *k = src;
+ if (dst)
+ memcpy(dst, src, key_size);
+ else
+ free(k->family);
+ return true;
}
static void font_destruct(void *key, void *value)
@@ -99,21 +101,19 @@ static unsigned bitmap_compare(void *a, void *b, size_t key_size)
}
}
-static bool bitmap_key_copy(void *dst, void *src, size_t key_size)
+static bool bitmap_key_move(void *dst, void *src, size_t key_size)
{
- 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;
+ if (!dst) {
+ if (s->type == BITMAP_OUTLINE)
+ ass_cache_dec_ref(s->u.outline.outline);
+ return true;
}
- return true;
+ memcpy(dst, src, key_size);
+ if (s->type != BITMAP_CLIP)
+ return true;
+ d->u.clip.text = strdup(s->u.clip.text);
+ return d->u.clip.text;
}
static void bitmap_destruct(void *key, void *value)
@@ -158,12 +158,16 @@ static unsigned composite_compare(void *a, void *b, size_t key_size)
return filter_compare(&ak->filter, &bk->filter, key_size);
}
-static bool composite_key_copy(void *dst, void *src, size_t key_size)
+static bool composite_key_move(void *dst, void *src, size_t key_size)
{
- memcpy(dst, src, key_size);
+ if (dst) {
+ memcpy(dst, src, key_size);
+ return true;
+ }
CompositeHashKey *k = src;
for (size_t i = 0; i < k->bitmap_count; i++)
- ass_cache_inc_ref(k->bitmaps[i].image);
+ ass_cache_dec_ref(k->bitmaps[i].image);
+ free(k->bitmaps);
return true;
}
@@ -205,21 +209,19 @@ 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)
+static bool outline_key_move(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;
+ if (!dst) {
+ if (s->type == OUTLINE_GLYPH)
+ ass_cache_dec_ref(s->u.glyph.font);
+ return true;
}
- return true;
+ memcpy(dst, src, key_size);
+ if (s->type != OUTLINE_DRAWING)
+ return true;
+ d->u.drawing.text = strdup(s->u.drawing.text);
+ return d->u.drawing.text;
}
static void outline_destruct(void *key, void *value)
@@ -238,8 +240,10 @@ 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)
+static bool glyph_metric_key_move(void *dst, void *src, size_t key_size)
{
+ if (!dst)
+ return true;
memcpy(dst, src, key_size);
GlyphMetricsHashKey *k = src;
ass_cache_inc_ref(k->font);
@@ -269,7 +273,7 @@ struct cache {
HashFunction hash_func;
HashCompare compare_func;
- CacheKeyCopy copy_func;
+ CacheKeyMove key_move_func;
CacheItemDestructor destruct_func;
size_t key_size;
size_t value_size;
@@ -306,9 +310,10 @@ static unsigned compare_simple(void *a, void *b, size_t key_size)
}
// Default copy function
-static bool copy_simple(void *dst, void *src, size_t key_size)
+static bool key_move_simple(void *dst, void *src, size_t key_size)
{
- memcpy(dst, src, key_size);
+ if (dst)
+ memcpy(dst, src, key_size);
return true;
}
@@ -320,7 +325,7 @@ 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,
- CacheKeyCopy copy_func, CacheItemDestructor destruct_func,
+ CacheKeyMove key_move_func, CacheItemDestructor destruct_func,
size_t key_size, size_t value_size)
{
Cache *cache = calloc(1, sizeof(*cache));
@@ -330,7 +335,7 @@ Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func,
cache->queue_last = &cache->queue_first;
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->key_move_func = key_move_func ? key_move_func : key_move_simple;
cache->destruct_func = destruct_func ? destruct_func : destruct_simple;
cache->key_size = key_size;
cache->value_size = value_size;
@@ -363,7 +368,9 @@ bool ass_cache_get(Cache *cache, void *key, void *value_ptr)
item->queue_next = NULL;
}
cache->hits++;
+ cache->key_move_func(NULL, key, cache->key_size);
*value = (char *) item + CACHE_ITEM_SIZE;
+ item->ref_count++;
return true;
}
item = item->next;
@@ -372,12 +379,13 @@ bool ass_cache_get(Cache *cache, void *key, void *value_ptr)
item = malloc(key_offs + cache->key_size);
if (!item) {
+ cache->key_move_func(NULL, key, cache->key_size);
*value = NULL;
return false;
}
item->size = 0;
item->cache = cache;
- if (!cache->copy_func((char *) item + key_offs, key, cache->key_size)) {
+ if (!cache->key_move_func((char *) item + key_offs, key, cache->key_size)) {
free(item);
*value = NULL;
return false;
@@ -391,16 +399,13 @@ bool ass_cache_get(Cache *cache, void *key, void *value_ptr)
item->next = *bucketptr;
*bucketptr = item;
- *cache->queue_last = item;
- item->queue_prev = cache->queue_last;
- cache->queue_last = &item->queue_next;
+ item->queue_prev = NULL;
item->queue_next = NULL;
-
- item->ref_count = 0;
+ item->ref_count = 1;
return false;
}
-void *ass_cache_get_key(void *value)
+void *ass_cache_key(void *value)
{
CacheItem *item = value_to_item(value);
return (char *) value + align_cache(item->cache->value_size);
@@ -414,6 +419,10 @@ void ass_cache_commit(void *value, size_t item_size)
Cache *cache = item->cache;
cache->cache_size += item_size;
cache->items++;
+
+ *cache->queue_last = item;
+ item->queue_prev = cache->queue_last;
+ cache->queue_last = &item->queue_next;
}
static inline void destroy_item(Cache *cache, CacheItem *item)
@@ -426,6 +435,8 @@ static inline void destroy_item(Cache *cache, CacheItem *item)
void ass_cache_inc_ref(void *value)
{
+ if (!value)
+ return;
CacheItem *item = value_to_item(value);
assert(item->size);
item->ref_count++;
@@ -433,6 +444,8 @@ void ass_cache_inc_ref(void *value)
void ass_cache_dec_ref(void *value)
{
+ if (!value)
+ return;
CacheItem *item = value_to_item(value);
assert(item->size && item->ref_count);
@@ -498,7 +511,7 @@ void ass_cache_empty(Cache *cache)
for (int i = 0; i < cache->buckets; i++) {
CacheItem *item = cache->map[i];
while (item) {
- assert(item->size);
+ assert(item->size && !item->ref_count);
CacheItem *next = item->next;
destroy_item(cache, item);
item = next;
@@ -522,34 +535,34 @@ void ass_cache_done(Cache *cache)
Cache *ass_font_cache_create(void)
{
return ass_cache_create(font_hash, font_compare,
- font_key_copy, font_destruct,
+ font_key_move, font_destruct,
sizeof(ASS_FontDesc), sizeof(ASS_Font));
}
Cache *ass_outline_cache_create(void)
{
return ass_cache_create(outline_hash, outline_compare,
- outline_key_copy, outline_destruct,
+ outline_key_move, outline_destruct,
sizeof(OutlineHashKey), sizeof(OutlineHashValue));
}
Cache *ass_glyph_metrics_cache_create(void)
{
return ass_cache_create(glyph_metrics_hash, glyph_metrics_compare,
- glyph_metric_key_copy, glyph_metric_destruct,
+ glyph_metric_key_move, glyph_metric_destruct,
sizeof(GlyphMetricsHashKey), sizeof(GlyphMetricsHashValue));
}
Cache *ass_bitmap_cache_create(void)
{
return ass_cache_create(bitmap_hash, bitmap_compare,
- bitmap_key_copy, bitmap_destruct,
+ bitmap_key_move, bitmap_destruct,
sizeof(BitmapHashKey), sizeof(BitmapHashValue));
}
Cache *ass_composite_cache_create(void)
{
return ass_cache_create(composite_hash, composite_compare,
- composite_key_copy, composite_destruct,
+ composite_key_move, composite_destruct,
sizeof(CompositeHashKey), sizeof(CompositeHashValue));
}
diff --git a/libass/ass_cache.h b/libass/ass_cache.h
index 6cea269..cd72533 100644
--- a/libass/ass_cache.h
+++ b/libass/ass_cache.h
@@ -58,7 +58,7 @@ typedef struct {
// Type-specific function pointers
typedef unsigned(*HashFunction)(void *key, size_t key_size);
typedef unsigned(*HashCompare)(void *a, void *b, size_t key_size);
-typedef bool(*CacheKeyCopy)(void *dst, void *src, size_t key_size);
+typedef bool(*CacheKeyMove)(void *dst, void *src, size_t key_size);
typedef void(*CacheItemDestructor)(void *key, void *value);
// cache hash keys
@@ -104,10 +104,10 @@ typedef struct {
} CompositeHashKey;
Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func,
- CacheKeyCopy copy_func, CacheItemDestructor destruct_func,
+ CacheKeyMove copy_func, CacheItemDestructor destruct_func,
size_t key_size, size_t value_size);
bool ass_cache_get(Cache *cache, void *key, void *value_ptr);
-void *ass_cache_get_key(void *value);
+void *ass_cache_key(void *value);
void ass_cache_commit(void *value, size_t item_size);
void ass_cache_inc_ref(void *value);
void ass_cache_dec_ref(void *value);
diff --git a/libass/ass_font.c b/libass/ass_font.c
index d9dc7ba..5889b49 100644
--- a/libass/ass_font.c
+++ b/libass/ass_font.c
@@ -229,8 +229,12 @@ ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library,
ASS_FontDesc *desc)
{
ASS_Font *font;
- if (ass_cache_get(font_cache, desc, &font))
- return font->desc.family ? font : NULL;
+ if (ass_cache_get(font_cache, desc, &font)) {
+ if (font->desc.family)
+ return font;
+ ass_cache_dec_ref(font);
+ return NULL;
+ }
if (!font)
return NULL;
@@ -238,7 +242,7 @@ ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library,
font->ftlibrary = ftlibrary;
font->shaper_priv = NULL;
font->n_faces = 0;
- ASS_FontDesc *new_desc = ass_cache_get_key(font);
+ ASS_FontDesc *new_desc = ass_cache_key(font);
font->desc.family = new_desc->family;
font->desc.bold = desc->bold;
font->desc.italic = desc->italic;
@@ -252,6 +256,7 @@ ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library,
if (error == -1) {
font->desc.family = NULL;
ass_cache_commit(font, 1);
+ ass_cache_dec_ref(font);
return NULL;
}
ass_cache_commit(font, 1);
diff --git a/libass/ass_parse.c b/libass/ass_parse.c
index e6db422..5698669 100644
--- a/libass/ass_parse.c
+++ b/libass/ass_parse.c
@@ -127,11 +127,11 @@ void update_font(ASS_Renderer *render_priv)
val = 0; // normal
desc.italic = val;
+ ass_cache_dec_ref(render_priv->state.font);
render_priv->state.font =
ass_font_new(render_priv->cache.font_cache, render_priv->library,
render_priv->ftlibrary, render_priv->fontselect,
&desc);
- free(desc.family);
if (render_priv->state.font)
change_font_size(render_priv, render_priv->state.font_size);
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 53d2681..29a5a3d 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -515,6 +515,7 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
ass_msg(render_priv->library, MSGL_WARN,
"Clip vector parsing failed. Skipping.");
ass_cache_commit(val, sizeof(BitmapHashKey) + sizeof(BitmapHashValue));
+ ass_cache_dec_ref(val);
return;
}
@@ -534,7 +535,10 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
}
Bitmap *clip_bm = val->bm;
- if (!clip_bm) return;
+ if (!clip_bm) {
+ ass_cache_dec_ref(val);
+ return;
+ }
// Iterate through bitmaps and blend/clip them
for (ASS_Image *cur = head; cur; cur = cur->next) {
@@ -582,7 +586,7 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
nbuffer = ass_aligned_alloc(32, as * ah);
if (!free_list_add(render_priv, nbuffer)) {
ass_aligned_free(nbuffer);
- return;
+ break;
}
// Blend together
@@ -604,7 +608,7 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
nbuffer = ass_aligned_alloc(align, ns * h);
if (!free_list_add(render_priv, nbuffer)) {
ass_aligned_free(nbuffer);
- return;
+ break;
}
// Blend together
@@ -620,6 +624,8 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
}
cur->bitmap = nbuffer;
}
+
+ ass_cache_dec_ref(val);
}
/**
@@ -685,6 +691,11 @@ static ASS_Image *render_text(ASS_Renderer *render_priv)
*tail = 0;
blend_vector_clip(render_priv, head);
+ for (int i = 0; i < text_info->n_bitmaps; ++i) {
+ CombinedBitmapInfo *info = &text_info->combined_bitmaps[i];
+ ass_cache_dec_ref(info->image); // XXX: not thread safe
+ }
+
return head;
}
@@ -921,9 +932,11 @@ init_render_context(ASS_Renderer *render_priv, ASS_Event *event)
static void free_render_context(ASS_Renderer *render_priv)
{
+ ass_cache_dec_ref(render_priv->state.font);
free(render_priv->state.family);
ass_drawing_free(render_priv->state.clip_drawing);
+ render_priv->state.font = NULL;
render_priv->state.family = NULL;
render_priv->state.clip_drawing = NULL;
@@ -1168,6 +1181,7 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
ass_drawing_hash(drawing);
if(!ass_drawing_parse(drawing, 0)) {
ass_cache_commit(val, 1);
+ ass_cache_dec_ref(val);
return;
}
val->outline = outline_copy(&drawing->outline);
@@ -1200,6 +1214,7 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
if (!val->outline) {
ass_cache_commit(val, 1);
+ ass_cache_dec_ref(val);
return;
}
@@ -1212,6 +1227,7 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
free(val->outline);
val->outline = NULL;
ass_cache_commit(val, 1);
+ ass_cache_dec_ref(val);
return;
}
@@ -1238,8 +1254,10 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
ass_cache_commit(val, 1);
}
- if (!val->outline)
+ if (!val->outline) {
+ ass_cache_dec_ref(val);
return;
+ }
info->hash_key.u.outline.outline = val;
info->outline = val->outline;
@@ -1903,6 +1921,8 @@ static int parse_events(ASS_Renderer *render_priv, ASS_Event *event)
// Fill glyph information
info->symbol = code;
info->font = render_priv->state.font;
+ if (!info->drawing)
+ ass_cache_inc_ref(info->font);
for (i = 0; i < 4; ++i) {
uint32_t clr = render_priv->state.c[i];
// VSFilter compatibility: apply fade only when it's positive
@@ -2166,10 +2186,14 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
CombinedBitmapInfo *combined_info = text_info->combined_bitmaps;
CombinedBitmapInfo *current_info = NULL;
GlyphInfo *last_info = NULL;
- for (int i = 0; i < text_info->length; ++i) {
+ for (int i = 0; i < text_info->length; i++) {
GlyphInfo *info = text_info->glyphs + i;
if (info->linebreak) linebreak = 1;
- if (info->skip) continue;
+ if (info->skip) {
+ for (; info; info = info->next)
+ ass_cache_dec_ref(info->hash_key.u.outline.outline);
+ continue;
+ }
for (; info; info = info->next) {
OutlineBitmapHashKey *key = &info->hash_key.u.outline;
@@ -2185,8 +2209,10 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
last_info = NULL;
if (nb_bitmaps >= text_info->max_bitmaps) {
size_t new_size = 2 * text_info->max_bitmaps;
- if (!ASS_REALLOC_ARRAY(text_info->combined_bitmaps, new_size))
+ if (!ASS_REALLOC_ARRAY(text_info->combined_bitmaps, new_size)) {
+ ass_cache_dec_ref(info->image);
continue;
+ }
text_info->max_bitmaps = new_size;
combined_info = text_info->combined_bitmaps;
}
@@ -2217,49 +2243,56 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
current_info->x = current_info->y = INT_MAX;
rectangle_reset(&current_info->rect);
rectangle_reset(&current_info->rect_o);
- current_info->bm = current_info->bm_o = current_info->bm_s = NULL;
current_info->n_bm = current_info->n_bm_o = 0;
+ current_info->bm = current_info->bm_o = current_info->bm_s = NULL;
+ current_info->image = NULL;
current_info->bitmap_count = current_info->max_bitmap_count = 0;
current_info->bitmaps = malloc(MAX_SUB_BITMAPS_INITIAL * sizeof(BitmapRef));
- if (!current_info->bitmaps)
+ if (!current_info->bitmaps) {
+ ass_cache_dec_ref(info->image);
continue;
+ }
current_info->max_bitmap_count = MAX_SUB_BITMAPS_INITIAL;
- ++nb_bitmaps;
+ nb_bitmaps++;
}
last_info = info;
- if (!info->image || !current_info)
+ if (!info->image || !current_info) {
+ ass_cache_dec_ref(info->image);
continue;
+ }
if (current_info->bitmap_count >= current_info->max_bitmap_count) {
size_t new_size = 2 * current_info->max_bitmap_count;
- if (!ASS_REALLOC_ARRAY(current_info->bitmaps, new_size))
+ if (!ASS_REALLOC_ARRAY(current_info->bitmaps, new_size)) {
+ ass_cache_dec_ref(info->image);
continue;
+ }
current_info->max_bitmap_count = new_size;
}
current_info->bitmaps[current_info->bitmap_count].image = info->image;
current_info->bitmaps[current_info->bitmap_count].x = x;
current_info->bitmaps[current_info->bitmap_count].y = y;
- ++current_info->bitmap_count;
+ current_info->bitmap_count++;
current_info->x = FFMIN(current_info->x, x);
current_info->y = FFMIN(current_info->y, y);
if (info->image->bm) {
rectangle_combine(&current_info->rect, info->image->bm, x, y);
- ++current_info->n_bm;
+ current_info->n_bm++;
}
if (info->image->bm_o) {
rectangle_combine(&current_info->rect_o, info->image->bm_o, x, y);
- ++current_info->n_bm_o;
+ current_info->n_bm_o++;
}
}
}
- for (int i = 0; i < nb_bitmaps; ++i) {
+ for (int i = 0; i < nb_bitmaps; i++) {
CombinedBitmapInfo *info = &combined_info[i];
- for (int j = 0; j < info->bitmap_count; ++j) {
+ for (int j = 0; j < info->bitmap_count; j++) {
info->bitmaps[j].x -= info->x;
info->bitmaps[j].y -= info->y;
}
@@ -2271,7 +2304,7 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
info->bm = hv->bm;
info->bm_o = hv->bm_o;
info->bm_s = hv->bm_s;
- free(info->bitmaps);
+ info->image = hv;
continue;
}
if (!hv)
@@ -2279,7 +2312,7 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
int bord = be_padding(info->filter.be);
if (!bord && info->n_bm == 1) {
- for (int j = 0; j < info->bitmap_count; ++j) {
+ for (int j = 0; j < info->bitmap_count; j++) {
if (!info->bitmaps[j].image->bm)
continue;
info->bm = copy_bitmap(render_priv->engine, info->bitmaps[j].image->bm);
@@ -2297,7 +2330,7 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
if (dst) {
dst->left = info->rect.x_min - info->x - bord;
dst->top = info->rect.y_min - info->y - bord;
- for (int j = 0; j < info->bitmap_count; ++j) {
+ for (int j = 0; j < info->bitmap_count; j++) {
Bitmap *src = info->bitmaps[j].image->bm;
if (!src)
continue;
@@ -2313,7 +2346,7 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
}
}
if (!bord && info->n_bm_o == 1) {
- for (int j = 0; j < info->bitmap_count; ++j) {
+ for (int j = 0; j < info->bitmap_count; j++) {
if (!info->bitmaps[j].image->bm_o)
continue;
info->bm_o = copy_bitmap(render_priv->engine, info->bitmaps[j].image->bm_o);
@@ -2331,7 +2364,7 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
if (dst) {
dst->left = info->rect_o.x_min - info->x - bord;
dst->top = info->rect_o.y_min - info->y - bord;
- for (int j = 0; j < info->bitmap_count; ++j) {
+ for (int j = 0; j < info->bitmap_count; j++) {
Bitmap *src = info->bitmaps[j].image->bm_o;
if (!src)
continue;
@@ -2360,6 +2393,7 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
ass_cache_commit(hv, bitmap_size(hv->bm) +
bitmap_size(hv->bm_o) + bitmap_size(hv->bm_s) +
sizeof(CompositeHashKey) + sizeof(CompositeHashValue));
+ info->image = hv;
}
text_info->n_bitmaps = nb_bitmaps;
diff --git a/libass/ass_render.h b/libass/ass_render.h
index 83dd1d8..ac7d347 100644
--- a/libass/ass_render.h
+++ b/libass/ass_render.h
@@ -125,8 +125,10 @@ typedef struct {
int x, y;
Rectangle rect, rect_o;
- Bitmap *bm, *bm_o, *bm_s; // glyphs, outline, shadow bitmaps
size_t n_bm, n_bm_o;
+
+ Bitmap *bm, *bm_o, *bm_s; // glyphs, outline, shadow bitmaps
+ CompositeHashValue *image;
} CombinedBitmapInfo;
// describes a glyph
diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c
index 8cb8654..95222ae 100644
--- a/libass/ass_shaper.c
+++ b/libass/ass_shaper.c
@@ -208,8 +208,12 @@ get_cached_metrics(struct ass_shaper_metrics_data *metrics, FT_Face face,
{
GlyphMetricsHashValue *val;
metrics->hash_key.glyph_index = glyph;
- if (ass_cache_get(metrics->metrics_cache, &metrics->hash_key, &val))
- return val->metrics.width < 0 ? NULL : val;
+ if (ass_cache_get(metrics->metrics_cache, &metrics->hash_key, &val)) {
+ if (val->metrics.width >= 0)
+ return val;
+ ass_cache_dec_ref(val);
+ return NULL;
+ }
if (!val)
return NULL;
@@ -219,6 +223,7 @@ get_cached_metrics(struct ass_shaper_metrics_data *metrics, FT_Face face,
if (FT_Load_Glyph(face, glyph, load_flags)) {
val->metrics.width = -1;
ass_cache_commit(val, 1);
+ ass_cache_dec_ref(val);
return NULL;
}
@@ -244,12 +249,13 @@ get_glyph(hb_font_t *font, void *font_data, hb_codepoint_t unicode,
*glyph = FT_Face_GetCharVariantIndex(face, ass_font_index_magic(face, unicode), variation);
else
*glyph = FT_Get_Char_Index(face, ass_font_index_magic(face, unicode));
+ if (!*glyph)
+ return false;
// rotate glyph advances for @fonts while we still know the Unicode codepoints
- if (*glyph != 0)
- get_cached_metrics(metrics_priv, face, unicode, *glyph);
-
- return *glyph != 0;
+ GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, unicode, *glyph);
+ ass_cache_dec_ref(metrics);
+ return true;
}
static hb_position_t
@@ -259,11 +265,12 @@ cached_h_advance(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
FT_Face face = font_data;
struct ass_shaper_metrics_data *metrics_priv = user_data;
GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, 0, glyph);
-
if (!metrics)
return 0;
- return metrics->metrics.horiAdvance;
+ hb_position_t advance = metrics->metrics.horiAdvance;
+ ass_cache_dec_ref(metrics);
+ return advance;
}
static hb_position_t
@@ -273,19 +280,19 @@ cached_v_advance(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
FT_Face face = font_data;
struct ass_shaper_metrics_data *metrics_priv = user_data;
GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, 0, glyph);
-
if (!metrics)
return 0;
- return metrics->metrics.vertAdvance;
-
+ hb_position_t advance = metrics->metrics.vertAdvance;
+ ass_cache_dec_ref(metrics);
+ return advance;
}
static hb_bool_t
cached_h_origin(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
hb_position_t *x, hb_position_t *y, void *user_data)
{
- return 1;
+ return true;
}
static hb_bool_t
@@ -295,14 +302,13 @@ cached_v_origin(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
FT_Face face = font_data;
struct ass_shaper_metrics_data *metrics_priv = user_data;
GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, 0, glyph);
-
if (!metrics)
- return 0;
+ return false;
*x = metrics->metrics.horiBearingX - metrics->metrics.vertBearingX;
*y = metrics->metrics.horiBearingY - (-metrics->metrics.vertBearingY);
-
- return 1;
+ ass_cache_dec_ref(metrics);
+ return true;
}
static hb_position_t
@@ -312,7 +318,7 @@ get_h_kerning(hb_font_t *font, void *font_data, hb_codepoint_t first,
FT_Face face = font_data;
FT_Vector kern;
- if (FT_Get_Kerning (face, first, second, FT_KERNING_DEFAULT, &kern))
+ if (FT_Get_Kerning(face, first, second, FT_KERNING_DEFAULT, &kern))
return 0;
return kern.x;
@@ -332,16 +338,15 @@ cached_extents(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
FT_Face face = font_data;
struct ass_shaper_metrics_data *metrics_priv = user_data;
GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, 0, glyph);
-
if (!metrics)
- return 0;
+ return false;
extents->x_bearing = metrics->metrics.horiBearingX;
extents->y_bearing = metrics->metrics.horiBearingY;
extents->width = metrics->metrics.width;
extents->height = -metrics->metrics.height;
-
- return 1;
+ ass_cache_dec_ref(metrics);
+ return true;
}
static hb_bool_t
@@ -354,15 +359,14 @@ get_contour_point(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
| FT_LOAD_IGNORE_TRANSFORM;
if (FT_Load_Glyph(face, glyph, load_flags))
- return 0;
+ return false;
if (point_index >= (unsigned)face->glyph->outline.n_points)
- return 0;
+ return false;
*x = face->glyph->outline.points[point_index].x;
*y = face->glyph->outline.points[point_index].y;
-
- return 1;
+ return true;
}
/**