summaryrefslogtreecommitdiff
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
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.
-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