summaryrefslogtreecommitdiff
path: root/fitz
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-02-13 17:53:21 +0000
committerRobin Watts <robin.watts@artifex.com>2012-02-13 22:05:12 +0000
commitd4c73c65888e422f8b5d5c102ce80f4e82622bfb (patch)
treef9879093e06204e8e85842996dab3a91bd3df0e9 /fitz
parente9c534aee18fa86a61decb9f7c17b3d28ead94dc (diff)
downloadmupdf-d4c73c65888e422f8b5d5c102ce80f4e82622bfb.tar.xz
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.
Diffstat (limited to 'fitz')
-rw-r--r--fitz/base_context.c11
-rw-r--r--fitz/dev_text.c2
-rw-r--r--fitz/fitz.h11
-rw-r--r--fitz/res_font.c123
-rw-r--r--fitz/res_store.c2
5 files changed, 105 insertions, 44 deletions
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)