summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-08-09 11:23:28 +0100
committerRobin Watts <robin.watts@artifex.com>2016-09-13 17:38:20 +0100
commit6446ad77363517a1adcccf0cb5167610f3ddd117 (patch)
tree78a1c96c56b40f6a5dd1d4d2769f4f02ec448a4c /source
parentbf8e4dea8d41e67ea502efb9bc9fcbf3400a0da5 (diff)
downloadmupdf-6446ad77363517a1adcccf0cb5167610f3ddd117.tar.xz
Bug 696984: Type 3 fonts bbox fixes.
The upshot of debugging this is that: 1) We can't trust the FontBBox. Certainly it appears that no one else trusts it. 2) We can't trust the d1 values in all cases, as it can lead to use rendering glyphs far larger than we'd want to. So we have the compromise used here. 1) We never clip to the FontBBox. 2) If the FontBBox is invalid, then we calculate the bbox from the contents of the data streams. 3) If the FontBBox is valid, and the d1 rectangle given does not fit inside it, then we calculate the bbox from the contents of the data streams. This could theoretically produce problems with glyphs that have much more content than they actually need, and rely on the d1 rect to clip it down to sanity. If the FontBBox is invalid in such fonts, we will go wrong. It's not clear to me that this will actually work in Acrobat/ Foxit/gs etc either, so we defer handling this better until we actually have an example. Tested with bug 694952, and bug 695843 which were the last 2 in this area.
Diffstat (limited to 'source')
-rw-r--r--source/fitz/font.c95
-rw-r--r--source/fitz/geometry.c14
2 files changed, 61 insertions, 48 deletions
diff --git a/source/fitz/font.c b/source/fitz/font.c
index 560f96ec..beab4c87 100644
--- a/source/fitz/font.c
+++ b/source/fitz/font.c
@@ -887,7 +887,7 @@ fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, const fz_mat
}
static fz_rect *
-fz_bound_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_rect *bounds)
+fz_bound_ft_glyph(fz_context *ctx, fz_font *font, int gid)
{
FT_Face face = font->ft_face;
FT_Error fterr;
@@ -895,6 +895,7 @@ fz_bound_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_rect *bounds)
FT_Matrix m;
FT_Vector v;
int ft_flags;
+ fz_rect *bounds = &font->bbox_table[gid];
// TODO: refactor loading into fz_load_ft_glyph
// TODO: cache results
@@ -1137,11 +1138,41 @@ fz_new_type3_font(fz_context *ctx, const char *name, const fz_matrix *matrix)
return font;
}
+static void
+fz_bound_t3_glyph(fz_context *ctx, fz_font *font, int gid)
+{
+ fz_display_list *list;
+ fz_device *dev;
+
+ list = font->t3lists[gid];
+ if (!list)
+ {
+ font->bbox_table[gid] = fz_empty_rect;
+ return;
+ }
+
+ dev = fz_new_bbox_device(ctx, &font->bbox_table[gid]);
+ fz_try(ctx)
+ {
+ fz_run_display_list(ctx, list, dev, &font->t3matrix, &fz_infinite_rect, NULL);
+ fz_close_device(ctx, dev);
+ }
+ fz_always(ctx)
+ {
+ fz_drop_device(ctx, dev);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
void
fz_prepare_t3_glyph(fz_context *ctx, fz_font *font, int gid, int nested_depth)
{
fz_buffer *contents;
fz_device *dev;
+ fz_rect d1_rect;
contents = font->t3procs[gid];
if (!contents)
@@ -1162,58 +1193,26 @@ fz_prepare_t3_glyph(fz_context *ctx, fz_font *font, int gid, int nested_depth)
FZ_DEVFLAG_MITERLIMIT_UNDEFINED |
FZ_DEVFLAG_LINEWIDTH_UNDEFINED;
font->t3run(ctx, font->t3doc, font->t3resources, contents, dev, &fz_identity, NULL, 0);
+ fz_close_device(ctx, dev);
font->t3flags[gid] = dev->flags;
- if (dev->flags & FZ_DEVFLAG_BBOX_DEFINED)
+ d1_rect = dev->d1_rect;
+ fz_drop_device(ctx, dev);
+ dev = NULL;
+ if (font->t3flags[gid] & FZ_DEVFLAG_BBOX_DEFINED)
{
assert(font->bbox_table != NULL);
assert(font->glyph_count > gid);
- font->bbox_table[gid] = dev->d1_rect;
+ font->bbox_table[gid] = d1_rect;
fz_transform_rect(&font->bbox_table[gid], &font->t3matrix);
- }
- fz_close_device(ctx, dev);
- fz_drop_device(ctx, dev);
-}
-
-static fz_rect *
-fz_bound_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_rect *bounds)
-{
- fz_display_list *list;
- fz_device *dev;
- fz_rect big;
- float m;
-
- list = font->t3lists[gid];
- if (!list)
- {
- *bounds = fz_empty_rect;
- return bounds;
- }
- dev = fz_new_bbox_device(ctx, bounds);
- fz_try(ctx)
- {
- fz_run_display_list(ctx, list, dev, &font->t3matrix, &fz_infinite_rect, NULL);
- fz_close_device(ctx, dev);
- }
- fz_always(ctx)
- {
- fz_drop_device(ctx, dev);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-
- if (!font->invalid_bbox)
- {
- /* clip the bbox size to a reasonable maximum for degenerate glyphs */
- big = font->bbox;
- 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);
+ if (font->invalid_bbox || !fz_contains_rect(&font->bbox, &d1_rect))
+ {
+ /* Either the font bbox is invalid, or the d1_rect returned is
+ * incompatible with it. Either way, don't trust the d1 rect
+ * and calculate it from the contents. */
+ fz_bound_t3_glyph(ctx, font, gid);
+ }
}
-
- return bounds;
}
void
@@ -1379,9 +1378,9 @@ fz_bound_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, fz
if (fz_is_infinite_rect(&font->bbox_table[gid]))
{
if (font->ft_face)
- fz_bound_ft_glyph(ctx, font, gid, &font->bbox_table[gid]);
+ fz_bound_ft_glyph(ctx, font, gid);
else if (font->t3lists)
- fz_bound_t3_glyph(ctx, font, gid, &font->bbox_table[gid]);
+ fz_bound_t3_glyph(ctx, font, gid);
else
font->bbox_table[gid] = fz_empty_rect;
}
diff --git a/source/fitz/geometry.c b/source/fitz/geometry.c
index f7a92816..1d3d0f66 100644
--- a/source/fitz/geometry.c
+++ b/source/fitz/geometry.c
@@ -538,3 +538,17 @@ fz_rect *fz_include_point_in_rect(fz_rect *r, const fz_point *p)
return r;
}
+
+int fz_contains_rect(const fz_rect *a, const fz_rect *b)
+{
+ if (a == NULL || b == NULL)
+ return 0;
+ if (fz_is_empty_rect(b))
+ return 1;
+ if (fz_is_empty_rect(a))
+ return 0;
+ return ((a->x0 > b->x0) ||
+ (a->y0 > b->y0) ||
+ (a->x1 < b->x1) ||
+ (a->y1 < b->y1));
+}