summaryrefslogtreecommitdiff
path: root/source/fitz/draw-device.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/fitz/draw-device.c')
-rw-r--r--source/fitz/draw-device.c240
1 files changed, 161 insertions, 79 deletions
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index 5b512c44..516e05bc 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -162,7 +162,7 @@ fz_knockout_begin(fz_context *ctx, fz_draw_device *dev)
fz_pixmap_bbox(ctx, state->dest, &bbox);
fz_intersect_irect(&bbox, &state->scissor);
- dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox);
+ dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox, state->dest->alpha || isolated);
if (isolated)
{
@@ -193,7 +193,7 @@ fz_knockout_begin(fz_context *ctx, fz_draw_device *dev)
}
else
{
- shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
#ifdef DUMP_GROUP_BLENDS
@@ -276,13 +276,10 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
unsigned char colorbv[FZ_MAX_COLORS + 1];
float colorfv[FZ_MAX_COLORS];
fz_irect bbox;
- int i;
+ int i, n;
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
- if (model == NULL)
- model = fz_device_gray(ctx);
-
if (flatness < 0.001f)
flatness = 0.001f;
@@ -298,8 +295,9 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
@@ -331,14 +329,11 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
unsigned char colorbv[FZ_MAX_COLORS + 1];
float colorfv[FZ_MAX_COLORS];
fz_irect bbox;
- int i;
+ int i, n;
float aa_level = 2.0f/(fz_graphics_aa_level(ctx)+2);
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
- if (model == NULL)
- model = fz_device_gray(ctx);
-
if (linewidth * expansion < aa_level)
linewidth = aa_level / expansion;
if (flatness < 0.001f)
@@ -359,11 +354,19 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, state->dest, "Before stroke ");
+ if (state->shape)
+ fz_dump_blend(ctx, state->shape, "/");
+ printf("\n");
+#endif
fz_scan_convert(ctx, gel, 0, &bbox, state->dest, colorbv);
if (state->shape)
{
@@ -377,6 +380,13 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
colorbv[0] = 255;
fz_scan_convert(ctx, gel, 0, &bbox, state->shape, colorbv);
}
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, state->dest, "After stroke ");
+ if (state->shape)
+ fz_dump_blend(ctx, state->shape, "/");
+ printf("\n");
+#endif
if (state->blendmode & FZ_BLEND_KNOCKOUT)
fz_knockout_end(ctx, dev);
@@ -424,13 +434,20 @@ fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
fz_try(ctx)
{
- state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].mask);
- state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, state[1].dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state[1].shape)
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
@@ -487,13 +504,20 @@ fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path,
fz_try(ctx)
{
- state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].mask);
- state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, state[1].dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state->shape)
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
@@ -537,24 +561,25 @@ draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_glyph *glyph,
skip_x = x - glyph->x - xorig;
skip_y = y - glyph->y - yorig;
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
-
msk = glyph->pixmap;
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
if (msk == NULL)
{
fz_paint_glyph(colorbv, dst, dp, glyph, w, h, skip_x, skip_y);
}
else
{
- unsigned char *mp = msk->samples + skip_y * msk->w + skip_x;
+ unsigned char *mp = msk->samples + skip_y * msk->stride + skip_x;
+ int da = dst->alpha;
+
while (h--)
{
if (dst->colorspace)
- fz_paint_span_with_color(dp, mp, dst->n, w, colorbv);
+ fz_paint_span_with_color(dp, mp, dst->n, w, colorbv, da);
else
- fz_paint_span(dp, mp, 1, w, 255);
- dp += dst->w * dst->n;
- mp += msk->w;
+ fz_paint_span(dp, da, mp, 1, 0, w, 255);
+ dp += dst->stride;
+ mp += msk->stride;
}
}
}
@@ -570,13 +595,14 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
unsigned char shapebv;
float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
- int i;
+ int i, n;
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
shapebv = 255;
@@ -599,7 +625,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
tm.f = span->items[i].y;
fz_concat(&trm, &tm, ctm);
- glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor);
+ glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor, state->dest->alpha);
if (glyph)
{
fz_pixmap *pixmap = glyph->pixmap;
@@ -651,13 +677,14 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
unsigned char colorbv[FZ_MAX_COLORS + 1];
float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
- int i;
+ int i, n;
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
@@ -738,13 +765,20 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
fz_try(ctx)
{
- mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, mask);
- dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, dest);
+ else
+ fz_copy_pixmap_rect(ctx, dest, state[0].dest, &bbox);
if (state->shape)
{
- shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
else
@@ -775,7 +809,7 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
tm.f = span->items[i].y;
fz_concat(&trm, &tm, ctm);
- glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor);
+ glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor, state[1].dest->alpha);
if (glyph)
{
int x = (int)trm.e;
@@ -853,13 +887,20 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text,
fz_try(ctx)
{
- state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, mask);
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state->shape)
{
- state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
else
@@ -963,12 +1004,6 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (fz_is_empty_irect(&bbox))
return;
- if (!model)
- {
- fz_warn(ctx, "cannot render shading directly to an alpha mask");
- return;
- }
-
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
@@ -977,11 +1012,14 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (alpha < 1)
{
- dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox);
- fz_clear_pixmap(ctx, dest);
+ dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox, state->dest->alpha);
+ if (state->dest->alpha)
+ fz_clear_pixmap(ctx, dest);
+ else
+ fz_copy_pixmap_rect(ctx, dest, state[0].dest, &bbox);
if (shape)
{
- shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
}
@@ -990,15 +1028,16 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
{
unsigned char *s;
int x, y, n, i;
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, shade->colorspace, shade->background);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = 255;
n = dest->n;
for (y = scissor.y0; y < scissor.y1; y++)
{
- s = dest->samples + (unsigned int)(((scissor.x0 - dest->x) + (y - dest->y) * dest->w) * dest->n);
+ s = dest->samples + (unsigned int)((y - dest->y) * dest->stride + (scissor.x0 - dest->x) * n);
for (x = scissor.x0; x < scissor.x1; x++)
{
for (i = 0; i < n; i++)
@@ -1009,7 +1048,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
{
for (y = scissor.y0; y < scissor.y1; y++)
{
- s = shape->samples + (unsigned int)((scissor.x0 - shape->x) + (y - shape->y) * shape->w);
+ s = shape->samples + (unsigned int)((y - shape->y) * shape->stride + (scissor.x0 - shape->x));
for (x = scissor.x0; x < scissor.x1; x++)
{
*s++ = 255;
@@ -1022,6 +1061,14 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (shape)
fz_clear_pixmap_rect_with_value(ctx, shape, 255, &bbox);
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, dest, "Shade ");
+ if (shape)
+ fz_dump_blend(ctx, shape, "/");
+ printf("\n");
+#endif
+
if (alpha < 1)
{
fz_paint_pixmap(state->dest, dest, alpha * 255);
@@ -1122,12 +1169,6 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
fz_var(scaled);
- if (!model)
- {
- fz_warn(ctx, "cannot render image directly to an alpha mask");
- return;
- }
-
if (image->w == 0 || image->h == 0)
return;
@@ -1170,7 +1211,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
orig_pixmap = pixmap;
/* convert images with more components (cmyk->rgb) before scaling */
- /* convert images with fewer components (gray->rgb after scaling */
+ /* convert images with fewer components (gray->rgb) after scaling */
/* convert images with expensive colorspace transforms after scaling */
fz_try(ctx)
@@ -1186,7 +1227,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
{
fz_irect bbox;
fz_pixmap_bbox(ctx, pixmap, &bbox);
- converted = fz_new_pixmap_with_bbox(ctx, model, &bbox);
+ converted = fz_new_pixmap_with_bbox(ctx, model, &bbox, pixmap->alpha);
fz_convert_pixmap(ctx, converted, pixmap);
pixmap = converted;
}
@@ -1218,7 +1259,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
{
fz_irect bbox;
fz_pixmap_bbox(ctx, pixmap, &bbox);
- converted = fz_new_pixmap_with_bbox(ctx, model, &bbox);
+ converted = fz_new_pixmap_with_bbox(ctx, model, &bbox, pixmap->alpha);
fz_convert_pixmap(ctx, converted, pixmap);
pixmap = converted;
}
@@ -1252,7 +1293,7 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_pixmap *pixmap;
fz_pixmap *orig_pixmap;
int dx, dy;
- int i;
+ int i, n;
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
fz_irect clip;
@@ -1325,8 +1366,9 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
pixmap = scaled;
}
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
@@ -1404,14 +1446,21 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
pixmap = fz_get_pixmap_from_image(ctx, image, NULL, &local_ctm, &dx, &dy);
orig_pixmap = pixmap;
- state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, mask);
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state->shape)
{
- state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
@@ -1433,7 +1482,21 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
if (scaled)
pixmap = scaled;
}
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, pixmap, "Plotting imagemask ");
+ fz_dump_blend(ctx, mask, "/");
+ fz_dump_blend(ctx, state[1].dest, " onto ");
+ if (state[1].shape)
+ fz_dump_blend(ctx, state[1].shape, "/");
+#endif
fz_paint_image(mask, &bbox, state->shape, pixmap, &local_ctm, 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
+#ifdef DUMP_GROUP_BLENDS
+ fz_dump_blend(ctx, state[1].dest, " to get ");
+ if (state[1].shape)
+ fz_dump_blend(ctx, state[1].shape, "/");
+ printf("\n");
+#endif
}
fz_always(ctx)
{
@@ -1517,7 +1580,13 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
fz_try(ctx)
{
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), &bbox);
+ /* If luminosity, then we generate a mask from the greyscale value of the shapes.
+ * If !luminosity, then we generate a mask from the alpha value of the shapes.
+ */
+ if (luminosity)
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), &bbox, 0);
+ else
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
if (state->shape)
{
/* FIXME: If we ever want to support AIS true, then
@@ -1547,7 +1616,8 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
}
#ifdef DUMP_GROUP_BLENDS
- dump_spaces(dev->top-1, "Mask begin\n");
+ dump_spaces(dev->top-1, "Mask begin");
+ printf("%s\n", luminosity ? "(luminosity)" : "");
#endif
state[1].scissor = bbox;
state[1].luminosity = luminosity;
@@ -1578,7 +1648,10 @@ fz_draw_end_mask(fz_context *ctx, fz_device *devp)
luminosity = state[1].luminosity;
#ifdef DUMP_GROUP_BLENDS
- dump_spaces(dev->top-1, "Mask -> Clip\n");
+ dump_spaces(dev->top-1, "Mask -> Clip: ");
+ fz_dump_blend(ctx, state[1].dest, "Mask ");
+ if (state[1].shape)
+ fz_dump_blend(ctx, state[1].shape, "/");
#endif
fz_try(ctx)
{
@@ -1594,10 +1667,18 @@ fz_draw_end_mask(fz_context *ctx, fz_device *devp)
fz_drop_pixmap(ctx, state[1].shape);
state[1].shape = NULL;
+#ifdef DUMP_GROUP_BLENDS
+ fz_dump_blend(ctx, temp, "-> Clip ");
+ printf("\n");
+#endif
+
/* create new dest scratch buffer */
fz_pixmap_bbox(ctx, temp, &bbox);
- dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox);
- fz_clear_pixmap(ctx, dest);
+ dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox, state->dest->alpha);
+ if (state->dest->alpha)
+ fz_clear_pixmap(ctx, dest);
+ else
+ fz_copy_pixmap_rect(ctx, dest, state->dest, &bbox);
/* push soft mask as clip mask */
state[1].dest = dest;
@@ -1606,7 +1687,7 @@ fz_draw_end_mask(fz_context *ctx, fz_device *devp)
* clip mask when we pop. So create a new shape now. */
if (state[0].shape)
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
state[1].scissor = bbox;
@@ -1635,13 +1716,13 @@ fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, int i
fz_try(ctx)
{
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
-
#ifndef ATTEMPT_KNOCKOUT_AND_ISOLATED
knockout = 0;
isolated = 1;
#endif
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha || isolated);
+
if (isolated)
{
fz_clear_pixmap(ctx, dest);
@@ -1659,7 +1740,7 @@ fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, int i
}
else
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
@@ -1902,12 +1983,13 @@ fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const
fz_try(ctx)
{
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
+ /* Patterns can be transparent, so we need to have an alpha here. */
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, 1);
fz_clear_pixmap(ctx, dest);
shape = state[0].shape;
if (shape)
{
- state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
state[1].blendmode |= FZ_BLEND_ISOLATED;