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.c177
1 files changed, 139 insertions, 38 deletions
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index af8e8384..b4cb88c2 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -44,6 +44,7 @@ struct fz_draw_device_s
fz_device super;
fz_matrix transform;
fz_rasterizer *rast;
+ fz_default_colorspaces *default_cs;
int flags;
int top;
fz_scale_cache *cache_x;
@@ -107,6 +108,50 @@ static void stack_change(fz_context *ctx, fz_draw_device *dev, char *s)
#define STACK_CONVERT(A) do {} while (0)
#endif
+/* Based upon the existence of a proof color space, and if we happen to be
+ * in a color space that is our target color space or a transparency group
+ * color space decide if we should be using the proof color space at this time */
+static fz_colorspace *
+fz_proof_cs(fz_context *ctx, fz_device *devp)
+{
+ fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_colorspace *prf = fz_default_output_intent(ctx, dev->default_cs);
+ fz_draw_state *state = &dev->stack[dev->top];
+ fz_colorspace *model = state->dest->colorspace;
+
+ if (prf == NULL || model == prf)
+ return NULL;
+ return prf;
+}
+
+/* Logic below assumes that default cs is set to color context cs if there
+ * was not a default in the document for that particular cs
+ */
+static fz_colorspace *fz_default_colorspace(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs)
+{
+ if (cs == NULL)
+ return NULL;
+ if (default_cs == NULL)
+ return cs;
+
+ switch (fz_colorspace_n(ctx, cs))
+ {
+ case 1:
+ if (cs == fz_device_gray(ctx))
+ return fz_default_gray(ctx, default_cs);
+ break;
+ case 3:
+ if (cs == fz_device_rgb(ctx))
+ return fz_default_rgb(ctx, default_cs);
+ break;
+ case 4:
+ if (cs == fz_device_cmyk(ctx))
+ return fz_default_cmyk(ctx, default_cs);
+ break;
+ }
+ return cs;
+}
+
static void fz_grow_stack(fz_context *ctx, fz_draw_device *dev)
{
int max = dev->stack_cap * 2;
@@ -281,12 +326,13 @@ static inline fz_matrix concat(const fz_matrix *one, const fz_matrix *two)
static void
fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int even_odd, const fz_matrix *in_ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_rasterizer *rast = dev->rast;
-
+ fz_colorspace *colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
float expansion = fz_matrix_expansion(&ctm);
float flatness = 0.3f / expansion;
unsigned char colorbv[FZ_MAX_COLORS + 1];
@@ -299,6 +345,9 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
if (colorspace == NULL && model != NULL)
fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (flatness < 0.001f)
flatness = 0.001f;
@@ -312,7 +361,7 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, colorspace, color);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -336,12 +385,13 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
static void
fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *in_ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_rasterizer *rast = dev->rast;
-
+ fz_colorspace *colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
float expansion = fz_matrix_expansion(&ctm);
float flatness = 0.3f / expansion;
float linewidth = stroke->linewidth;
@@ -354,9 +404,13 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
fz_colorspace *model = state->dest->colorspace;
float mlw = fz_graphics_min_line_width(ctx);
+
if (colorspace == NULL && model != NULL)
fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (mlw > aa_level)
aa_level = mlw;
if (linewidth * expansion < aa_level)
@@ -374,7 +428,7 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, colorspace, color);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -626,7 +680,7 @@ draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_glyph *glyph,
static void
fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_matrix *in_ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix ctm = concat(in_ctm, &dev->transform);
@@ -637,17 +691,25 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
int i, n;
+ fz_colorspace *colorspace = NULL;
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
+
+ if (colorspace_in)
+ colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
if (colorspace == NULL && model != NULL)
fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, colorspace, color);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -700,7 +762,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
fz_path *path = fz_outline_glyph(ctx, span->font, gid, &tm);
if (path)
{
- fz_draw_fill_path(ctx, devp, path, 0, in_ctm, colorspace, color, alpha);
+ fz_draw_fill_path(ctx, devp, path, 0, in_ctm, colorspace, color, alpha, color_params);
fz_drop_path(ctx, path);
}
else
@@ -717,8 +779,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
static void
fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_stroke_state *stroke,
- const fz_matrix *in_ctm, fz_colorspace *colorspace,
- const float *color, float alpha)
+ const fz_matrix *in_ctm, fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix ctm = concat(in_ctm, &dev->transform);
@@ -728,17 +789,25 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
int i, n;
+ fz_colorspace *colorspace = NULL;
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
+
+ if (colorspace_in)
+ colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
if (colorspace == NULL && model != NULL)
fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, colorspace, color);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -779,7 +848,7 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
fz_path *path = fz_outline_glyph(ctx, span->font, gid, &tm);
if (path)
{
- fz_draw_stroke_path(ctx, devp, path, stroke, in_ctm, colorspace, color, alpha);
+ fz_draw_stroke_path(ctx, devp, path, stroke, in_ctm, colorspace, color, alpha, color_params);
fz_drop_path(ctx, path);
}
else
@@ -893,7 +962,7 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
state[1].mask = NULL;
fz_try(ctx)
{
- fz_draw_fill_path(ctx, devp, path, 0, in_ctm, fz_device_gray(ctx), &white, 1);
+ fz_draw_fill_path(ctx, devp, path, 0, in_ctm, fz_device_gray(ctx), &white, 1, NULL);
}
fz_always(ctx)
{
@@ -1016,7 +1085,7 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text,
state[0].mask = NULL;
fz_try(ctx)
{
- fz_draw_stroke_path(ctx, devp, path, stroke, in_ctm, fz_device_gray(ctx), &white, 1);
+ fz_draw_stroke_path(ctx, devp, path, stroke, in_ctm, fz_device_gray(ctx), &white, 1, NULL);
}
fz_always(ctx)
{
@@ -1050,7 +1119,7 @@ fz_draw_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
}
static void
-fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_matrix *in_ctm, float alpha)
+fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_matrix *in_ctm, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix ctm = concat(in_ctm, &dev->transform);
@@ -1061,6 +1130,7 @@ 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 *model = state->dest->colorspace;
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
fz_bound_shade(ctx, shade, &ctm, &bounds);
scissor = state->scissor;
@@ -1069,6 +1139,9 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (fz_is_empty_irect(&bbox))
return;
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
@@ -1096,7 +1169,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, shade->colorspace, shade->background);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, fz_default_colorspace(ctx, dev->default_cs, shade->colorspace), shade->background);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -1127,7 +1200,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
}
}
- fz_paint_shade(ctx, shade, &ctm, dest, &bbox);
+ fz_paint_shade(ctx, shade, &ctm, dest, prf, color_params, &bbox);
if (shape)
fz_clear_pixmap_rect_with_value(ctx, shape, 255, &bbox);
@@ -1219,7 +1292,7 @@ fz_default_image_scale(void *arg, int dst_w, int dst_h, int src_w, int src_h)
}
static void
-fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *in_ctm, float alpha)
+fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *in_ctm, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix local_ctm = concat(in_ctm, &dev->transform);
@@ -1231,6 +1304,8 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
fz_irect clip;
fz_matrix inverse;
fz_irect src_area;
+ fz_colorspace *src_cs;
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
fz_intersect_irect(fz_pixmap_bbox(ctx, state->dest, &clip), &state->scissor);
@@ -1273,6 +1348,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
}
pixmap = fz_get_pixmap_from_image(ctx, image, &src_area, &local_ctm, &dx, &dy);
+ src_cs = fz_default_colorspace(ctx, dev->default_cs, pixmap->colorspace);
/* convert images with more components (cmyk->rgb) before scaling */
/* convert images with fewer components (gray->rgb) after scaling */
@@ -1286,12 +1362,12 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
state = fz_knockout_begin(ctx, dev);
after = 0;
- if (pixmap->colorspace == fz_device_gray(ctx))
+ if (src_cs == fz_device_gray(ctx))
after = 1;
- if (pixmap->colorspace != model && !after)
+ if (src_cs != model && !after)
{
- fz_pixmap *converted = fz_convert_pixmap(ctx, pixmap, model, 1);
+ fz_pixmap *converted = fz_convert_pixmap(ctx, pixmap, model, prf, dev->default_cs, color_params, 1);
fz_drop_pixmap(ctx, pixmap);
pixmap = converted;
}
@@ -1315,18 +1391,18 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
}
}
- if (pixmap->colorspace != model)
+ if (src_cs != model && after)
{
#if FZ_PLOTTERS_RGB
- if ((pixmap->colorspace == fz_device_gray(ctx) && model == fz_device_rgb(ctx)) ||
- (pixmap->colorspace == fz_device_gray(ctx) && model == fz_device_bgr(ctx)))
+ if ((src_cs == fz_device_gray(ctx) && model == fz_device_rgb(ctx)) ||
+ (src_cs == fz_device_gray(ctx) && model == fz_device_bgr(ctx)))
{
/* We have special case rendering code for gray -> rgb/bgr */
}
else
#endif
{
- fz_pixmap *converted = fz_convert_pixmap(ctx, pixmap, model, 1);
+ fz_pixmap *converted = fz_convert_pixmap(ctx, pixmap, model, prf, dev->default_cs, color_params, 1);
fz_drop_pixmap(ctx, pixmap);
pixmap = converted;
}
@@ -1345,7 +1421,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
static void
fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *in_ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix local_ctm = concat(in_ctm, &dev->transform);
@@ -1360,6 +1436,14 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_irect clip;
fz_matrix inverse;
fz_irect src_area;
+ fz_colorspace *colorspace = NULL;
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
+
+ if (colorspace_in)
+ colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
+
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
if (colorspace == NULL && model != NULL)
fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
@@ -1436,7 +1520,7 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, colorspace, color);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -1629,7 +1713,7 @@ fz_draw_pop_clip(fz_context *ctx, fz_device *devp)
}
static void
-fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int luminosity, fz_colorspace *colorspace, const float *colorfv)
+fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int luminosity, fz_colorspace *colorspace_in, const float *colorfv, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_pixmap *dest;
@@ -1637,6 +1721,13 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
fz_draw_state *state = push_stack(ctx, dev);
fz_pixmap *shape = state->shape;
fz_rect trect = *rect;
+ fz_colorspace *colorspace = NULL;
+
+ if (colorspace_in)
+ colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
+
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
STACK_PUSHED("mask");
fz_transform_rect(&trect, &dev->transform);
@@ -1671,7 +1762,7 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
float bc;
if (!colorspace)
colorspace = fz_device_gray(ctx);
- fz_convert_color(ctx, fz_device_gray(ctx), &bc, colorspace, colorfv);
+ fz_convert_color(ctx, color_params, NULL, fz_device_gray(ctx), &bc, colorspace, colorfv);
fz_clear_pixmap_with_value(ctx, dest, bc * 255);
if (shape)
fz_clear_pixmap_with_value(ctx, shape, 255);
@@ -2247,11 +2338,28 @@ fz_draw_end_tile(fz_context *ctx, fz_device *devp)
}
static void
+fz_draw_render_flags(fz_context *ctx, fz_device *devp, int set, int clear)
+{
+ fz_draw_device *dev = (fz_draw_device*)devp;
+ dev->flags = (dev->flags | set ) & ~clear;
+}
+
+static void
+fz_draw_set_default_colorspaces(fz_context *ctx, fz_device *devp, fz_default_colorspaces *default_cs)
+{
+ fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_drop_default_colorspaces(ctx, dev->default_cs);
+ dev->default_cs = fz_keep_default_colorspaces(ctx, default_cs);
+}
+
+static void
fz_draw_drop_device(fz_context *ctx, fz_device *devp)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_rasterizer *rast = dev->rast;
+ fz_drop_default_colorspaces(ctx, dev->default_cs);
+
/* pop and free the stacks */
if (dev->top > 0)
fz_warn(ctx, "items left on stack in draw device: %d", dev->top+1);
@@ -2277,14 +2385,6 @@ fz_draw_drop_device(fz_context *ctx, fz_device *devp)
fz_drop_rasterizer(ctx, rast);
}
-static void
-fz_draw_render_flags(fz_context *ctx, fz_device *devp, int set, int clear)
-{
- fz_draw_device *dev = (fz_draw_device*)devp;
-
- dev->flags = (dev->flags | set ) & ~clear;
-}
-
fz_device *
fz_new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest)
{
@@ -2319,6 +2419,7 @@ fz_new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest)
dev->super.end_tile = fz_draw_end_tile;
dev->super.render_flags = fz_draw_render_flags;
+ dev->super.set_default_colorspaces = fz_draw_set_default_colorspaces;
dev->transform = transform ? *transform : fz_identity;
dev->flags = 0;