summaryrefslogtreecommitdiff
path: root/draw
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-01-02 18:25:10 +0000
committerRobin Watts <robin.watts@artifex.com>2012-01-02 18:25:10 +0000
commit634fa34f946fb3d48736917102a1e5be583a3fc8 (patch)
treeda00d37e1a8da4312ec198fc0156b90bd951ee07 /draw
parentb7ed90ac050ea30dcab70fe3b49d31398b49699f (diff)
downloadmupdf-634fa34f946fb3d48736917102a1e5be583a3fc8.tar.xz
Fix bug 692593 - solve crash due to inappropriately sized shape plane.
When starting to tile, create a shape plane if one exists. When finishing tiling, plot the shape plane back too. This solves the SEGVs. Something isn't quite right with the blending colours on part of this file though.
Diffstat (limited to 'draw')
-rw-r--r--draw/draw_device.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/draw/draw_device.c b/draw/draw_device.c
index 2634c4f8..5583c30e 100644
--- a/draw/draw_device.c
+++ b/draw/draw_device.c
@@ -1461,8 +1461,10 @@ fz_draw_begin_tile(fz_device *devp, fz_rect area, fz_rect view, float xstep, flo
{
fz_draw_device *dev = devp->user;
fz_colorspace *model = dev->dest->colorspace;
- fz_pixmap *dest;
+ fz_pixmap *dest = NULL;
+ fz_pixmap *shape = dev->shape;
fz_bbox bbox;
+ fz_context *ctx = dev->ctx;
/* area, view, xstep, ystep are in pattern space */
/* ctm maps from pattern space to device space */
@@ -1482,7 +1484,20 @@ fz_draw_begin_tile(fz_device *devp, fz_rect area, fz_rect view, float xstep, flo
dest = fz_new_pixmap_with_rect(dev->ctx, model, bbox);
/* FIXME: See note #1 */
fz_clear_pixmap(dest);
-
+ if (shape)
+ {
+ fz_var(shape);
+ fz_try(ctx)
+ {
+ shape = fz_new_pixmap_with_rect(dev->ctx, NULL, bbox);
+ fz_clear_pixmap(shape);
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_pixmap(ctx, dest);
+ fz_rethrow(ctx);
+ }
+ }
dev->stack[dev->top].scissor = dev->scissor;
dev->stack[dev->top].dest = dev->dest;
dev->stack[dev->top].shape = dev->shape;
@@ -1499,6 +1514,7 @@ fz_draw_begin_tile(fz_device *devp, fz_rect area, fz_rect view, float xstep, flo
dev->scissor = bbox;
dev->dest = dest;
+ dev->shape = shape;
}
static void
@@ -1506,26 +1522,24 @@ fz_draw_end_tile(fz_device *devp)
{
fz_draw_device *dev = devp->user;
fz_pixmap *tile = dev->dest;
+ fz_pixmap *tileshape = dev->shape;
float xstep, ystep;
- fz_matrix ctm, ttm;
+ fz_matrix ctm, ttm, shapectm;
fz_rect area;
int x0, y0, x1, y1, x, y;
if (dev->top > 0)
{
dev->top--;
-#ifdef DUMP_GROUP_BLENDS
- dump_spaces(dev->top, "Tile end\n");
-#endif
xstep = dev->stack[dev->top].xstep;
ystep = dev->stack[dev->top].ystep;
area = dev->stack[dev->top].area;
ctm = dev->stack[dev->top].ctm;
dev->scissor = dev->stack[dev->top].scissor;
dev->dest = dev->stack[dev->top].dest;
+ dev->shape = dev->stack[dev->top].shape;
dev->blendmode = dev->stack[dev->top].blendmode;
-
x0 = floorf(area.x0 / xstep);
y0 = floorf(area.y0 / ystep);
x1 = ceilf(area.x1 / xstep);
@@ -1533,6 +1547,22 @@ fz_draw_end_tile(fz_device *devp)
ctm.e = tile->x;
ctm.f = tile->y;
+ if (tileshape)
+ {
+ shapectm = ctm;
+ shapectm.e = tileshape->x;
+ shapectm.f = tileshape->y;
+ }
+
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(dev->ctx, tile, "Tiling ");
+ if (tileshape)
+ fz_dump_blend(dev->ctx, tileshape, "/");
+ fz_dump_blend(dev->ctx, dev->dest, " onto ");
+ if (dev->shape)
+ fz_dump_blend(dev->ctx, dev->shape, "/");
+#endif
for (y = y0; y < y1; y++)
{
@@ -1542,10 +1572,24 @@ fz_draw_end_tile(fz_device *devp)
tile->x = ttm.e;
tile->y = ttm.f;
fz_paint_pixmap_with_rect(dev->dest, tile, 255, dev->scissor);
+ if (tileshape)
+ {
+ ttm = fz_concat(fz_translate(x * xstep, y * ystep), shapectm);
+ tileshape->x = ttm.e;
+ tileshape->y = ttm.f;
+ fz_paint_pixmap_with_rect(dev->shape, tileshape, 255, dev->scissor);
+ }
}
}
fz_drop_pixmap(dev->ctx, tile);
+ fz_drop_pixmap(dev->ctx, tileshape);
+#ifdef DUMP_GROUP_BLENDS
+ fz_dump_blend(dev->ctx, dev->dest, " to get ");
+ if (dev->shape)
+ fz_dump_blend(dev->ctx, dev->shape, "/");
+ printf("\n");
+#endif
}
if (dev->blendmode & FZ_BLEND_KNOCKOUT)
@@ -1557,7 +1601,7 @@ fz_draw_free_user(fz_device *devp)
{
fz_draw_device *dev = devp->user;
fz_context *ctx = dev->ctx;
- /* TODO: pop and free the stacks */
+ /* pop and free the stacks */
if (dev->top > 0)
{
fz_warn(ctx, "items left on stack in draw device: %d", dev->top);