diff options
author | Robin Watts <robin.watts@artifex.com> | 2012-01-02 18:25:10 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2012-01-02 18:25:10 +0000 |
commit | 634fa34f946fb3d48736917102a1e5be583a3fc8 (patch) | |
tree | da00d37e1a8da4312ec198fc0156b90bd951ee07 /draw | |
parent | b7ed90ac050ea30dcab70fe3b49d31398b49699f (diff) | |
download | mupdf-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.c | 60 |
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); |