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.c168
1 files changed, 137 insertions, 31 deletions
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index d8f5c911..9ff734ec 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -349,7 +349,55 @@ colors_supported(fz_context *ctx, fz_colorspace *cs, fz_pixmap *dest)
}
static void
-resolve_color(fz_context *ctx, const float *color, fz_colorspace *colorspace, float alpha, const fz_color_params *color_params, unsigned char *colorbv, fz_pixmap *dest, fz_colorspace *prf)
+set_op_from_spaces(fz_context *ctx, fz_overprint *op, const fz_pixmap *dest, const fz_colorspace *src, int opm)
+{
+ int dn, sn, i, j, dc;
+
+ if (!op)
+ return;
+
+ sn = fz_colorspace_n(ctx, src);
+ dn = dest->n - dest->alpha;
+ dc = dn - dest->s;
+
+ for (i = 0; i < dc; i++)
+ {
+ const char *name = fz_colorspace_colorant(ctx, dest->colorspace, i);
+
+ for (j = 0; j < sn; j++)
+ {
+ const char *sname = fz_colorspace_colorant(ctx, src, j);
+ if (!name || !sname)
+ continue;
+ if (!strcmp(name, sname))
+ break;
+ if (!strcmp(sname, "All"))
+ break;
+ }
+ if (j == sn)
+ fz_set_overprint(op, i);
+ }
+ for (i = dc; i < dn; i++)
+ {
+ const char *name = fz_separation_name(ctx, dest->seps, i - dc);
+
+ for (j = 0; j < sn; j++)
+ {
+ const char *sname = fz_colorspace_colorant(ctx, src, j);
+ if (!name || !sname)
+ continue;
+ if (!strcmp(name, sname))
+ break;
+ if (!strcmp(sname, "All"))
+ break;
+ }
+ if (j == sn)
+ fz_set_overprint(op, i);
+ }
+}
+
+static fz_overprint *
+resolve_color(fz_context *ctx, fz_overprint *op, const float *color, fz_colorspace *colorspace, float alpha, const fz_color_params *color_params, unsigned char *colorbv, fz_pixmap *dest, fz_colorspace *prf)
{
float colorfv[FZ_MAX_COLORS];
int i;
@@ -362,6 +410,9 @@ resolve_color(fz_context *ctx, const float *color, fz_colorspace *colorspace, fl
if (color_params == NULL)
color_params = fz_default_color_params(ctx);
+ if (!color_params || color_params->op == 0 || !fz_colorspace_is_subtractive(ctx, dest->colorspace))
+ op = NULL;
+
if (n == 0)
i = 0;
else if (fz_colorspace_is_device_n(ctx, colorspace) && colors_supported(ctx, colorspace, dest))
@@ -369,6 +420,7 @@ resolve_color(fz_context *ctx, const float *color, fz_colorspace *colorspace, fl
fz_convert_separation_colors(ctx, color_params, dest->colorspace, dest->seps, colorfv, colorspace, color);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
+ set_op_from_spaces(ctx, op, dest, colorspace, color_params->opm);
}
else
{
@@ -378,8 +430,25 @@ resolve_color(fz_context *ctx, const float *color, fz_colorspace *colorspace, fl
colorbv[i] = colorfv[i] * 255;
for (; i < n; i++)
colorbv[i] = 0;
+
}
colorbv[i] = alpha * 255;
+
+ /* If we are overprinting, and we're plotting in cmyk and a given
+ * color component is zero, then protect that component from being
+ * written to. */
+ if (op)
+ {
+ if (!fz_colorspace_is_device_n(ctx, colorspace))
+ for (i = 4; i < n; i++)
+ fz_set_overprint(op, i);
+ if (color_params->opm == 1 && fz_colorspace_n(ctx, colorspace) == 4)
+ for (i = 0; i < n; i++)
+ if (colorfv[i] == 0)
+ fz_set_overprint(op, i);
+ }
+
+ return op;
}
static fz_draw_state *
@@ -424,6 +493,8 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
unsigned char colorbv[FZ_MAX_COLORS + 1];
fz_irect bbox;
fz_draw_state *state = &dev->stack[dev->top];
+ fz_overprint op = { { 0 } };
+ fz_overprint *eop;
if (dev->top == 0 && dev->resolve_spots)
state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
@@ -438,16 +509,16 @@ 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);
- resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
+ eop = resolve_color(ctx, &op, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
- fz_convert_rasterizer(ctx, rast, even_odd, state->dest, colorbv);
+ fz_convert_rasterizer(ctx, rast, even_odd, state->dest, colorbv, eop);
if (state->shape)
{
if (!rast->fns.reusable)
fz_flatten_fill_path(ctx, rast, path, &ctm, flatness, &bbox, NULL);
colorbv[0] = alpha * 255;
- fz_convert_rasterizer(ctx, rast, even_odd, state->shape, colorbv);
+ fz_convert_rasterizer(ctx, rast, even_odd, state->shape, colorbv, 0);
}
if (state->blendmode & FZ_BLEND_KNOCKOUT)
@@ -471,6 +542,8 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
float aa_level = 2.0f/(fz_rasterizer_graphics_aa_level(rast)+2);
fz_draw_state *state = &dev->stack[dev->top];
float mlw = fz_rasterizer_graphics_min_line_width(rast);
+ fz_overprint op = { { 0 } };
+ fz_overprint *eop;
if (dev->top == 0 && dev->resolve_spots)
state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
@@ -489,7 +562,7 @@ 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);
- resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
+ eop = resolve_color(ctx, &op, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
#ifdef DUMP_GROUP_BLENDS
dump_spaces(dev->top, "");
@@ -498,14 +571,14 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
fz_dump_blend(ctx, "/", state->shape);
printf("\n");
#endif
- fz_convert_rasterizer(ctx, rast, 0, state->dest, colorbv);
+ fz_convert_rasterizer(ctx, rast, 0, state->dest, colorbv, eop);
if (state->shape)
{
if (!rast->fns.reusable)
(void)fz_flatten_stroke_path(ctx, rast, path, stroke, &ctm, flatness, linewidth, &bbox, NULL);
colorbv[0] = 255;
- fz_convert_rasterizer(ctx, rast, 0, state->shape, colorbv);
+ fz_convert_rasterizer(ctx, rast, 0, state->shape, colorbv, 0);
}
#ifdef DUMP_GROUP_BLENDS
dump_spaces(dev->top, "");
@@ -574,7 +647,7 @@ fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
fz_clear_pixmap(ctx, state[1].shape);
}
- fz_convert_rasterizer(ctx, rast, even_odd, state[1].mask, NULL);
+ fz_convert_rasterizer(ctx, rast, even_odd, state[1].mask, NULL, 0);
state[1].scissor = bbox;
#ifdef DUMP_GROUP_BLENDS
@@ -656,7 +729,7 @@ fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path,
fz_clear_pixmap(ctx, state[1].shape);
}
- fz_convert_rasterizer(ctx, rast, 0, state[1].mask, NULL);
+ fz_convert_rasterizer(ctx, rast, 0, state[1].mask, NULL, 0);
state[1].blendmode |= FZ_BLEND_ISOLATED;
state[1].scissor = bbox;
@@ -672,7 +745,7 @@ fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path,
static void
draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_glyph *glyph,
- int xorig, int yorig, const fz_irect *scissor)
+ int xorig, int yorig, const fz_irect *scissor, fz_overprint *eop)
{
unsigned char *dp;
fz_irect bbox, bbox2;
@@ -699,7 +772,7 @@ draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_glyph *glyph,
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);
+ fz_paint_glyph(colorbv, dst, dp, glyph, w, h, skip_x, skip_y, eop);
}
else
{
@@ -710,13 +783,13 @@ draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_glyph *glyph,
{
fz_span_color_painter_t *fn;
- fn = fz_get_span_color_painter(dst->n, da, colorbv);
+ fn = fz_get_span_color_painter(dst->n, da, colorbv, eop);
assert(fn);
if (fn == NULL)
return;
while (h--)
{
- (*fn)(dp, mp, dst->n, w, colorbv, da);
+ (*fn)(dp, mp, dst->n, w, colorbv, da, eop);
dp += dst->stride;
mp += msk->stride;
}
@@ -725,13 +798,13 @@ draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_glyph *glyph,
{
fz_span_painter_t *fn;
- fn = fz_get_span_painter(da, 1, 0, 255);
+ fn = fz_get_span_painter(da, 1, 0, 255, eop);
assert(fn);
if (fn == NULL)
return;
while (h--)
{
- (*fn)(dp, da, mp, 1, 0, w, 255);
+ (*fn)(dp, da, mp, 1, 0, w, 255, eop);
dp += dst->stride;
mp += msk->stride;
}
@@ -754,6 +827,8 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
fz_colorspace *colorspace = NULL;
fz_colorspace *prf = fz_proof_cs(ctx, dev);
fz_rasterizer *rast = dev->rast;
+ fz_overprint op = { { 0 } };
+ fz_overprint *eop;
if (dev->top == 0 && dev->resolve_spots)
state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
@@ -770,7 +845,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
- resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
+ eop = resolve_color(ctx, &op, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
shapebv = 255;
for (span = text->head; span; span = span->next)
@@ -799,16 +874,16 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
int y = floorf(trm.f);
if (pixmap == NULL || pixmap->n == 1)
{
- draw_glyph(colorbv, state->dest, glyph, x, y, &state->scissor);
+ draw_glyph(colorbv, state->dest, glyph, x, y, &state->scissor, eop);
if (state->shape)
- draw_glyph(&shapebv, state->shape, glyph, x, y, &state->scissor);
+ draw_glyph(&shapebv, state->shape, glyph, x, y, &state->scissor, 0);
}
else
{
fz_matrix mat;
mat.a = pixmap->w; mat.b = mat.c = 0; mat.d = pixmap->h;
mat.e = x + pixmap->x; mat.f = y + pixmap->y;
- fz_paint_image(state->dest, &state->scissor, state->shape, pixmap, &mat, alpha * 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
+ fz_paint_image(state->dest, &state->scissor, state->shape, pixmap, &mat, alpha * 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, eop);
}
fz_drop_glyph(ctx, glyph);
}
@@ -845,6 +920,8 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
fz_colorspace *colorspace = NULL;
fz_colorspace *prf = fz_proof_cs(ctx, dev);
int aa = fz_rasterizer_text_aa_level(dev->rast);
+ fz_overprint op = { { 0 } };
+ fz_overprint *eop;
if (dev->top == 0 && dev->resolve_spots)
state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
@@ -855,7 +932,7 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
- resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
+ eop = resolve_color(ctx, &op, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
for (span = text->head; span; span = span->next)
{
@@ -880,9 +957,9 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
{
int x = (int)trm.e;
int y = (int)trm.f;
- draw_glyph(colorbv, state->dest, glyph, x, y, &state->scissor);
+ draw_glyph(colorbv, state->dest, glyph, x, y, &state->scissor, eop);
if (state->shape)
- draw_glyph(colorbv, state->shape, glyph, x, y, &state->scissor);
+ draw_glyph(colorbv, state->shape, glyph, x, y, &state->scissor, 0);
fz_drop_glyph(ctx, glyph);
}
else
@@ -990,9 +1067,9 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
{
int x = (int)trm.e;
int y = (int)trm.f;
- draw_glyph(NULL, mask, glyph, x, y, &bbox);
+ draw_glyph(NULL, mask, glyph, x, y, &bbox, 0);
if (state[1].shape)
- draw_glyph(NULL, state[1].shape, glyph, x, y, &bbox);
+ draw_glyph(NULL, state[1].shape, glyph, x, y, &bbox, 0);
fz_drop_glyph(ctx, glyph);
}
else
@@ -1116,9 +1193,9 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text,
{
int x = (int)trm.e;
int y = (int)trm.f;
- draw_glyph(NULL, mask, glyph, x, y, &bbox);
+ draw_glyph(NULL, mask, glyph, x, y, &bbox, 0);
if (shape)
- draw_glyph(NULL, shape, glyph, x, y, &bbox);
+ draw_glyph(NULL, shape, glyph, x, y, &bbox, 0);
fz_drop_glyph(ctx, glyph);
}
else
@@ -1179,6 +1256,8 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
unsigned char colorbv[FZ_MAX_COLORS + 1];
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *prf = fz_proof_cs(ctx, dev);
+ fz_overprint op = { { 0 } };
+ fz_overprint *eop;
if (dev->top == 0 && dev->resolve_spots)
state = push_group_for_separations(ctx, dev, color_params, prf, dev->default_cs);
@@ -1218,7 +1297,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
unsigned char *s;
int x, y, n, i;
- resolve_color(ctx, shade->background, fz_default_colorspace(ctx, dev->default_cs, shade->colorspace), alpha, color_params, colorbv, state->dest, prf);
+ eop = resolve_color(ctx, &op, shade->background, fz_default_colorspace(ctx, dev->default_cs, shade->colorspace), alpha, color_params, colorbv, state->dest, prf);
n = dest->n;
for (y = scissor.y0; y < scissor.y1; y++)
@@ -1257,6 +1336,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (alpha < 1)
{
+ /* FIXME: eop */
fz_paint_pixmap(state->dest, dest, alpha * 255);
fz_drop_pixmap(ctx, dest);
if (shape)
@@ -1349,6 +1429,8 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
fz_irect src_area;
fz_colorspace *src_cs;
fz_colorspace *prf = fz_proof_cs(ctx, dev);
+ fz_overprint op = { { 0 } };
+ fz_overprint *eop = &op;
if (alpha == 0)
return;
@@ -1363,6 +1445,9 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
if (image->w == 0 || image->h == 0)
return;
+ if (!color_params || color_params->op == 0)
+ eop = NULL;
+
/* ctm maps the image (expressed as the unit square) onto the
* destination device. Reverse that to get a mapping from
* the destination device to the source pixels. */
@@ -1417,6 +1502,10 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
after = 0;
if (src_cs == fz_device_gray(ctx))
after = 1;
+ else if (fz_colorspace_is_indexed(ctx, src_cs))
+ {}
+ else if (fz_colorspace_n(ctx, src_cs) <= fz_colorspace_n(ctx, model))
+ after = 1;
if (conversion_required && !after)
{
@@ -1424,7 +1513,10 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
/* If we have a spotty image, and we are going to spotty output,
* then we can't lose the spots during color conversion. */
if (fz_colorspace_is_device_n(ctx, src_cs) && state->dest->seps)
+ {
converted = fz_clone_pixmap_area_with_different_seps(ctx, pixmap, NULL, model, state->dest->seps, color_params, prf, dev->default_cs);
+ set_op_from_spaces(ctx, eop, state->dest, src_cs, color_params->opm);
+ }
else
converted = fz_convert_pixmap(ctx, pixmap, model, prf, dev->default_cs, color_params, 1);
fz_drop_pixmap(ctx, pixmap);
@@ -1464,15 +1556,27 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
{
fz_pixmap *converted;
if (fz_colorspace_is_device_n(ctx, src_cs) && state->dest->seps)
+ {
converted = fz_clone_pixmap_area_with_different_seps(ctx, pixmap, NULL, model, state->dest->seps, color_params, prf, dev->default_cs);
+ set_op_from_spaces(ctx, eop, state->dest, src_cs, color_params->opm);
+ }
else
+ {
converted = fz_convert_pixmap(ctx, pixmap, model, prf, dev->default_cs, color_params, 1);
+ if (eop && !fz_colorspace_is_device_n(ctx, pixmap->colorspace) && fz_colorspace_n(ctx, model) == 4)
+ {
+ int i;
+ int n = state->dest->n - state->dest->alpha;
+ for (i = 4; i < n; i++)
+ fz_set_overprint(eop, i);
+ }
+ }
fz_drop_pixmap(ctx, pixmap);
pixmap = converted;
}
}
- fz_paint_image(state->dest, &state->scissor, state->shape, pixmap, &local_ctm, alpha * 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
+ fz_paint_image(state->dest, &state->scissor, state->shape, pixmap, &local_ctm, alpha * 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, eop);
if (state->blendmode & FZ_BLEND_KNOCKOUT)
fz_knockout_end(ctx, dev);
@@ -1499,6 +1603,8 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_irect src_area;
fz_colorspace *colorspace = NULL;
fz_colorspace *prf = fz_proof_cs(ctx, dev);
+ fz_overprint op = { { 0 } };
+ fz_overprint *eop;
if (alpha == 0)
return;
@@ -1578,9 +1684,9 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
}
}
- resolve_color(ctx, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
+ eop = resolve_color(ctx, &op, color, colorspace, alpha, color_params, colorbv, state->dest, prf);
- fz_paint_image_with_color(state->dest, &state->scissor, state->shape, pixmap, &local_ctm, colorbv, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
+ fz_paint_image_with_color(state->dest, &state->scissor, state->shape, pixmap, &local_ctm, colorbv, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, eop);
if (state->blendmode & FZ_BLEND_KNOCKOUT)
fz_knockout_end(ctx, dev);
@@ -1687,7 +1793,7 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
if (state[1].shape)
fz_dump_blend(ctx, "/", state[1].shape);
#endif
- fz_paint_image(state[1].mask, &bbox, state[1].shape, pixmap, &local_ctm, 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
+ fz_paint_image(state[1].mask, &bbox, state[1].shape, pixmap, &local_ctm, 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED, 0);
#ifdef DUMP_GROUP_BLENDS
fz_dump_blend(ctx, " to get ", state[1].mask);
if (state[1].shape)