summaryrefslogtreecommitdiff
path: root/source/fitz
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebras@gmail.com>2018-02-02 21:45:49 +0100
committerSebastian Rasmussen <sebras@gmail.com>2018-02-13 18:22:16 +0100
commitf51836b9732c38d945b87fda0770009a77ba680c (patch)
tree11b8acd5efe8fa12eb9f1241a4911923d20b07f1 /source/fitz
parent5b8ce880027d37aa57ad387134303d160b19ee81 (diff)
downloadmupdf-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.
Diffstat (limited to 'source/fitz')
-rw-r--r--source/fitz/draw-device.c106
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