summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2011-12-07 17:58:00 +0000
committerRobin Watts <robin.watts@artifex.com>2011-12-07 18:09:23 +0000
commit7a6b60d0ec1abac316917690878011c3228a6fb7 (patch)
tree1d1c9b662ba1b738d08e557558fc9875cbbc1a31
parent841533481464ea4cad3dcb8c6dd636c5d455e6eb (diff)
downloadmupdf-7a6b60d0ec1abac316917690878011c3228a6fb7.tar.xz
Fix tile coverage calculations.
The code attempts to spot cases where a pattern tile is so large that only 1 repeat is visible. Due to rounding errors, this test could sometimes fail, and (on badly formed files) we'd attempt to allocate huge pixmaps. The fix is to allow for rounding errors.
-rw-r--r--draw/draw_device.c5
-rw-r--r--pdf/pdf_interpret.c13
2 files changed, 14 insertions, 4 deletions
diff --git a/draw/draw_device.c b/draw/draw_device.c
index 165cb1a9..788d8148 100644
--- a/draw/draw_device.c
+++ b/draw/draw_device.c
@@ -1438,6 +1438,11 @@ fz_draw_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ys
fz_knockout_begin(dev);
bbox = fz_round_rect(fz_transform_rect(ctm, view));
+ /* We should never have a bbox that entirely covers our destination.
+ * If we do, then the check for only 1 tile being visible above has
+ * failed. */
+ assert(bbox.x0 > dev->dest->x || bbox.x1 < dev->dest->x + dev->dest->w ||
+ bbox.y0 > dev->dest->y || bbox.y1 < dev->dest->y + dev->dest->h);
dest = fz_new_pixmap_with_rect(model, bbox);
/* FIXME: See note #1 */
fz_clear_pixmap(dest);
diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c
index 55e66e61..f598e9fb 100644
--- a/pdf/pdf_interpret.c
+++ b/pdf/pdf_interpret.c
@@ -1151,10 +1151,15 @@ pdf_show_pattern(pdf_csi *csi, pdf_pattern *pat, fz_rect area, int what)
/* patterns are painted using the ctm in effect at the beginning of the content stream */
/* get bbox of shape in pattern space for stamping */
area = fz_transform_rect(invptm, area);
- x0 = floorf(area.x0 / pat->xstep);
- y0 = floorf(area.y0 / pat->ystep);
- x1 = ceilf(area.x1 / pat->xstep);
- y1 = ceilf(area.y1 / pat->ystep);
+
+ /* When calculating the number of tiles required, we adjust by a small
+ * amount to allow for rounding errors. By choosing this amount to be
+ * smaller than 1/256, we guarantee we won't cause problems that will
+ * be visible even under our most extreme antialiasing. */
+ x0 = floorf(area.x0 / pat->xstep + 0.001);
+ y0 = floorf(area.y0 / pat->ystep + 0.001);
+ x1 = ceilf(area.x1 / pat->xstep - 0.001);
+ y1 = ceilf(area.y1 / pat->ystep - 0.001);
oldtopctm = csi->top_ctm;
oldtop = csi->gtop;