From d4c73c65888e422f8b5d5c102ce80f4e82622bfb Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 13 Feb 2012 17:53:21 +0000 Subject: Add locking around freetype calls. We only open one instance of freetype per document. We therefore have to ensure that only 1 call to it takes place at a time. We introduce a lock for this purpose (FZ_LOCK_FREETYPE), and arrange to take/release it as required. We also update the font context so it is properly shared. --- fitz/base_context.c | 11 ++--- fitz/dev_text.c | 2 + fitz/fitz.h | 11 +++-- fitz/res_font.c | 123 +++++++++++++++++++++++++++++++++++++--------------- fitz/res_store.c | 2 +- 5 files changed, 105 insertions(+), 44 deletions(-) (limited to 'fitz') diff --git a/fitz/base_context.c b/fitz/base_context.c index 47d4ba79..8df74531 100644 --- a/fitz/base_context.c +++ b/fitz/base_context.c @@ -15,10 +15,10 @@ fz_free_context(fz_context *ctx) return; /* Other finalisation calls go here (in reverse order) */ - fz_free_glyph_cache_context(ctx); - fz_free_store_context(ctx); + fz_drop_glyph_cache_context(ctx); + fz_drop_store_context(ctx); fz_free_aa_context(ctx); - fz_free_font_context(ctx); + fz_drop_font_context(ctx); if (ctx->warn) { @@ -68,7 +68,6 @@ new_context_phase1(fz_alloc_context *alloc, fz_locks_context *locks) /* New initialisation calls for context entries go here */ fz_try(ctx) { - fz_new_font_context(ctx); fz_new_aa_context(ctx); } fz_catch(ctx) @@ -102,6 +101,7 @@ fz_new_context(fz_alloc_context *alloc, fz_locks_context *locks, unsigned int ma { fz_new_store_context(ctx, max_store); fz_new_glyph_cache_context(ctx); + fz_new_font_context(ctx); } fz_catch(ctx) { @@ -124,6 +124,7 @@ fz_clone_context(fz_context *ctx) new_ctx = new_context_phase1(ctx->alloc, ctx->locks); new_ctx->store = fz_store_keep(ctx); - new_ctx->glyph_cache = fz_glyph_cache_keep(ctx); + new_ctx->glyph_cache = fz_keep_glyph_cache(ctx); + new_ctx->font = fz_keep_font_context(ctx); return new_ctx; } diff --git a/fitz/dev_text.c b/fitz/dev_text.c index f7b55c5e..d38fab21 100644 --- a/fitz/dev_text.c +++ b/fitz/dev_text.c @@ -238,6 +238,7 @@ fz_text_extract_span(fz_context *ctx, fz_text_span **last, fz_text *text, fz_mat if (text->len == 0) return; + fz_lock(ctx, FZ_LOCK_FREETYPE); if (font->ft_face) { err = FT_Set_Char_Size(font->ft_face, 64, 64, 72, 72); @@ -353,6 +354,7 @@ fz_text_extract_span(fz_context *ctx, fz_text_span **last, fz_text *text, fz_mat fz_add_text_char(ctx, last, font, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); } + fz_unlock(ctx, FZ_LOCK_FREETYPE); } static void diff --git a/fitz/fitz.h b/fitz/fitz.h index b256d90b..3992a75b 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -411,6 +411,7 @@ struct fz_locks_context_s enum { FZ_LOCK_ALLOC = 0, FZ_LOCK_FILE, + FZ_LOCK_FREETYPE, FZ_LOCK_GLYPHCACHE, FZ_LOCK_MAX }; @@ -809,7 +810,7 @@ enum { }; void fz_new_store_context(fz_context *ctx, unsigned int max); -void fz_free_store_context(fz_context *ctx); +void fz_drop_store_context(fz_context *ctx); fz_store *fz_store_keep(fz_context *ctx); void fz_debug_store(fz_context *ctx); @@ -1148,7 +1149,8 @@ struct fz_font_s }; void fz_new_font_context(fz_context *ctx); -void fz_free_font_context(fz_context *ctx); +fz_font_context *fz_keep_font_context(fz_context *ctx); +void fz_drop_font_context(fz_context *ctx); fz_font *fz_new_type3_font(fz_context *ctx, char *name, fz_matrix matrix); @@ -1247,8 +1249,9 @@ void fz_debug_path(fz_context *ctx, fz_path *, int indent); */ void fz_new_glyph_cache_context(fz_context *ctx); -fz_glyph_cache *fz_glyph_cache_keep(fz_context *ctx); -void fz_free_glyph_cache_context(fz_context *ctx); +fz_glyph_cache *fz_keep_glyph_cache(fz_context *ctx); +void fz_drop_glyph_cache_context(fz_context *ctx); +void fz_purge_glyph_cache(fz_context *ctx); fz_pixmap *fz_render_ft_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm); fz_pixmap *fz_render_t3_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm, fz_colorspace *model); diff --git a/fitz/res_font.c b/fitz/res_font.c index 298e637e..7a194da6 100644 --- a/fitz/res_font.c +++ b/fitz/res_font.c @@ -70,8 +70,11 @@ fz_new_font(fz_context *ctx, char *name, int use_glyph_bbox, int glyph_count) fz_font * fz_keep_font(fz_context *ctx, fz_font *font) { - if (font) - font->refs ++; + if (!font) + return NULL; + fz_lock(ctx, FZ_LOCK_ALLOC); + font->refs ++; + fz_unlock(ctx, FZ_LOCK_ALLOC); return font; } @@ -79,36 +82,41 @@ void fz_drop_font(fz_context *ctx, fz_font *font) { int fterr; - int i; + int i, drop; - if (font && --font->refs == 0) - { - if (font->t3procs) - { - if (font->t3resources) - fz_drop_obj(font->t3resources); - for (i = 0; i < 256; i++) - if (font->t3procs[i]) - fz_drop_buffer(ctx, font->t3procs[i]); - fz_free(ctx, font->t3procs); - fz_free(ctx, font->t3widths); - fz_free(ctx, font->t3flags); - } + fz_lock(ctx, FZ_LOCK_ALLOC); + drop = (font && --font->refs == 0); + fz_unlock(ctx, FZ_LOCK_ALLOC); + if (!drop) + return; - if (font->ft_face) - { - fterr = FT_Done_Face((FT_Face)font->ft_face); - if (fterr) - fz_warn(ctx, "freetype finalizing face: %s", ft_error_string(fterr)); - fz_drop_freetype(ctx); - } + if (font->t3procs) + { + if (font->t3resources) + fz_drop_obj(font->t3resources); + for (i = 0; i < 256; i++) + if (font->t3procs[i]) + fz_drop_buffer(ctx, font->t3procs[i]); + fz_free(ctx, font->t3procs); + fz_free(ctx, font->t3widths); + fz_free(ctx, font->t3flags); + } - fz_free(ctx, font->ft_file); - fz_free(ctx, font->ft_data); - fz_free(ctx, font->bbox_table); - fz_free(ctx, font->width_table); - fz_free(ctx, font); + if (font->ft_face) + { + fz_lock(ctx, FZ_LOCK_FREETYPE); + fterr = FT_Done_Face((FT_Face)font->ft_face); + fz_unlock(ctx, FZ_LOCK_FREETYPE); + if (fterr) + fz_warn(ctx, "freetype finalizing face: %s", ft_error_string(fterr)); + fz_drop_freetype(ctx); } + + fz_free(ctx, font->ft_file); + fz_free(ctx, font->ft_data); + fz_free(ctx, font->bbox_table); + fz_free(ctx, font->width_table); + fz_free(ctx, font); } void @@ -125,6 +133,7 @@ fz_set_font_bbox(fz_context *ctx, fz_font *font, float xmin, float ymin, float x */ struct fz_font_context_s { + int ctx_refs; FT_Library ftlib; int ftlib_refs; }; @@ -143,17 +152,32 @@ struct ft_error void fz_new_font_context(fz_context *ctx) { ctx->font = fz_malloc_struct(ctx, fz_font_context); + ctx->font->ctx_refs = 1; ctx->font->ftlib = NULL; ctx->font->ftlib_refs = 0; } -void fz_free_font_context(fz_context *ctx) +fz_font_context * +fz_keep_font_context(fz_context *ctx) { - if (!ctx->font) + if (!ctx || !ctx->font) + return NULL; + fz_lock(ctx, FZ_LOCK_ALLOC); + ctx->font->ctx_refs++; + fz_unlock(ctx, FZ_LOCK_ALLOC); + return ctx->font; +} + +void fz_drop_font_context(fz_context *ctx) +{ + int drop; + if (!ctx || !ctx->font) return; - /* assert(!ctx->ftlib); */ - /* assert(ctx->ftlib_refs == 0); */ - fz_free(ctx, ctx->font); + fz_lock(ctx, FZ_LOCK_ALLOC); + drop = --ctx->font->ctx_refs; + fz_unlock(ctx, FZ_LOCK_ALLOC); + if (drop == 0) + fz_free(ctx, ctx->font); } static const struct ft_error ft_errors[] = @@ -179,15 +203,21 @@ fz_keep_freetype(fz_context *ctx) int maj, min, pat; fz_font_context *fct = ctx->font; + fz_lock(ctx, FZ_LOCK_FREETYPE); if (fct->ftlib) { fct->ftlib_refs++; + fz_unlock(ctx, FZ_LOCK_FREETYPE); return; } fterr = FT_Init_FreeType(&fct->ftlib); if (fterr) - fz_throw(ctx, "cannot init freetype: %s", ft_error_string(fterr)); + { + char *mess = ft_error_string(fterr); + fz_unlock(ctx, FZ_LOCK_FREETYPE); + fz_throw(ctx, "cannot init freetype: %s", mess); + } FT_Library_Version(fct->ftlib, &maj, &min, &pat); if (maj == 2 && min == 1 && pat < 7) @@ -195,10 +225,12 @@ fz_keep_freetype(fz_context *ctx) fterr = FT_Done_FreeType(fct->ftlib); if (fterr) fz_warn(ctx, "freetype finalizing: %s", ft_error_string(fterr)); + fz_unlock(ctx, FZ_LOCK_FREETYPE); fz_throw(ctx, "freetype version too old: %d.%d.%d", maj, min, pat); } fct->ftlib_refs++; + fz_unlock(ctx, FZ_LOCK_FREETYPE); } static void @@ -207,6 +239,7 @@ fz_drop_freetype(fz_context *ctx) int fterr; fz_font_context *fct = ctx->font; + fz_lock(ctx, FZ_LOCK_FREETYPE); if (--fct->ftlib_refs == 0) { fterr = FT_Done_FreeType(fct->ftlib); @@ -214,6 +247,7 @@ fz_drop_freetype(fz_context *ctx) fz_warn(ctx, "freetype finalizing: %s", ft_error_string(fterr)); fct->ftlib = NULL; } + fz_unlock(ctx, FZ_LOCK_FREETYPE); } fz_font * @@ -225,7 +259,9 @@ fz_new_font_from_file(fz_context *ctx, char *path, int index, int use_glyph_bbox fz_keep_freetype(ctx); + fz_lock(ctx, FZ_LOCK_FREETYPE); fterr = FT_New_Face(ctx->font->ftlib, path, index, &face); + fz_unlock(ctx, FZ_LOCK_FREETYPE); if (fterr) { fz_drop_freetype(ctx); @@ -251,7 +287,9 @@ fz_new_font_from_memory(fz_context *ctx, unsigned char *data, int len, int index fz_keep_freetype(ctx); + fz_lock(ctx, FZ_LOCK_FREETYPE); fterr = FT_New_Memory_Face(ctx->font->ftlib, data, len, index, &face); + fz_unlock(ctx, FZ_LOCK_FREETYPE); if (fterr) { fz_drop_freetype(ctx); @@ -279,6 +317,7 @@ fz_adjust_ft_glyph_width(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) int realw; float scale; + fz_lock(ctx, FZ_LOCK_FREETYPE); /* TODO: use FT_Get_Advance */ fterr = FT_Set_Char_Size(font->ft_face, 1000, 1000, 72, 72); if (fterr) @@ -290,6 +329,7 @@ fz_adjust_ft_glyph_width(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) fz_warn(ctx, "freetype failed to load glyph: %s", ft_error_string(fterr)); realw = ((FT_Face)font->ft_face)->glyph->metrics.horiAdvance; + fz_unlock(ctx, FZ_LOCK_FREETYPE); subw = font->width_table[gid]; if (realw) scale = (float) subw / realw; @@ -374,6 +414,7 @@ fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) v.x = trm.e * 64; v.y = trm.f * 64; + fz_lock(ctx, FZ_LOCK_FREETYPE); fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ if (fterr) fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr)); @@ -417,6 +458,7 @@ fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) if (fterr) { fz_warn(ctx, "freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); + fz_unlock(ctx, FZ_LOCK_FREETYPE); return NULL; } } @@ -432,8 +474,10 @@ fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) if (fterr) { fz_warn(ctx, "freetype render glyph (gid %d): %s", gid, ft_error_string(fterr)); + fz_unlock(ctx, FZ_LOCK_FREETYPE); return NULL; } + fz_unlock(ctx, FZ_LOCK_FREETYPE); return fz_copy_ft_bitmap(ctx, face->glyph->bitmap_left, face->glyph->bitmap_top, &face->glyph->bitmap); } @@ -465,10 +509,12 @@ fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix tr v.x = trm.e * 64; v.y = trm.f * 64; + fz_lock(ctx, FZ_LOCK_FREETYPE); fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ if (fterr) { fz_warn(ctx, "FT_Set_Char_Size: %s", ft_error_string(fterr)); + fz_unlock(ctx, FZ_LOCK_FREETYPE); return NULL; } @@ -478,6 +524,7 @@ fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix tr if (fterr) { fz_warn(ctx, "FT_Load_Glyph(gid %d): %s", gid, ft_error_string(fterr)); + fz_unlock(ctx, FZ_LOCK_FREETYPE); return NULL; } @@ -485,6 +532,7 @@ fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix tr if (fterr) { fz_warn(ctx, "FT_Stroker_New: %s", ft_error_string(fterr)); + fz_unlock(ctx, FZ_LOCK_FREETYPE); return NULL; } @@ -509,6 +557,7 @@ fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix tr { fz_warn(ctx, "FT_Get_Glyph: %s", ft_error_string(fterr)); FT_Stroker_Done(stroker); + fz_unlock(ctx, FZ_LOCK_FREETYPE); return NULL; } @@ -518,6 +567,7 @@ fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix tr fz_warn(ctx, "FT_Glyph_Stroke: %s", ft_error_string(fterr)); FT_Done_Glyph(glyph); FT_Stroker_Done(stroker); + fz_unlock(ctx, FZ_LOCK_FREETYPE); return NULL; } @@ -528,12 +578,14 @@ fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix tr { fz_warn(ctx, "FT_Glyph_To_Bitmap: %s", ft_error_string(fterr)); FT_Done_Glyph(glyph); + fz_unlock(ctx, FZ_LOCK_FREETYPE); return NULL; } bitmap = (FT_BitmapGlyph)glyph; pixmap = fz_copy_ft_bitmap(ctx, bitmap->left, bitmap->top, &bitmap->bitmap); FT_Done_Glyph(glyph); + fz_unlock(ctx, FZ_LOCK_FREETYPE); return pixmap; } @@ -563,6 +615,7 @@ fz_bound_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) v.x = trm.e * 64; v.y = trm.f * 64; + fz_lock(ctx, FZ_LOCK_FREETYPE); fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ if (fterr) fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr)); @@ -572,6 +625,7 @@ fz_bound_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) if (fterr) { fz_warn(ctx, "freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); + fz_unlock(ctx, FZ_LOCK_FREETYPE); bounds.x0 = bounds.x1 = trm.e; bounds.y0 = bounds.y1 = trm.f; return bounds; @@ -585,6 +639,7 @@ fz_bound_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) } FT_Outline_Get_CBox(&face->glyph->outline, &cbox); + fz_unlock(ctx, FZ_LOCK_FREETYPE); bounds.x0 = cbox.xMin / 64.0f; bounds.y0 = cbox.yMin / 64.0f; bounds.x1 = cbox.xMax / 64.0f; diff --git a/fitz/res_store.c b/fitz/res_store.c index 379c1dc5..2af5ad34 100644 --- a/fitz/res_store.c +++ b/fitz/res_store.c @@ -435,7 +435,7 @@ fz_store_keep(fz_context *ctx) } void -fz_free_store_context(fz_context *ctx) +fz_drop_store_context(fz_context *ctx) { int refs; if (ctx == NULL || ctx->store == NULL) -- cgit v1.2.3