diff options
author | Robin Watts <robin.watts@artifex.com> | 2015-02-20 14:56:40 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2015-02-24 10:09:51 +0000 |
commit | 61de5ad4c1afb03cbec8a239162a7e657d57fc2d (patch) | |
tree | 449a7f6ddba624b1682cd0c7f5f067b03290cf12 /source | |
parent | 8a8b535da2461ba858a32c4f346f08abca875daa (diff) | |
download | mupdf-61de5ad4c1afb03cbec8a239162a7e657d57fc2d.tar.xz |
Bug 695843: Tweak bboxes of type3 fonts; honour the d1 values.
The example file for this bug has an invalid font bbox. The current
code uses this bbox (or some multiple of it) to clip the glyphs
size.
In the new code, when we convert the glyphs to display lists we
watch for the bbox given in any d1 operator used. If we find one,
we gather the rectangle specified and store it as the glyph rectangle
in the fz_font.
If we then attempt to bound a glyph that used d1, it happens instantly
without needing to run the list. This seems to match acrobats behaviour.
Tests indicate that Acrobat never clips d0 glyphs, so our behaviour
is still different here, but I am not changing this at the moment.
Also, I note that t3flags should be a un unsigned short but are currently
just a char. Fix that too.
Also fix some missing code in fz_new_font that would cause leaks if mallocs
failed.
Diffstat (limited to 'source')
-rw-r--r-- | source/fitz/font.c | 37 | ||||
-rw-r--r-- | source/pdf/pdf-interpret-imp.h | 2 | ||||
-rw-r--r-- | source/pdf/pdf-op-run.c | 7 |
3 files changed, 34 insertions, 12 deletions
diff --git a/source/fitz/font.c b/source/fitz/font.c index 5f2f85e1..3d4a06e5 100644 --- a/source/fitz/font.c +++ b/source/fitz/font.c @@ -1007,10 +1007,18 @@ fz_new_type3_font(fz_context *ctx, const char *name, const fz_matrix *matrix) int i; font = fz_new_font(ctx, name, 1, 256); - font->t3procs = fz_malloc_array(ctx, 256, sizeof(fz_buffer*)); - font->t3lists = fz_malloc_array(ctx, 256, sizeof(fz_display_list*)); - font->t3widths = fz_malloc_array(ctx, 256, sizeof(float)); - font->t3flags = fz_malloc_array(ctx, 256, sizeof(char)); + fz_try(ctx) + { + font->t3procs = fz_malloc_array(ctx, 256, sizeof(fz_buffer*)); + font->t3lists = fz_malloc_array(ctx, 256, sizeof(fz_display_list*)); + font->t3widths = fz_malloc_array(ctx, 256, sizeof(float)); + font->t3flags = fz_malloc_array(ctx, 256, sizeof(unsigned short)); + } + fz_catch(ctx) + { + fz_drop_font(ctx, font); + fz_rethrow(ctx); + } font->t3matrix = *matrix; for (i = 0; i < 256; i++) @@ -1050,29 +1058,35 @@ fz_prepare_t3_glyph(fz_context *ctx, fz_font *font, int gid, int nested_depth) FZ_DEVFLAG_LINEWIDTH_UNDEFINED; font->t3run(ctx, font->t3doc, font->t3resources, contents, dev, &fz_identity, NULL, 0); font->t3flags[gid] = dev->flags; + if (dev->flags & FZ_DEVFLAG_BBOX_DEFINED) + { + assert(font->bbox_table != NULL); + assert(font->bbox_count > gid); + font->bbox_table[gid] = dev->d1_rect; + fz_transform_rect(&font->bbox_table[gid], &font->t3matrix); + } fz_drop_device(ctx, dev); } static fz_rect * -fz_bound_t3_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, fz_rect *bounds) +fz_bound_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_rect *bounds) { fz_display_list *list; - fz_matrix ctm; fz_device *dev; fz_rect big; + float m; list = font->t3lists[gid]; if (!list) { *bounds = fz_empty_rect; - return fz_transform_rect(bounds, trm); + return bounds; } - fz_concat(&ctm, &font->t3matrix, trm); dev = fz_new_bbox_device(ctx, bounds); fz_try(ctx) { - fz_run_display_list(ctx, list, dev, &ctm, &fz_infinite_rect, NULL); + fz_run_display_list(ctx, list, dev, &font->t3matrix, &fz_infinite_rect, NULL); } fz_always(ctx) { @@ -1085,7 +1099,8 @@ fz_bound_t3_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, /* clip the bbox size to a reasonable maximum for degenerate glyphs */ big = font->bbox; - fz_expand_rect(&big, fz_max(fz_matrix_expansion(&ctm) * 2, fz_max(big.x1 - big.x0, big.y1 - big.y0))); + m = fz_max(fz_abs(big.x1 - big.x0), fz_abs(big.y1 - big.y0)); + fz_expand_rect(&big, fz_max(fz_matrix_expansion(&font->t3matrix) * 2, m)); fz_intersect_rect(bounds, &big); return bounds; @@ -1256,7 +1271,7 @@ fz_bound_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, fz if (font->ft_face) fz_bound_ft_glyph(ctx, font, gid, &font->bbox_table[gid]); else if (font->t3lists) - fz_bound_t3_glyph(ctx, font, gid, &fz_identity, &font->bbox_table[gid]); + fz_bound_t3_glyph(ctx, font, gid, &font->bbox_table[gid]); else font->bbox_table[gid] = fz_empty_rect; } diff --git a/source/pdf/pdf-interpret-imp.h b/source/pdf/pdf-interpret-imp.h index 817a7d2c..9c72bfe2 100644 --- a/source/pdf/pdf-interpret-imp.h +++ b/source/pdf/pdf-interpret-imp.h @@ -129,6 +129,8 @@ struct pdf_csi_s int xbalance; int in_text; + fz_rect d1_rect; + /* cookie support */ fz_cookie *cookie; }; diff --git a/source/pdf/pdf-op-run.c b/source/pdf/pdf-op-run.c index c09abb45..204d3c23 100644 --- a/source/pdf/pdf-op-run.c +++ b/source/pdf/pdf-op-run.c @@ -2367,7 +2367,7 @@ static void pdf_run_d1(pdf_csi *csi, void *state) if (pr->nested_depth > 1) return; - pr->dev->flags |= FZ_DEVFLAG_MASK; + pr->dev->flags |= FZ_DEVFLAG_MASK | FZ_DEVFLAG_BBOX_DEFINED; pr->dev->flags &= ~(FZ_DEVFLAG_FILLCOLOR_UNDEFINED | FZ_DEVFLAG_STROKECOLOR_UNDEFINED | FZ_DEVFLAG_STARTCAP_UNDEFINED | @@ -2376,6 +2376,11 @@ static void pdf_run_d1(pdf_csi *csi, void *state) FZ_DEVFLAG_LINEJOIN_UNDEFINED | FZ_DEVFLAG_MITERLIMIT_UNDEFINED | FZ_DEVFLAG_LINEWIDTH_UNDEFINED); + + pr->dev->d1_rect.x0 = fz_min(csi->stack[2], csi->stack[4]); + pr->dev->d1_rect.y0 = fz_min(csi->stack[3], csi->stack[5]); + pr->dev->d1_rect.x1 = fz_max(csi->stack[2], csi->stack[4]); + pr->dev->d1_rect.y1 = fz_max(csi->stack[3], csi->stack[5]); } static void pdf_run_f(pdf_csi *csi, void *state) |