diff options
Diffstat (limited to 'source/fitz/draw-device.c')
-rw-r--r-- | source/fitz/draw-device.c | 177 |
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; |