summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDr.Smile <vabnick@gmail.com>2015-09-18 00:33:33 +0300
committerDr.Smile <vabnick@gmail.com>2016-06-30 23:13:53 +0300
commitf4d6e4b9af4cfe2fe684640f19682e4f954b7549 (patch)
treee5d817822df0f3448c0708924c7babd553856197
parent25d65abce1a0fabe3c3bf81f1ee7ee7f24b91a4e (diff)
downloadlibass-f4d6e4b9af4cfe2fe684640f19682e4f954b7549.tar.bz2
libass-f4d6e4b9af4cfe2fe684640f19682e4f954b7549.tar.xz
cache: remove ass_cache_cancel(), cache failures instead
-rw-r--r--libass/ass_cache.c212
-rw-r--r--libass/ass_cache.h6
-rw-r--r--libass/ass_font.c15
-rw-r--r--libass/ass_render.c147
-rw-r--r--libass/ass_shaper.c32
5 files changed, 228 insertions, 184 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));
}
diff --git a/libass/ass_cache.h b/libass/ass_cache.h
index 63e9e59..c18f9d8 100644
--- a/libass/ass_cache.h
+++ b/libass/ass_cache.h
@@ -59,6 +59,7 @@ typedef struct {
typedef unsigned(*HashFunction)(void *key, size_t key_size);
typedef size_t(*ItemSize)(void *value, size_t value_size);
typedef unsigned(*HashCompare)(void *a, void *b, size_t key_size);
+typedef bool(*CacheKeyCopy)(void *dst, void *src, size_t key_size);
typedef void(*CacheItemDestructor)(void *key, void *value);
// cache hash keys
@@ -104,12 +105,11 @@ typedef struct {
} CompositeHashKey;
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);
bool ass_cache_get(Cache *cache, void *key, void *value_ptr);
void *ass_cache_get_key(void *value);
void ass_cache_commit(void *value);
-void ass_cache_cancel(void *value);
void ass_cache_inc_ref(void *value);
void ass_cache_dec_ref(void *value);
void ass_cache_cut(Cache *cache, size_t max_size);
diff --git a/libass/ass_font.c b/libass/ass_font.c
index a4c45bd..c40ff1e 100644
--- a/libass/ass_font.c
+++ b/libass/ass_font.c
@@ -228,17 +228,18 @@ ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library,
FT_Library ftlibrary, ASS_FontSelector *fontsel,
ASS_FontDesc *desc)
{
- int error;
ASS_Font *font;
if (ass_cache_get(font_cache, desc, &font))
- return font;
+ return font->desc.family ? font : NULL;
+ if (!font)
+ return NULL;
font->library = library;
font->ftlibrary = ftlibrary;
font->shaper_priv = NULL;
font->n_faces = 0;
ASS_FontDesc *new_desc = ass_cache_get_key(font);
- font->desc.family = new_desc->family = strdup(desc->family);
+ font->desc.family = new_desc->family;
font->desc.bold = desc->bold;
font->desc.italic = desc->italic;
font->desc.vertical = desc->vertical;
@@ -247,11 +248,11 @@ ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library,
font->v.x = font->v.y = 0;
font->size = 0.;
- error = add_face(fontsel, font, 0);
+ int error = add_face(fontsel, font, 0);
if (error == -1) {
- ass_cache_cancel(font);
- free(font->desc.family);
- return 0;
+ font->desc.family = NULL;
+ ass_cache_commit(font);
+ return NULL;
}
ass_cache_commit(font);
return font;
diff --git a/libass/ass_render.c b/libass/ass_render.c
index ef0531d..7a1dd47 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -498,23 +498,17 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
key.u.clip.text = drawing->text;
BitmapHashValue *val;
- Bitmap *clip_bm = NULL;
- if (ass_cache_get(render_priv->cache.bitmap_cache, &key, &val)) {
- clip_bm = val->bm;
- } else {
+ if (!ass_cache_get(render_priv->cache.bitmap_cache, &key, &val)) {
+ if (!val)
+ return;
+ val->bm = val->bm_o = NULL;
+
// Not found in cache, parse and rasterize it
ASS_Outline *outline = ass_drawing_parse(drawing, 1);
if (!outline) {
ass_msg(render_priv->library, MSGL_WARN,
"Clip vector parsing failed. Skipping.");
- ass_cache_cancel(val);
- return;
- }
-
- BitmapHashKey *new_key = ass_cache_get_key(val);
- new_key->u.clip.text = strdup(drawing->text);
- if (!new_key->u.clip.text) {
- ass_cache_cancel(val);
+ ass_cache_commit(val);
return;
}
@@ -528,14 +522,11 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
outline_translate(outline, trans.x, trans.y);
}
- clip_bm = outline_to_bitmap(render_priv, outline, 0);
-
- // Add to cache
- val->bm = clip_bm;
- val->bm_o = NULL;
+ val->bm = outline_to_bitmap(render_priv, outline, 0);
ass_cache_commit(val);
}
+ Bitmap *clip_bm = val->bm;
if (!clip_bm) return;
// Iterate through bitmaps and blend/clip them
@@ -1161,19 +1152,15 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
OutlineHashValue *val;
fill_glyph_hash(priv, &key, info);
if (!ass_cache_get(priv->cache.outline_cache, &key, &val)) {
+ if (!val)
+ return;
memset(val, 0, sizeof(*val));
if (info->drawing) {
ASS_Drawing *drawing = info->drawing;
ass_drawing_hash(drawing);
if(!ass_drawing_parse(drawing, 0)) {
- ass_cache_cancel(val);
- return;
- }
- OutlineHashKey *new_key = ass_cache_get_key(val);
- new_key->u.drawing.text = strdup(drawing->text);
- if(!new_key->u.drawing.text) {
- ass_cache_cancel(val);
+ ass_cache_commit(val);
return;
}
val->outline = outline_copy(&drawing->outline);
@@ -1205,17 +1192,23 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
}
if (!val->outline) {
- ass_cache_cancel(val);
+ ass_cache_commit(val);
return;
}
outline_get_cbox(val->outline, &val->bbox_scaled);
if (info->border_style == 3) {
- FT_Vector advance;
-
val->border = calloc(1, sizeof(ASS_Outline));
+ if (!val->border) {
+ outline_free(val->outline);
+ free(val->outline);
+ val->outline = NULL;
+ ass_cache_commit(val);
+ return;
+ }
+ FT_Vector advance;
if (priv->settings.shaper == ASS_SHAPING_SIMPLE || info->drawing)
advance = val->advance;
else
@@ -1235,11 +1228,12 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
double_to_d6(info->border_y * priv->border_scale));
}
- if (!info->drawing)
- ass_cache_inc_ref(info->font);
ass_cache_commit(val);
}
+ if (!val->outline)
+ return;
+
info->hash_key.u.outline.outline = val;
info->outline = val->outline;
info->border = val->border;
@@ -1343,62 +1337,57 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
BitmapHashValue *val;
OutlineBitmapHashKey *key = &info->hash_key.u.outline;
- if (!ass_cache_get(render_priv->cache.bitmap_cache, &info->hash_key, &val)) {
- FT_Vector shift;
- int error;
- double fax_scaled, fay_scaled;
- double scale_x = render_priv->font_scale_x;
+ if (ass_cache_get(render_priv->cache.bitmap_cache, &info->hash_key, &val)) {
+ info->image = val;
+ return;
+ }
+ if (!val)
+ return;
- val->bm = val->bm_o = NULL;
+ ASS_Outline *outline = outline_copy(info->outline);
+ ASS_Outline *border = outline_copy(info->border);
- ASS_Outline *outline = outline_copy(info->outline);
- ASS_Outline *border = outline_copy(info->border);
-
- // calculating rotation shift vector (from rotation origin to the glyph basepoint)
- shift.x = key->shift_x;
- shift.y = key->shift_y;
- fax_scaled = info->fax / info->scale_y * info->scale_x;
- fay_scaled = info->fay / info->scale_x * info->scale_y;
-
- // apply rotation
- // use blur_scale because, like blurs, VSFilter forgets to scale this
- transform_3d(shift, outline, border,
- info->frx, info->fry, info->frz, fax_scaled,
- fay_scaled, render_priv->blur_scale, info->asc);
-
- // PAR correction scaling
- FT_Matrix m = { double_to_d16(scale_x), 0,
- 0, double_to_d16(1.0) };
-
- // subpixel shift
- if (outline) {
- if (scale_x != 1.0)
- outline_transform(outline, &m);
- outline_translate(outline, key->advance.x, -key->advance.y);
- }
- if (border) {
- if (scale_x != 1.0)
- outline_transform(border, &m);
- outline_translate(border, key->advance.x, -key->advance.y);
- }
+ // calculating rotation shift vector (from rotation origin to the glyph basepoint)
+ FT_Vector shift = { key->shift_x, key->shift_y };
+ double scale_x = render_priv->font_scale_x;
+ double fax_scaled = info->fax / info->scale_y * info->scale_x;
+ double fay_scaled = info->fay / info->scale_x * info->scale_y;
- // render glyph
- error = outline_to_bitmap2(render_priv, outline, border,
- &val->bm, &val->bm_o);
- if (error)
- info->symbol = 0;
+ // apply rotation
+ // use blur_scale because, like blurs, VSFilter forgets to scale this
+ transform_3d(shift, outline, border,
+ info->frx, info->fry, info->frz, fax_scaled,
+ fay_scaled, render_priv->blur_scale, info->asc);
- assert(info->hash_key.type == BITMAP_OUTLINE);
- ass_cache_inc_ref(info->hash_key.u.outline.outline);
- ass_cache_commit(val);
+ // PAR correction scaling
+ FT_Matrix m = { double_to_d16(scale_x), 0,
+ 0, double_to_d16(1.0) };
- outline_free(outline);
- free(outline);
- outline_free(border);
- free(border);
+ // subpixel shift
+ if (outline) {
+ if (scale_x != 1.0)
+ outline_transform(outline, &m);
+ outline_translate(outline, key->advance.x, -key->advance.y);
+ }
+ if (border) {
+ if (scale_x != 1.0)
+ outline_transform(border, &m);
+ outline_translate(border, key->advance.x, -key->advance.y);
}
+ // render glyph
+ int error = outline_to_bitmap2(render_priv, outline, border,
+ &val->bm, &val->bm_o);
+ if (error)
+ info->symbol = 0;
+
+ ass_cache_commit(val);
info->image = val;
+
+ outline_free(outline);
+ free(outline);
+ outline_free(border);
+ free(border);
}
/**
@@ -2277,6 +2266,8 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
free(info->bitmaps);
continue;
}
+ if (!hv)
+ continue;
int bord = be_padding(info->filter.be);
if (!bord && info->n_bm == 1) {
@@ -2358,8 +2349,6 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv,
hv->bm = info->bm;
hv->bm_o = info->bm_o;
hv->bm_s = info->bm_s;
- for (int j = 0; j < info->bitmap_count; ++j)
- ass_cache_inc_ref(info->bitmaps[j].image);
ass_cache_commit(hv);
}
diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c
index 95ffda3..6f872e3 100644
--- a/libass/ass_shaper.c
+++ b/libass/ass_shaper.c
@@ -208,26 +208,28 @@ 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)) {
- int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
- | FT_LOAD_IGNORE_TRANSFORM;
-
- if (FT_Load_Glyph(face, glyph, load_flags)) {
- ass_cache_cancel(val);
- return NULL;
- }
-
- memcpy(&val->metrics, &face->glyph->metrics, sizeof(FT_Glyph_Metrics));
+ if (ass_cache_get(metrics->metrics_cache, &metrics->hash_key, &val))
+ return val->metrics.width < 0 ? NULL : val;
+ if (!val)
+ return NULL;
- // if @font rendering is enabled and the glyph should be rotated,
- // make cached_h_advance pick up the right advance later
- if (metrics->vertical && unicode >= VERTICAL_LOWER_BOUND)
- val->metrics.horiAdvance = val->metrics.vertAdvance;
+ int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
+ | FT_LOAD_IGNORE_TRANSFORM;
- ass_cache_inc_ref(metrics->hash_key.font);
+ if (FT_Load_Glyph(face, glyph, load_flags)) {
+ val->metrics.width = -1;
ass_cache_commit(val);
+ return NULL;
}
+ memcpy(&val->metrics, &face->glyph->metrics, sizeof(FT_Glyph_Metrics));
+
+ // if @font rendering is enabled and the glyph should be rotated,
+ // make cached_h_advance pick up the right advance later
+ if (metrics->vertical && unicode >= VERTICAL_LOWER_BOUND)
+ val->metrics.horiAdvance = val->metrics.vertAdvance;
+
+ ass_cache_commit(val);
return val;
}