summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2012-02-21 11:30:58 -0800
committerChris Liddell <chris.liddell@artifex.com>2012-03-15 11:54:23 +0000
commit902c99cc0c9032bf269c60da048542adfdb9be66 (patch)
tree7e3e698e86d1973eda682a165250758e507b3a11
parent2b3234a84fc41b6bb3b9743f820a2606141b38b6 (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.c40
-rw-r--r--gs/base/gscspace.h2
-rw-r--r--gs/base/gxblend.c2
-rw-r--r--xps/ghostxps.h1
-rw-r--r--xps/xpsgradient.c51
-rw-r--r--xps/xpsimage.c3
-rw-r--r--xps/xpsopacity.c5
-rw-r--r--xps/xpspage.c8
-rw-r--r--xps/xpstop.c9
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(&params);
{
- 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(&params);
{
- 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(&params, TRANSPARENCY_MASK_Luminosity);
gs_begin_transparency_mask(ctx->pgs, &params, &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(&params, TRANSPARENCY_MASK_Luminosity);
gs_begin_transparency_mask(ctx->pgs, &params, &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;