diff options
author | Sebastian Rasmussen <sebras@gmail.com> | 2018-02-02 21:45:49 +0100 |
---|---|---|
committer | Sebastian Rasmussen <sebras@gmail.com> | 2018-02-13 18:22:16 +0100 |
commit | f51836b9732c38d945b87fda0770009a77ba680c (patch) | |
tree | 11b8acd5efe8fa12eb9f1241a4911923d20b07f1 | |
parent | 5b8ce880027d37aa57ad387134303d160b19ee81 (diff) | |
download | mupdf-f51836b9732c38d945b87fda0770009a77ba680c.tar.xz |
Bug 698901: Drop pixmaps/knockout group upon error when ending group.
Previously the call to fz_convert_pixmap() threw causing a destination
pixmap leak. This illustrated a bigger issue with the error handling
so now all types of pixmaps are dropped and care is taken to also end
the knockout group, should there be any.
-rw-r--r-- | source/fitz/draw-device.c | 106 |
1 files changed, 61 insertions, 45 deletions
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c index 0696b3bd..43dbb52d 100644 --- a/source/fitz/draw-device.c +++ b/source/fitz/draw-device.c @@ -2382,6 +2382,7 @@ fz_draw_end_group(fz_context *ctx, fz_device *devp) state = &dev->stack[--dev->top]; STACK_POPPED("group"); + alpha = state[1].alpha; blendmode = state[1].blendmode & FZ_BLEND_MODEMASK; isolated = state[1].blendmode & FZ_BLEND_ISOLATED; @@ -2406,61 +2407,76 @@ fz_draw_end_group(fz_context *ctx, fz_device *devp) if (state[1].blendmode & FZ_BLEND_KNOCKOUT) printf(" (knockout)"); #endif - if (state[0].dest->colorspace != state[1].dest->colorspace) + + fz_try(ctx) { - fz_pixmap *converted = fz_convert_pixmap(ctx, state[1].dest, state[0].dest->colorspace, NULL, dev->default_cs, fz_default_color_params(ctx), 1); - fz_drop_pixmap(ctx, state[1].dest); - state[1].dest = converted; - } + if (state[0].dest->colorspace != state[1].dest->colorspace) + { + fz_pixmap *converted = fz_convert_pixmap(ctx, state[1].dest, state[0].dest->colorspace, NULL, dev->default_cs, fz_default_color_params(ctx), 1); + fz_drop_pixmap(ctx, state[1].dest); + state[1].dest = converted; + } - if ((blendmode == 0) && (state[0].shape == state[1].shape) && (state[0].group_alpha == state[1].group_alpha)) - fz_paint_pixmap(state[0].dest, state[1].dest, alpha * 255); - else - fz_blend_pixmap(ctx, state[0].dest, state[1].dest, alpha * 255, blendmode, isolated, state[1].group_alpha); + if ((blendmode == 0) && (state[0].shape == state[1].shape) && (state[0].group_alpha == state[1].group_alpha)) + fz_paint_pixmap(state[0].dest, state[1].dest, alpha * 255); + else + fz_blend_pixmap(ctx, state[0].dest, state[1].dest, alpha * 255, blendmode, isolated, state[1].group_alpha); - if (state[0].shape != state[1].shape) - { - /* The 'D' on page 7 of Altona_Technical_v20_x4.pdf goes wrong if this - * isn't alpha * 255, as the blend back fails to take account of alpha. */ - if (state[0].shape) + if (state[0].shape != state[1].shape) + { + /* The 'D' on page 7 of Altona_Technical_v20_x4.pdf goes wrong if this + * isn't alpha * 255, as the blend back fails to take account of alpha. */ + if (state[0].shape) + { + if (state[1].shape) + fz_paint_pixmap(state[0].shape, state[1].shape, alpha * 255); + else + fz_paint_pixmap_alpha(state[0].shape, state[1].dest, alpha * 255); + } + } + assert(state[0].group_alpha == NULL || state[0].group_alpha != state[1].group_alpha); + if (state[0].group_alpha && state[0].group_alpha != state[1].group_alpha) { - if (state[1].shape) - fz_paint_pixmap(state[0].shape, state[1].shape, alpha * 255); + /* The 'D' on page 7 of Altona_Technical_v20_x4.pdf uses an isolated group, + * and goes wrong if this is 255 * alpha, as an alpha effectively gets + * applied twice. CATX5233 page 7 uses a non-isolated group, and goes wrong + * if alpha isn't applied here. */ + if (state[1].group_alpha) + fz_paint_pixmap(state[0].group_alpha, state[1].group_alpha, isolated ? 255 : alpha * 255); else - fz_paint_pixmap_alpha(state[0].shape, state[1].dest, alpha * 255); + fz_paint_pixmap_alpha(state[0].group_alpha, state[1].dest, isolated ? 255 : alpha * 255); } - fz_drop_pixmap(ctx, state[1].shape); + + assert(state[0].dest != state[1].dest); + +#ifdef DUMP_GROUP_BLENDS + fz_dump_blend(ctx, " to get ", state[0].dest); + if (state[0].shape) + fz_dump_blend(ctx, "/S=", state[0].shape); + if (state[0].group_alpha) + fz_dump_blend(ctx, "/GA=", state[0].group_alpha); + printf("\n"); +#endif } - assert(state[0].group_alpha == NULL || state[0].group_alpha != state[1].group_alpha); - if (state[0].group_alpha && state[0].group_alpha != state[1].group_alpha) + fz_always(ctx) { - /* The 'D' on page 7 of Altona_Technical_v20_x4.pdf uses an isolated group, - * and goes wrong if this is 255 * alpha, as an alpha effectively gets - * applied twice. CATX5233 page 7 uses a non-isolated group, and goes wrong - * if alpha isn't applied here. */ - if (state[1].group_alpha) - fz_paint_pixmap(state[0].group_alpha, state[1].group_alpha, isolated ? 255 : alpha * 255); - else - fz_paint_pixmap_alpha(state[0].group_alpha, state[1].dest, isolated ? 255 : alpha * 255); + if (state[0].shape != state[1].shape) + fz_drop_pixmap(ctx, state[1].shape); + fz_drop_pixmap(ctx, state[1].group_alpha); + /* The following test should not be required, but just occasionally + * errors can cause the stack to get out of sync, and this might save + * our bacon. */ + if (state[0].dest != state[1].dest) + fz_drop_pixmap(ctx, state[1].dest); + + if (state[0].blendmode & FZ_BLEND_KNOCKOUT) + fz_knockout_end(ctx, dev); + } + fz_catch(ctx) + { + fz_rethrow(ctx); } - fz_drop_pixmap(ctx, state[1].group_alpha); - /* The following test should not be required, but just occasionally - * errors can cause the stack to get out of sync, and this might save - * our bacon. */ - assert(state[0].dest != state[1].dest); - if (state[0].dest != state[1].dest) - fz_drop_pixmap(ctx, state[1].dest); -#ifdef DUMP_GROUP_BLENDS - fz_dump_blend(ctx, " to get ", state[0].dest); - if (state[0].shape) - fz_dump_blend(ctx, "/S=", state[0].shape); - if (state[0].group_alpha) - fz_dump_blend(ctx, "/GA=", state[0].group_alpha); - printf("\n"); -#endif - if (state[0].blendmode & FZ_BLEND_KNOCKOUT) - fz_knockout_end(ctx, dev); } typedef struct |