diff options
Diffstat (limited to 'draw/draw_glyph.c')
-rw-r--r-- | draw/draw_glyph.c | 87 |
1 files changed, 66 insertions, 21 deletions
diff --git a/draw/draw_glyph.c b/draw/draw_glyph.c index 49f04fe8..00eaf460 100644 --- a/draw/draw_glyph.c +++ b/draw/draw_glyph.c @@ -8,6 +8,7 @@ typedef struct fz_glyph_key_s fz_glyph_key; struct fz_glyph_cache_s { + int refs; fz_hash_table *hash; int total; }; @@ -37,10 +38,12 @@ fz_new_glyph_cache_context(fz_context *ctx) fz_rethrow(ctx); } cache->total = 0; + cache->refs = 1; ctx->glyph_cache = cache; } +/* The glyph cache lock is always held when this function is called. */ static void fz_evict_glyph_cache(fz_context *ctx) { @@ -70,10 +73,25 @@ fz_free_glyph_cache_context(fz_context *ctx) if (!ctx->glyph_cache) return; - fz_evict_glyph_cache(ctx); - fz_free_hash(ctx, ctx->glyph_cache->hash); - fz_free(ctx, ctx->glyph_cache); - ctx->glyph_cache = NULL; + fz_lock(ctx, FZ_LOCK_GLYPHCACHE); + ctx->glyph_cache->refs--; + if (ctx->glyph_cache->refs == 0) + { + fz_evict_glyph_cache(ctx); + fz_free_hash(ctx, ctx->glyph_cache->hash); + fz_free(ctx, ctx->glyph_cache); + ctx->glyph_cache = NULL; + } + fz_unlock(ctx, FZ_LOCK_GLYPHCACHE); +} + +fz_glyph_cache * +fz_glyph_cache_keep(fz_context *ctx) +{ + fz_lock(ctx, FZ_LOCK_GLYPHCACHE); + ctx->glyph_cache->refs++; + fz_unlock(ctx, FZ_LOCK_GLYPHCACHE); + return ctx->glyph_cache; } fz_pixmap * @@ -92,8 +110,6 @@ fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_color fz_pixmap *val; float size = fz_matrix_expansion(ctm); - if (!ctx->glyph_cache) - fz_new_glyph_cache_context(ctx); cache = ctx->glyph_cache; if (size > MAX_FONT_SIZE) @@ -113,25 +129,49 @@ fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_color key.e = (ctm.e - floorf(ctm.e)) * 256; key.f = (ctm.f - floorf(ctm.f)) * 256; + fz_lock(ctx, FZ_LOCK_GLYPHCACHE); val = fz_hash_find(ctx, cache->hash, &key); if (val) - return fz_keep_pixmap(ctx, val); + { + fz_keep_pixmap(ctx, val); + fz_unlock(ctx, FZ_LOCK_GLYPHCACHE); + return val; + } ctm.e = floorf(ctm.e) + key.e / 256.0f; ctm.f = floorf(ctm.f) + key.f / 256.0f; - if (font->ft_face) - { - val = fz_render_ft_glyph(ctx, font, gid, ctm); - } - else if (font->t3procs) + fz_try(ctx) { - val = fz_render_t3_glyph(ctx, font, gid, ctm, model); + if (font->ft_face) + { + val = fz_render_ft_glyph(ctx, font, gid, ctm); + } + else if (font->t3procs) + { + /* We drop the glyphcache here, and execute the t3 + * glyph code. The danger here is that some other + * thread will come along, and want the same glyph + * too. If it does, we may both end up rendering + * pixmaps. We cope with this later on, by ensuring + * that only one gets inserted into the cache. If + * we insert ours to find one already there, we + * abandon ours, and use the one there already. + */ + fz_unlock(ctx, FZ_LOCK_GLYPHCACHE); + val = fz_render_t3_glyph(ctx, font, gid, ctm, model); + fz_lock(ctx, FZ_LOCK_GLYPHCACHE); + } + else + { + fz_warn(ctx, "assert: uninitialized font structure"); + val = NULL; + } } - else + fz_catch(ctx) { - fz_warn(ctx, "assert: uninitialized font structure"); - return NULL; + fz_unlock(ctx, FZ_LOCK_GLYPHCACHE); + fz_rethrow(ctx); } if (val) @@ -142,8 +182,14 @@ fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_color fz_evict_glyph_cache(ctx); fz_try(ctx) { - fz_hash_insert(ctx, cache->hash, &key, val); - fz_keep_font(ctx, key.font); + fz_pixmap *pix = fz_hash_insert(ctx, cache->hash, &key, val); + if (pix) + { + fz_drop_pixmap(ctx, val); + val = pix; + } + else + fz_keep_font(ctx, key.font); val = fz_keep_pixmap(ctx, val); } fz_catch(ctx) @@ -151,10 +197,9 @@ fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_color fz_warn(ctx, "Failed to encache glyph - continuing"); } cache->total += val->w * val->h; - return val; } - return val; } - return NULL; + fz_unlock(ctx, FZ_LOCK_GLYPHCACHE); + return val; } |