diff options
author | Michael Vrhel <michael.vrhel@artifex.com> | 2012-02-21 11:30:58 -0800 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2012-03-15 11:54:23 +0000 |
commit | 902c99cc0c9032bf269c60da048542adfdb9be66 (patch) | |
tree | 7e3e698e86d1973eda682a165250758e507b3a11 | |
parent | 2b3234a84fc41b6bb3b9743f820a2606141b38b6 (diff) |
Fix for bug 692865. Make XPS interpreter use ICC color spaces for default
The XPS interpreter was still using Device color spaces for its default
color spaces. This fix has it use ICC color spaces by default which
is required by the spec. This revealed an issue with the color space
handling of the opacity masks. These were getting drawn in sRGB color
space but the transparency group is linear gray. Since we are drawing
the opacity mask as a luminosity mask that is gray we ended up
mapping through a nonlinearity.
-rw-r--r-- | gs/base/gscspace.c | 40 | ||||
-rw-r--r-- | gs/base/gscspace.h | 2 | ||||
-rw-r--r-- | gs/base/gxblend.c | 2 | ||||
-rw-r--r-- | xps/ghostxps.h | 1 | ||||
-rw-r--r-- | xps/xpsgradient.c | 51 | ||||
-rw-r--r-- | xps/xpsimage.c | 3 | ||||
-rw-r--r-- | xps/xpsopacity.c | 5 | ||||
-rw-r--r-- | xps/xpspage.c | 8 | ||||
-rw-r--r-- | xps/xpstop.c | 9 |
9 files changed, 90 insertions, 31 deletions
diff --git a/gs/base/gscspace.c b/gs/base/gscspace.c index 7dc1235a7..24c8a1b15 100644 --- a/gs/base/gscspace.c +++ b/gs/base/gscspace.c @@ -159,6 +159,46 @@ gs_cspace_new_DeviceCMYK(gs_memory_t *mem) &gs_color_space_type_DeviceCMYK); } +/* For use in initializing ICC color spaces for XPS */ +gs_color_space * +gs_cspace_new_ICC(gs_memory_t *pmem, gs_state * pgs, int components) +{ + gsicc_manager_t *icc_manage = pgs->icc_manager; + int code; + gs_color_space *pcspace = gs_cspace_alloc(pmem, &gs_color_space_type_ICC); + + switch (components) { + case -1: /* alpha case */ + if (icc_manage->smask_profiles == NULL) { + code = gsicc_initialize_iccsmask(icc_manage); + } + if (code == 0) { + pcspace->cmm_icc_profile_data = + icc_manage->smask_profiles->smask_gray; + } else { + pcspace->cmm_icc_profile_data = icc_manage->default_gray; + } + break; + case -3: /* alpha case. needs linear RGB */ + if (icc_manage->smask_profiles == NULL) { + code = gsicc_initialize_iccsmask(icc_manage); + } + if (code == 0) { + pcspace->cmm_icc_profile_data = + icc_manage->smask_profiles->smask_rgb; + } else { + pcspace->cmm_icc_profile_data = icc_manage->default_rgb; + } + break; + case 1: pcspace->cmm_icc_profile_data = icc_manage->default_gray; break; + case 3: pcspace->cmm_icc_profile_data = icc_manage->default_rgb; break; + case 4: pcspace->cmm_icc_profile_data = icc_manage->default_cmyk; break; + default: rc_decrement(pcspace,"gs_cspace_new_ICC"); return NULL; + } + rc_increment(pcspace->cmm_icc_profile_data); + return pcspace; +} + /* ------ Accessors ------ */ /* Get the index of a color space. */ diff --git a/gs/base/gscspace.h b/gs/base/gscspace.h index 24dccd13a..c8c2e4e31 100644 --- a/gs/base/gscspace.h +++ b/gs/base/gscspace.h @@ -344,6 +344,8 @@ struct gs_color_space_s { gs_color_space *gs_cspace_new_DeviceGray(gs_memory_t *mem); gs_color_space *gs_cspace_new_DeviceRGB(gs_memory_t *mem); gs_color_space *gs_cspace_new_DeviceCMYK(gs_memory_t *mem); +gs_color_space *gs_cspace_new_ICC(gs_memory_t *pmem, gs_state * pgs, + int components); /* ------ Accessors ------ */ diff --git a/gs/base/gxblend.c b/gs/base/gxblend.c index b8a4ae2fe..64833a372 100644 --- a/gs/base/gxblend.c +++ b/gs/base/gxblend.c @@ -1463,7 +1463,7 @@ dump_raw_buffer(int num_rows, int width, int n_chan, /* during a particular band if we have a large file */ /* if (clist_band_count != 65) return; */ buff_ptr = Buffer; -#ifdef RAW_DUMP_AS_PAM +#if RAW_DUMP_AS_PAM if ((n_chan == 4) || (n_chan == 5)) { int x; sprintf(full_file_name,"%d)%s.pam",global_index,filename); diff --git a/xps/ghostxps.h b/xps/ghostxps.h index a7807b81f..3a94edc6a 100644 --- a/xps/ghostxps.h +++ b/xps/ghostxps.h @@ -367,6 +367,7 @@ struct xps_context_s gs_state *pgs; gs_font_dir *fontdir; + gs_color_space *gray_lin; /* needed for transparency */ gs_color_space *gray; gs_color_space *srgb; gs_color_space *scrgb; diff --git a/xps/xpsgradient.c b/xps/xpsgradient.c index 7230bde87..caaa38bca 100644 --- a/xps/xpsgradient.c +++ b/xps/xpsgradient.c @@ -266,7 +266,6 @@ xps_create_gradient_stop_function(xps_context_t *ctx, struct stop *stops, int co range[3] = 1.0; range[4] = 0.0; range[5] = 1.0; - sparams.n = 3; sparams.Range = range; functions = xps_alloc(ctx, k * sizeof(void*)); @@ -278,6 +277,17 @@ xps_create_gradient_stop_function(xps_context_t *ctx, struct stop *stops, int co sparams.Bounds = bounds; sparams.Encode = encode; + if (opacity_only) + { + sparams.n = 1; + lparams.n = 1; + } + else + { + sparams.n = 3; + lparams.n = 3; + } + for (i = 0; i < k; i++) { domain = xps_alloc(ctx, 2 * sizeof(float)); @@ -293,7 +303,6 @@ xps_create_gradient_stop_function(xps_context_t *ctx, struct stop *stops, int co range[3] = 1.0; range[4] = 0.0; range[5] = 1.0; - lparams.n = 3; lparams.Range = range; c0 = xps_alloc(ctx, 3 * sizeof(float)); @@ -305,12 +314,7 @@ xps_create_gradient_stop_function(xps_context_t *ctx, struct stop *stops, int co if (opacity_only) { c0[0] = stops[i].color[0]; - c0[1] = stops[i].color[0]; - c0[2] = stops[i].color[0]; - c1[0] = stops[i+1].color[0]; - c1[1] = stops[i+1].color[0]; - c1[2] = stops[i+1].color[0]; } else { @@ -423,13 +427,17 @@ xps_reverse_function(xps_context_t *ctx, gs_function_t *func, float *fary, void sparams.m = 1; sparams.Domain = domain; - sparams.n = 3; sparams.Range = range; sparams.k = 1; sparams.Functions = functions; sparams.Bounds = NULL; sparams.Encode = encode; + if (ctx->opacity_only) + sparams.n = 1; + else + sparams.n = 3; + code = gs_function_1ItSg_init(&sfunc, &sparams, ctx->memory); if (code < 0) { @@ -460,7 +468,10 @@ xps_draw_one_radial_gradient(xps_context_t *ctx, gs_shading_R_params_init(¶ms); { - params.ColorSpace = ctx->srgb; + if (ctx->opacity_only) + params.ColorSpace = ctx->gray_lin; + else + params.ColorSpace = ctx->srgb; params.Coords[0] = x0; params.Coords[1] = y0; @@ -509,7 +520,10 @@ xps_draw_one_linear_gradient(xps_context_t *ctx, gs_shading_A_params_init(¶ms); { - params.ColorSpace = ctx->srgb; + if (ctx->opacity_only) + params.ColorSpace = ctx->gray_lin; + else + params.ColorSpace = ctx->srgb; params.Coords[0] = x0; params.Coords[1] = y0; @@ -619,12 +633,16 @@ xps_draw_radial_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu out[1] = 0.0; out[2] = 0.0; out[3] = 0.0; - if (ctx->opacity_only) + if (ctx->opacity_only) + { gs_function_evaluate(func, in, out); - else + xps_set_color(ctx, ctx->gray_lin, out); + } + else + { gs_function_evaluate(func, in, out + 1); - - xps_set_color(ctx, ctx->srgb, out); + xps_set_color(ctx, ctx->srgb, out); + } gs_moveto(ctx->pgs, bbox.p.x, bbox.p.y); gs_lineto(ctx->pgs, bbox.q.x, bbox.p.y); @@ -917,7 +935,12 @@ xps_parse_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dic gs_trans_mask_params_init(¶ms, TRANSPARENCY_MASK_Luminosity); gs_begin_transparency_mask(ctx->pgs, ¶ms, &bbox, 0); + /* I dont like this, but dont want to change interface of draw */ + /* For the opacity case, we want to make sure the functions + are set up for gray only */ + ctx->opacity_only = true; code = draw(ctx, root, spread_method, opacity_func); + ctx->opacity_only = false; if (code) { gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity); diff --git a/xps/xpsimage.c b/xps/xpsimage.c index 2da749e40..7ccab0b30 100644 --- a/xps/xpsimage.c +++ b/xps/xpsimage.c @@ -220,7 +220,7 @@ xps_paint_image_brush_imp(xps_context_t *ctx, xps_image_t *image, int alpha) if (alpha) { - colorspace = ctx->gray; + colorspace = ctx->gray_lin; samples = image->alpha; count = (image->width * image->bits + 7) / 8 * image->height; used = 0; @@ -295,7 +295,6 @@ xps_paint_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, if (code < 0) return gs_rethrow(code, "cannot gsave before transparency group"); - gs_setcolorspace(ctx->pgs, ctx->gray); gs_trans_mask_params_init(¶ms, TRANSPARENCY_MASK_Luminosity); gs_begin_transparency_mask(ctx->pgs, ¶ms, &bbox, 0); code = xps_paint_image_brush_imp(ctx, image, 1); diff --git a/xps/xpsopacity.c b/xps/xpsopacity.c index 9545a610b..65f69864b 100644 --- a/xps/xpsopacity.c +++ b/xps/xpsopacity.c @@ -57,9 +57,10 @@ xps_begin_opacity(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, if (opacity_mask_tag) { gs_trans_mask_params_init(&tmp, TRANSPARENCY_MASK_Luminosity); + gs_gsave(ctx->pgs); + gs_setcolorspace(ctx->pgs, ctx->gray_lin); gs_begin_transparency_mask(ctx->pgs, &tmp, &bbox, 0); - gs_gsave(ctx->pgs); /* Need a path to fill/clip for the brush */ gs_moveto(ctx->pgs, bbox.p.x, bbox.p.y); @@ -81,8 +82,8 @@ xps_begin_opacity(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, return gs_rethrow(code, "cannot parse opacity mask brush"); } - gs_grestore(ctx->pgs); gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity); + gs_grestore(ctx->pgs); ctx->opacity_only = save; } diff --git a/xps/xpspage.c b/xps/xpspage.c index 4896ac311..3d32cb4a8 100644 --- a/xps/xpspage.c +++ b/xps/xpspage.c @@ -216,14 +216,6 @@ xps_parse_fixed_page(xps_context_t *ctx, xps_part_t *part) } } - /* Initialize the default profiles in the ctx to what is in the manager */ - ctx->gray->cmm_icc_profile_data = ctx->pgs->icc_manager->default_gray; - ctx->srgb->cmm_icc_profile_data = ctx->pgs->icc_manager->default_rgb; - /* scrgb really needs to be a bit different. - * Unless we are handling nonlinearity before conversion from float. ToDo. */ - ctx->scrgb->cmm_icc_profile_data = ctx->pgs->icc_manager->default_rgb; - ctx->cmyk->cmm_icc_profile_data = ctx->pgs->icc_manager->default_cmyk; - /* Draw contents */ for (node = xps_down(root); node; node = xps_next(node)) diff --git a/xps/xpstop.c b/xps/xpstop.c index f88d71f3e..3effd01ac 100644 --- a/xps/xpstop.c +++ b/xps/xpstop.c @@ -126,10 +126,11 @@ xps_imp_allocate_interp_instance(pl_interp_instance_t **ppinstance, ctx->zip_table = NULL; /* Gray, RGB and CMYK profiles set when color spaces installed in graphics lib */ - ctx->gray = gs_cspace_new_DeviceGray(ctx->memory); - ctx->cmyk = gs_cspace_new_DeviceCMYK(ctx->memory); - ctx->srgb = gs_cspace_new_DeviceRGB(ctx->memory); - ctx->scrgb = gs_cspace_new_DeviceRGB(ctx->memory); /* This needs a different profile */ + ctx->gray_lin = gs_cspace_new_ICC(ctx->memory, ctx->pgs, -1); + ctx->gray = gs_cspace_new_ICC(ctx->memory, ctx->pgs, 1); + ctx->cmyk = gs_cspace_new_ICC(ctx->memory, ctx->pgs, 4); + ctx->srgb = gs_cspace_new_ICC(ctx->memory, ctx->pgs, 3); + ctx->scrgb = gs_cspace_new_ICC(ctx->memory, ctx->pgs, 3); instance->pre_page_action = 0; instance->pre_page_closure = 0; |