summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base/gdevdflt.c1
-rw-r--r--base/gdevp14.c2420
-rw-r--r--base/gdevp14.h42
-rw-r--r--base/gsicc_cache.c6
-rw-r--r--base/gstparam.h6
-rw-r--r--base/gstrans.c41
-rw-r--r--base/gstrans.h4
-rw-r--r--base/gxblend.h4
-rw-r--r--base/gxblend1.c264
-rw-r--r--base/gxdevsop.h7
-rw-r--r--devices/devs.mak2
-rw-r--r--devices/gdevpng.c17
-rw-r--r--devices/vector/gdevpdft.c2
13 files changed, 1681 insertions, 1135 deletions
diff --git a/base/gdevdflt.c b/base/gdevdflt.c
index bd0e0c4d3..96b8a8eee 100644
--- a/base/gdevdflt.c
+++ b/base/gdevdflt.c
@@ -1026,6 +1026,7 @@ gx_default_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size)
case gxdso_supports_saved_pages:
case gxdso_needs_invariant_palette:
case gxdso_supports_iccpostrender:
+ case gxdso_supports_alpha:
return 0;
case gxdso_pattern_shfill_doesnt_need_path:
return (dev_proc(pdev, fill_path) == gx_default_fill_path);
diff --git a/base/gdevp14.c b/base/gdevp14.c
index 30cca0e69..4bddb116a 100644
--- a/base/gdevp14.c
+++ b/base/gdevp14.c
@@ -135,13 +135,13 @@ static void pdf14_debug_mask_stack_state(pdf14_ctx *ctx);
gs_private_st_ptrs7(st_pdf14_buf, pdf14_buf, "pdf14_buf",
pdf14_buf_enum_ptrs, pdf14_buf_reloc_ptrs,
saved, data, backdrop, transfer_fn, mask_stack,
- matte, parent_color_info);
+ matte, group_color_info);
-gs_private_st_ptrs2(st_pdf14_ctx, pdf14_ctx, "pdf14_ctx",
+gs_private_st_ptrs3(st_pdf14_ctx, pdf14_ctx, "pdf14_ctx",
pdf14_ctx_enum_ptrs, pdf14_ctx_reloc_ptrs,
- stack, mask_stack);
+ stack, mask_stack, base_color);
-gs_private_st_ptrs1(st_pdf14_clr, pdf14_parent_color_t, "pdf14_clr",
+gs_private_st_ptrs1(st_pdf14_clr, pdf14_group_color_t, "pdf14_clr",
pdf14_clr_enum_ptrs, pdf14_clr_reloc_ptrs, previous);
gs_private_st_ptrs2(st_pdf14_mask, pdf14_mask_t, "pdf_mask",
@@ -341,23 +341,21 @@ static int pdf14_cmykspot_put_image(gx_device * dev, gs_gstate * pgs,
static int pdf14_custom_put_image(gx_device * dev, gs_gstate * pgs,
gx_device * target);
-/* Used to alter device color mapping procs based upon group or softmask color space */
-static int pdf14_update_device_color_procs(gx_device *dev,
+/* Alter pdf14 device color model based upon group or softmask. This occurs
+ post clist or in immediate rendering case. Data stored with buffer */
+static pdf14_group_color_t* pdf14_push_color_model(gx_device *dev,
gs_transparency_color_t group_color, int64_t icc_hashcode,
- gs_gstate *pgs, cmm_profile_t *iccprofile, bool is_mask);
+ cmm_profile_t *iccprofile, bool is_mask);
+static void pdf14_pop_color_model(gx_device* dev, pdf14_group_color_t* group_color);
-/* Used to alter device color mapping procs based upon group or softmask color space */
-/* Uses color procs stack so that it can be used with clist writer */
-static int
-pdf14_update_device_color_procs_push_c(gx_device *dev,
- gs_transparency_color_t group_color, int64_t icc_hashcode,
- gs_gstate *pgs, cmm_profile_t *iccprofile, bool is_mask);
-
-static int
-pdf14_update_device_color_procs_pop_c(gx_device *dev,gs_gstate *pgs);
+/* Alter clist writer device color model based upon group or softmask. Data
+ stored in the device color model stack */
+static int pdf14_clist_push_color_model(gx_device* dev, gx_device* cdev, gs_gstate* pgs,
+ const gs_pdf14trans_t* pdf14pct, gs_memory_t* mem, bool is_mask);
+static int pdf14_clist_pop_color_model(gx_device* dev, gs_gstate* pgs);
-static void pdf14_push_parent_color(gx_device *dev, const gs_gstate *pgs);
-static void pdf14_pop_parent_color(gx_device *dev, const gs_gstate *pgs);
+/* Used for cleaning up the stack if things go wrong */
+static void pdf14_pop_group_color(gx_device *dev, const gs_gstate *pgs);
static const pdf14_procs_t gray_pdf14_procs = {
pdf14_unpack_additive,
@@ -775,7 +773,7 @@ ENUM_PTRS_WITH(pdf14_device_enum_ptrs, pdf14_device *pdev)
return 0;
}
case 0: return ENUM_OBJ(pdev->ctx);
-case 1: return ENUM_OBJ(pdev->trans_group_parent_cmap_procs);
+case 1: return ENUM_OBJ(pdev->color_model_stack);
case 2: return ENUM_OBJ(pdev->smaskcolor);
case 3: ENUM_RETURN(gx_device_enum_ptr(pdev->target));
case 4: ENUM_RETURN(gx_device_enum_ptr(pdev->pclist_device));
@@ -792,7 +790,7 @@ static RELOC_PTRS_WITH(pdf14_device_reloc_ptrs, pdf14_device *pdev)
}
RELOC_VAR(pdev->ctx);
RELOC_VAR(pdev->smaskcolor);
- RELOC_VAR(pdev->trans_group_parent_cmap_procs);
+ RELOC_VAR(pdev->color_model_stack);
pdev->target = gx_device_reloc_ptr(pdev->target, gcst);
pdev->pclist_device = gx_device_reloc_ptr(pdev->pclist_device, gcst);
}
@@ -889,12 +887,13 @@ resolve_matte(pdf14_buf *maskbuf, byte *src_data, int src_planestride, int src_r
need to do the offset to our data in the buffer. Bug 700686: If we are in
a softmask that includes a matte entry, then we need to undo the matte
entry here at this time in the image's native color space not the parent
- color space. */
+ color space. The big_endian term here is only set to true if the data
+ has been baked as such during the put_image blending operation. */
static forceinline pdf14_buf*
template_transform_color_buffer(gs_gstate *pgs, pdf14_ctx *ctx, gx_device *dev,
pdf14_buf *src_buf, byte *src_data, cmm_profile_t *src_profile,
cmm_profile_t *des_profile, int x0, int y0, int width, int height, bool *did_alloc,
- bool has_matte, bool deep)
+ bool has_matte, bool deep, bool big_endian)
{
gsicc_rendering_param_t rendering_params;
gsicc_link_t *icc_link;
@@ -970,6 +969,11 @@ template_transform_color_buffer(gs_gstate *pgs, pdf14_ctx *ctx, gx_device *dev,
gsicc_init_buffer(&des_buff_desc, des_profile->num_comps, 1<<deep, false,
false, true, des_planestride, des_rowstride, height, width);
+ if (big_endian) {
+ src_buff_desc.little_endian = false;
+ des_buff_desc.little_endian = false;
+ }
+
/* If we have a matte entry, undo the pre-blending now. Also set pdf14
context to ensure that this is not done again during the group
composition */
@@ -1040,28 +1044,28 @@ static pdf14_buf*
pdf14_transform_color_buffer_no_matte(gs_gstate *pgs, pdf14_ctx *ctx, gx_device *dev,
pdf14_buf *src_buf, byte *src_data, cmm_profile_t *src_profile,
cmm_profile_t *des_profile, int x0, int y0, int width, int height, bool *did_alloc,
- bool deep)
+ bool deep, bool big_endian)
{
if (deep)
return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile,
- des_profile, x0, y0, width, height, did_alloc, false, true);
+ des_profile, x0, y0, width, height, did_alloc, false, true, big_endian);
else
return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile,
- des_profile, x0, y0, width, height, did_alloc, false, false);
+ des_profile, x0, y0, width, height, did_alloc, false, false, big_endian);
}
static pdf14_buf*
pdf14_transform_color_buffer_with_matte(gs_gstate *pgs, pdf14_ctx *ctx, gx_device *dev,
pdf14_buf *src_buf, byte *src_data, cmm_profile_t *src_profile,
cmm_profile_t *des_profile, int x0, int y0, int width, int height, bool *did_alloc,
- bool deep)
+ bool deep, bool big_endian)
{
if (deep)
return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile,
- des_profile, x0, y0, width, height, did_alloc, true, true);
+ des_profile, x0, y0, width, height, did_alloc, true, true, big_endian);
else
return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile,
- des_profile, x0, y0, width, height, did_alloc, true, false);
+ des_profile, x0, y0, width, height, did_alloc, true, false, big_endian);
}
/**
@@ -1082,7 +1086,6 @@ pdf14_buf_new(gs_int_rect *rect, bool has_tags, bool has_alpha_g,
/* yet another plane */
pdf14_buf *result;
- pdf14_parent_color_t *new_parent_color;
int rowstride = ((rect->q.x - rect->p.x + 3) & -4)<<deep;
int height = (rect->q.y - rect->p.y);
int n_planes = n_chan + (has_shape ? 1 : 0) + (has_alpha_g ? 1 : 0) +
@@ -1120,21 +1123,9 @@ pdf14_buf_new(gs_int_rect *rect, bool has_tags, bool has_alpha_g,
result->num_spots = num_spots;
result->deep = deep;
result->page_group = false;
- new_parent_color = gs_alloc_struct(memory, pdf14_parent_color_t, &st_pdf14_clr,
- "pdf14_buf_new");
- if (new_parent_color == NULL) {
- gs_free_object(memory, result, "pdf14_buf_new");
- return NULL;
- }
+ result->group_color_info = NULL;
+ result->group_popped = false;
- result->parent_color_info = new_parent_color;
- result->parent_color_info->get_cmap_procs = NULL;
- result->parent_color_info->parent_color_mapping_procs = NULL;
- result->parent_color_info->parent_color_comp_index = NULL;
- result->parent_color_info->icc_profile = NULL;
- result->parent_color_info->previous = NULL;
- result->parent_color_info->encode = NULL;
- result->parent_color_info->decode = NULL;
if (idle || height <= 0) {
/* Empty clipping - will skip all drawings. */
result->planestride = 0;
@@ -1173,7 +1164,7 @@ pdf14_buf_new(gs_int_rect *rect, bool has_tags, bool has_alpha_g,
static void
pdf14_buf_free(pdf14_buf *buf)
{
- pdf14_parent_color_t *old_parent_color_info = buf->parent_color_info;
+ pdf14_group_color_t *group_color_info = buf->group_color_info;
gs_memory_t *memory = buf->memory;
if (buf->mask_stack && buf->mask_stack->rc_mask)
@@ -1184,13 +1175,13 @@ pdf14_buf_free(pdf14_buf *buf)
gs_free_object(memory, buf->matte, "pdf14_buf_free");
gs_free_object(memory, buf->data, "pdf14_buf_free");
- while (old_parent_color_info) {
- if (old_parent_color_info->icc_profile != NULL) {
- gsicc_adjust_profile_rc(old_parent_color_info->icc_profile, -1, "pdf14_buf_free");
+ while (group_color_info) {
+ if (group_color_info->icc_profile != NULL) {
+ gsicc_adjust_profile_rc(group_color_info->icc_profile, -1, "pdf14_buf_free");
}
- buf->parent_color_info = old_parent_color_info->previous;
- gs_free_object(memory, old_parent_color_info, "pdf14_buf_free");
- old_parent_color_info = buf->parent_color_info;
+ buf->group_color_info = group_color_info->previous;
+ gs_free_object(memory, group_color_info, "pdf14_buf_free");
+ group_color_info = buf->group_color_info;
}
gs_free_object(memory, buf->backdrop, "pdf14_buf_free");
@@ -1216,63 +1207,31 @@ pdf14_rcmask_new(gs_memory_t *memory)
result = gs_alloc_struct(memory, pdf14_rcmask_t, &st_pdf14_rcmask,
"pdf14_maskbuf_new");
- if ( result == NULL )
- return(NULL);
+ if (result == NULL)
+ return NULL;
rc_init_free(result, memory, 1, rc_pdf14_maskbuf_free);
result->mask_buf = NULL;
result->memory = memory;
- return(result);
+ return result;
}
static pdf14_ctx *
-pdf14_ctx_new(gs_int_rect *rect, int n_chan, bool additive, gx_device *dev, bool deep)
+pdf14_ctx_new(gx_device *dev, bool deep)
{
pdf14_ctx *result;
- pdf14_buf *buf;
gs_memory_t *memory = dev->memory->stable_memory;
- bool has_tags = device_encodes_tags(dev);
- pdf14_device *pdev = (pdf14_device *)dev;
- int num_spots;
-
+
result = gs_alloc_struct(memory, pdf14_ctx, &st_pdf14_ctx, "pdf14_ctx_new");
if (result == NULL)
return result;
- /* Note: buffer creation expects alpha to be in number of channels */
- /* Old code here used num_spots = pdev->devn_params.page_spot_colors,
- * but this fails for devices like psdcmykog, which does not expand
- * to take on new spot colors, over and above the 2 it has built in.
- * Accordingly, we calculate the number of spot colors to be the
- * number of channels we've been asked for, less the number of
- * 'standard' colorants. */
- num_spots = n_chan - pdev->num_std_colorants;
- buf = pdf14_buf_new(rect, has_tags, false, false, false, n_chan + 1,
- num_spots, memory, deep);
- if (buf == NULL) {
- gs_free_object(memory, result, "pdf14_ctx_new");
- return NULL;
- }
- if_debug5m('v', memory,
- "[v]base buf: %d x %d, %d color channels, %d planes, deep=%d\n",
- buf->rect.q.x, buf->rect.q.y, buf->n_chan, buf->n_planes, deep);
- if (buf->data != NULL) {
- /* Memsetting by 0, so this copes with the deep case too */
- if (buf->has_tags) {
- memset(buf->data, 0, buf->planestride * (buf->n_planes-1));
- } else {
- memset(buf->data, 0, buf->planestride * buf->n_planes);
- }
- }
- buf->saved = NULL;
- result->stack = buf;
+ result->stack = NULL;
result->mask_stack = pdf14_mask_element_new(memory);
result->mask_stack->rc_mask = pdf14_rcmask_new(memory);
- result->n_chan = n_chan;
result->memory = memory;
- result->rect = *rect;
- result->additive = additive;
result->smask_depth = 0;
result->smask_blend = false;
result->deep = deep;
+ result->base_color = NULL;
return result;
}
@@ -1281,10 +1240,14 @@ pdf14_ctx_free(pdf14_ctx *ctx)
{
pdf14_buf *buf, *next;
+ if (ctx->base_color) {
+ gsicc_adjust_profile_rc(ctx->base_color->icc_profile, -1, "pdf14_ctx_free");
+ gs_free_object(ctx->memory, ctx->base_color, "pdf14_ctx_free");
+ }
if (ctx->mask_stack) {
/* A mask was created but was not used in this band. */
rc_decrement(ctx->mask_stack->rc_mask, "pdf14_ctx_free");
- gs_free_object(ctx->memory,ctx->mask_stack,"pdf14_ctx_free");
+ gs_free_object(ctx->memory, ctx->mask_stack, "pdf14_ctx_free");
}
for (buf = ctx->stack; buf != NULL; buf = next) {
next = buf->saved;
@@ -1333,44 +1296,182 @@ pdf14_find_backdrop_buf(pdf14_ctx *ctx, bool *is_backdrop)
return NULL;
}
+static pdf14_group_color_t*
+pdf14_make_base_group_color(gx_device* dev)
+{
+ pdf14_device* pdev = (pdf14_device*)dev;
+ pdf14_group_color_t* group_color;
+ bool deep = pdev->ctx->deep;
+
+ if_debug0m('v', dev->memory, "[v]pdf14_make_base_group_color\n");
+
+ group_color = gs_alloc_struct(pdev->ctx->memory,
+ pdf14_group_color_t, &st_pdf14_clr,
+ "pdf14_make_base_group_color");
+
+ if (group_color == NULL)
+ return NULL;
+ memset(group_color, 0, sizeof(pdf14_group_color_t));
+
+ group_color->blend_procs = pdev->blend_procs;
+ group_color->polarity = pdev->color_info.polarity;
+ group_color->num_components = pdev->color_info.num_components;
+ group_color->isadditive = pdev->ctx->additive;
+ group_color->unpack_procs = pdev->pdf14_procs;
+ group_color->max_color = pdev->color_info.max_color = deep ? 65535 : 255;
+ group_color->max_gray = pdev->color_info.max_gray = deep ? 65535 : 255;
+ group_color->depth = pdev->color_info.depth;
+ group_color->decode = dev_proc(pdev, decode_color);
+ group_color->encode = dev_proc(pdev, encode_color);
+ group_color->group_color_mapping_procs = dev_proc(pdev, get_color_mapping_procs);
+ group_color->group_color_comp_index = dev_proc(pdev, get_color_comp_index);
+ memcpy(&(group_color->comp_bits), &(pdev->color_info.comp_bits),
+ GX_DEVICE_COLOR_MAX_COMPONENTS);
+ memcpy(&(group_color->comp_shift), &(pdev->color_info.comp_shift),
+ GX_DEVICE_COLOR_MAX_COMPONENTS);
+ group_color->get_cmap_procs = pdf14_get_cmap_procs;
+ group_color->icc_profile = pdev->icc_struct->device_profile[0];
+ gsicc_adjust_profile_rc(group_color->icc_profile, 1, "pdf14_make_base_group_color");
+
+ return group_color;
+}
+
+/* This wil create the first buffer when we have
+ either the first drawing operation or transparency
+ group push. At that time, the color space in which
+ we are going to be doing the alpha blend will be known. */
+static int
+pdf14_initialize_ctx(gx_device* dev, int n_chan, bool additive, const gs_gstate* pgs)
+{
+ pdf14_device* pdev = (pdf14_device*)dev;
+ bool has_tags = device_encodes_tags(dev);
+ int num_spots = pdev->ctx->num_spots;
+ pdf14_buf* buf;
+ gs_memory_t* memory = dev->memory->stable_memory;
+
+ /* Check for a blank idle group as a base group */
+ if (pdev->ctx->stack != NULL && pdev->ctx->stack->group_popped &&
+ pdev->ctx->stack->idle) {
+ pdf14_buf_free(pdev->ctx->stack);
+ pdev->ctx->stack = NULL;
+ }
+
+ if (pdev->ctx->stack != NULL)
+ return 0;
+
+ if_debug2m('v', dev->memory, "[v]pdf14_initialize_ctx: width = %d, height = %d\n",
+ dev->width, dev->height);
+
+ buf = pdf14_buf_new(&(pdev->ctx->rect), has_tags, false, false, false, n_chan + 1,
+ num_spots, memory, pdev->ctx->deep);
+ if (buf == NULL) {
+ return gs_error_VMerror;
+ }
+ if_debug5m('v', memory,
+ "[v]base buf: %d x %d, %d color channels, %d planes, deep=%d\n",
+ buf->rect.q.x, buf->rect.q.y, buf->n_chan, buf->n_planes, pdev->ctx->deep);
+
+ /* This check is not really needed */
+ if (buf->data != NULL) {
+ /* Memsetting by 0, so this copes with the deep case too */
+ if (buf->has_tags) {
+ memset(buf->data, 0, buf->planestride * (buf->n_planes - 1));
+ }
+ else {
+ memset(buf->data, 0, buf->planestride * buf->n_planes);
+ }
+ }
+ buf->saved = NULL;
+ pdev->ctx->stack = buf;
+ pdev->ctx->n_chan = n_chan;
+ pdev->ctx->additive = additive;
+
+ /* Every buffer needs group color information including the base
+ one that is created for when we have no group */
+ buf->group_color_info = gs_alloc_struct(pdev->memory->stable_memory,
+ pdf14_group_color_t, &st_pdf14_clr, "pdf14_initialize_ctx");
+ if (buf->group_color_info == NULL)
+ return gs_error_VMerror;
+
+ if (pgs != NULL)
+ buf->group_color_info->get_cmap_procs = pgs->get_cmap_procs;
+ else
+ buf->group_color_info->get_cmap_procs = pdf14_get_cmap_procs;
+
+ buf->group_color_info->group_color_mapping_procs =
+ dev_proc(pdev, get_color_mapping_procs);
+ buf->group_color_info->group_color_comp_index =
+ dev_proc(pdev, get_color_comp_index);
+ buf->group_color_info->blend_procs = pdev->blend_procs;
+ buf->group_color_info->polarity = pdev->color_info.polarity;
+ buf->group_color_info->num_components = pdev->color_info.num_components;
+ buf->group_color_info->isadditive = pdev->ctx->additive;
+ buf->group_color_info->unpack_procs = pdev->pdf14_procs;
+ buf->group_color_info->depth = pdev->color_info.depth;
+ buf->group_color_info->max_color = pdev->color_info.max_color;
+ buf->group_color_info->max_gray = pdev->color_info.max_gray;
+ buf->group_color_info->encode = dev_proc(pdev, encode_color);
+ buf->group_color_info->decode = dev_proc(pdev, decode_color);
+ memcpy(&(buf->group_color_info->comp_bits), &(pdev->color_info.comp_bits),
+ GX_DEVICE_COLOR_MAX_COMPONENTS);
+ memcpy(&(buf->group_color_info->comp_shift), &(pdev->color_info.comp_shift),
+ GX_DEVICE_COLOR_MAX_COMPONENTS);
+ buf->group_color_info->previous = NULL; /* used during clist writing */
+ buf->group_color_info->icc_profile = pdev->icc_struct->device_profile[0];
+ if (buf->group_color_info->icc_profile != NULL)
+ gsicc_adjust_profile_rc(buf->group_color_info->icc_profile, 1, "pdf14_initialize_ctx");
+
+ return 0;
+}
+
+static pdf14_group_color_t*
+pdf14_clone_group_color_info(gx_device* pdev, pdf14_group_color_t* src)
+{
+ pdf14_group_color_t* des = gs_alloc_struct(pdev->memory->stable_memory,
+ pdf14_group_color_t, &st_pdf14_clr, "pdf14_clone_group_color_info");
+ if (des == NULL)
+ return NULL;
+
+ memcpy(des, src, sizeof(pdf14_group_color_t));
+ if (des->icc_profile != NULL)
+ gsicc_adjust_profile_rc(des->icc_profile, 1, "pdf14_clone_group_color_info");
+ des->previous = NULL; /* used during clist writing for state stack */
+
+ return des;
+}
+
static int
pdf14_push_transparency_group(pdf14_ctx *ctx, gs_int_rect *rect, bool isolated,
bool knockout, uint16_t alpha, uint16_t shape, uint16_t opacity,
gs_blend_mode_t blend_mode, bool idle, uint mask_id,
- int numcomps, bool cm_back_drop,
- cmm_profile_t *group_profile,
- cmm_profile_t *tos_profile, gs_gstate *pgs,
+ int numcomps, bool cm_back_drop, bool shade_group,
+ cmm_profile_t *group_profile, cmm_profile_t *tos_profile,
+ pdf14_group_color_t* group_color, gs_gstate *pgs,
gx_device *dev)
{
pdf14_buf *tos = ctx->stack;
pdf14_buf *buf, * pdf14_backdrop;
- bool has_shape, has_tags, is_backdrop;
+ bool has_shape = false;
+ bool is_backdrop;
+ int num_spots;
if_debug1m('v', ctx->memory,
"[v]pdf14_push_transparency_group, idle = %d\n", idle);
- /* We are going to use the shape in the knockout computation. If previous
- buffer has a shape or if this is a knockout then we will have a shape here */
- has_shape = tos->has_shape || tos->knockout;
- /* If previous buffer has tags, then add tags here */
- has_tags = tos->has_tags;
+ if (tos != NULL)
+ has_shape = tos->has_shape || tos->knockout;
- /* If the group is NOT isolated we add in the alpha_g plane. This enables
- recompositing to be performed ala art_pdf_recomposite_group_8 so that
- the backdrop is only included one time in the computation.
+ if (ctx->smask_depth > 0)
+ num_spots = 0;
+ else
+ num_spots = ctx->num_spots;
- For shape and alpha, backdrop removal is accomplished by maintaining
- two sets of variables to hold the accumulated values. The group shape
- and alpha, f_g and alpha_g, accumulate only the shape and alpha of the group
- elements, excluding the group backdrop.
- */
- /* Order of buffer data is color data, followed by alpha channel, followed by
- shape (if present), then alpha_g (if present), then tags (if present) */
- buf = pdf14_buf_new(rect, has_tags, !isolated, has_shape, idle, numcomps + 1,
- tos->num_spots, ctx->memory, ctx->deep);
+ buf = pdf14_buf_new(rect, ctx->has_tags, !isolated, has_shape, idle, numcomps + 1,
+ num_spots, ctx->memory, ctx->deep);
if (buf == NULL)
return_error(gs_error_VMerror);
+
if_debug4m('v', ctx->memory,
"[v]base buf: %d x %d, %d color channels, %d planes\n",
buf->rect.q.x, buf->rect.q.y, buf->n_chan, buf->n_planes);
@@ -1386,8 +1487,9 @@ pdf14_push_transparency_group(pdf14_ctx *ctx, gs_int_rect *rect, bool isolated,
ctx->mask_stack = NULL; /* Clean the mask field for rendering this group.
See pdf14_pop_transparency_group how to handle it. */
buf->saved = tos;
+ buf->group_color_info = group_color;
- if (tos->saved == NULL)
+ if (tos == NULL)
buf->page_group = true;
ctx->stack = buf;
@@ -1469,30 +1571,71 @@ pdf14_pop_transparency_group(gs_gstate *pgs, pdf14_ctx *ctx,
pdf14_buf *maskbuf;
int x0, x1, y0, y1;
int nos_num_color_comp;
- bool icc_match;
+ bool no_icc_match;
pdf14_device *pdev = (pdf14_device *)dev;
bool overprint = pdev->overprint;
gx_color_index drawn_comps = pdev->drawn_comps_stroke | pdev->drawn_comps_fill;
bool has_matte = false;
- if (nos == NULL)
- return_error(gs_error_unknownerror); /* Unmatched group pop */
-
- nos_num_color_comp = nos->parent_color_info->num_components - nos->num_spots;
- tos_num_color_comp = tos_num_color_comp - tos->num_spots;
-
#ifdef DEBUG
pdf14_debug_mask_stack_state(ctx);
#endif
if (mask_stack == NULL) {
maskbuf = NULL;
- } else {
+ }
+ else {
maskbuf = mask_stack->rc_mask->mask_buf;
}
if (maskbuf != NULL && maskbuf->matte != NULL)
has_matte = true;
+ /* Check if this is our last buffer, if yes, there is nothing to
+ compose to. Keep this buffer until we have the put image.
+ If we have another group push, this group must be destroyed.
+ This only occurs sometimes when at clist creation time
+ push_shfill_group occured and nothing was drawn in this group.
+ There is also the complication if we have a softmask. There
+ are two approaches to this problem. Apply the softmask during
+ the put image or handle it now. I choose the later as the
+ put_image code is already way to complicated. */
+ if (nos == NULL && maskbuf == NULL) {
+ tos->group_popped = true;
+ return 0;
+ }
+
+ /* Here is the case with the soft mask. Go ahead and create a new
+ target buffer (nos) with the same color information etc, but blank
+ and go ahead and do the blend with the softmask so that it gets applied. */
+ if (nos == NULL && maskbuf != NULL) {
+ nos = pdf14_buf_new(&(tos->rect), ctx->has_tags, !tos->isolated, tos->has_shape,
+ tos->idle, tos->n_chan, tos->num_spots, ctx->memory, ctx->deep);
+ if (nos == NULL)
+ return gs_error_VMerror;
+
+ if_debug4m('v', ctx->memory,
+ "[v] special buffer for softmask application: %d x %d, %d color channels, %d planes\n",
+ nos->rect.q.x, nos->rect.q.y, nos->n_chan, nos->n_planes);
+
+ nos->dirty = tos->dirty;
+ nos->isolated = tos->isolated;
+ nos->knockout = tos->knockout;
+ nos->alpha = 65535;
+ nos->shape = 65535;
+ nos->opacity = 65535;
+ nos->blend_mode = tos->blend_mode;
+ nos->mask_id = tos->mask_id;
+ nos->group_color_info = pdf14_clone_group_color_info(dev, tos->group_color_info);
+
+ if (nos->data != NULL)
+ memset(nos->data, 0, nos->planestride * (nos->n_chan +
+ (nos->has_shape ? 1 : 0) +
+ (nos->has_alpha_g ? 1 : 0)));
+ }
+
+ nos_num_color_comp = nos->group_color_info->num_components - tos->num_spots;
+ tos_num_color_comp = tos_num_color_comp - tos->num_spots;
+
/* Sanitise the dirty rectangles, in case some of the drawing routines
* have made them overly large. */
rect_intersect(tos->dirty, tos->rect);
@@ -1540,32 +1683,32 @@ pdf14_pop_transparency_group(gs_gstate *pgs, pdf14_ctx *ctx,
operations called in the tile transparency code. Instead we may want to
look at pdf14_begin_transparency_group and pdf14_end_transparency group which
is where all the ICC information is handled. We will return to look at that later */
- if (nos->parent_color_info->icc_profile != NULL) {
- icc_match = (nos->parent_color_info->icc_profile->hashcode !=
+ if (nos->group_color_info->icc_profile != NULL) {
+ no_icc_match = (nos->group_color_info->icc_profile->hashcode !=
curr_icc_profile->hashcode);
} else {
/* Let the other tests make the decision if we need to transform */
- icc_match = false;
+ no_icc_match = false;
}
/* If the color spaces are different and we actually did do a swap of
the procs for color */
- if ((nos->parent_color_info->parent_color_mapping_procs != NULL &&
- nos_num_color_comp != tos_num_color_comp) || icc_match) {
+ if ((nos->group_color_info->group_color_mapping_procs != NULL &&
+ nos_num_color_comp != tos_num_color_comp) || no_icc_match) {
if (x0 < x1 && y0 < y1) {
pdf14_buf *result;
bool did_alloc; /* We don't care here */
if (has_matte) {
result = pdf14_transform_color_buffer_with_matte(pgs, ctx, dev,
- tos, tos->data, curr_icc_profile, nos->parent_color_info->icc_profile,
+ tos, tos->data, curr_icc_profile, nos->group_color_info->icc_profile,
tos->rect.p.x, tos->rect.p.y, tos->rect.q.x - tos->rect.p.x,
- tos->rect.q.y - tos->rect.p.y, &did_alloc, tos->deep);
+ tos->rect.q.y - tos->rect.p.y, &did_alloc, tos->deep, false);
has_matte = false;
} else {
result = pdf14_transform_color_buffer_no_matte(pgs, ctx, dev,
- tos, tos->data, curr_icc_profile, nos->parent_color_info->icc_profile,
+ tos, tos->data, curr_icc_profile, nos->group_color_info->icc_profile,
tos->rect.p.x, tos->rect.p.y, tos->rect.q.x - tos->rect.p.x,
- tos->rect.q.y - tos->rect.p.y, &did_alloc, tos->deep);
+ tos->rect.q.y - tos->rect.p.y, &did_alloc, tos->deep, false);
}
if (result == NULL)
return_error(gs_error_unknownerror); /* transform failed */
@@ -1581,8 +1724,8 @@ pdf14_pop_transparency_group(gs_gstate *pgs, pdf14_ctx *ctx,
#endif
/* compose. never do overprint in this case */
pdf14_compose_group(tos, nos, maskbuf, x0, x1, y0, y1, nos->n_chan,
- nos->parent_color_info->isadditive,
- nos->parent_color_info->parent_blending_procs,
+ nos->group_color_info->isadditive,
+ nos->group_color_info->blend_procs,
has_matte, false, drawn_comps, ctx->memory, dev);
}
} else {
@@ -1620,7 +1763,8 @@ pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect, uint16_t bg_alph
gs_transparency_mask_subtype_t subtype,
int numcomps, int Background_components,
const float Background[], int Matte_components,
- const float Matte[], const float GrayBackground)
+ const float Matte[], const float GrayBackground,
+ pdf14_group_color_t* group_color)
{
pdf14_buf *buf;
int i;
@@ -1630,13 +1774,17 @@ pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect, uint16_t bg_alph
idle, replacing);
ctx->smask_depth += 1;
+ if (ctx->stack == NULL) {
+ return_error(gs_error_VMerror);
+ }
+
/* An optimization to consider is that if the SubType is Alpha
then we really should only be allocating the alpha band and
only draw with that channel. Current architecture makes that
a bit tricky. We need to create this based upon the size of
the color space + an alpha channel. NOT the device size
or the previous ctx size */
- /* A mask doesnt worry about tags */
+ /* A mask doesn't worry about tags */
buf = pdf14_buf_new(rect, false, false, false, idle, numcomps + 1, 0,
ctx->memory, ctx->deep);
if (buf == NULL)
@@ -1650,6 +1798,8 @@ pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect, uint16_t bg_alph
buf->blend_mode = BLEND_MODE_Normal;
buf->transfer_fn = transfer_fn;
buf->matte_num_comps = Matte_components;
+ buf->group_color_info = group_color;
+
if (Matte_components) {
buf->matte = (uint16_t *)gs_alloc_bytes(ctx->memory, Matte_components * sizeof(uint16_t),
"pdf14_push_transparency_mask");
@@ -1684,7 +1834,7 @@ pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect, uint16_t bg_alph
/* Soft Mask related information so we know how to
compute luminosity when we pop the soft mask */
buf->SMask_SubType = subtype;
- if (buf->data != NULL){
+ if (buf->data != NULL) {
/* We need to initialize it to the BC if it existed */
/* According to the spec, the CS has to be the same */
/* If the back ground component is black, then don't bother
@@ -1739,10 +1889,11 @@ static void pdf14_free_mask_stack(pdf14_ctx *ctx, gs_memory_t *memory)
static int
pdf14_pop_transparency_mask(pdf14_ctx *ctx, gs_gstate *pgs, gx_device *dev)
{
- pdf14_buf *tos = ctx->stack;
+ pdf14_buf* tos = ctx->stack;
+ pdf14_buf* nos = tos->saved;
byte *new_data_buf;
int icc_match;
- cmm_profile_t *des_profile = tos->parent_color_info->icc_profile; /* If set, this should be a gray profile */
+ cmm_profile_t *des_profile = nos->group_color_info->icc_profile; /* If set, this should be a gray profile */
cmm_profile_t *src_profile;
gsicc_rendering_param_t rendering_params;
gsicc_link_t *icc_link;
@@ -1756,7 +1907,7 @@ pdf14_pop_transparency_mask(pdf14_ctx *ctx, gs_gstate *pgs, gx_device *dev)
/* icc_match == -1 means old non-icc code.
icc_match == 0 means use icc code
icc_match == 1 mean no conversion needed */
- if ( des_profile != NULL && src_profile != NULL ) {
+ if (des_profile != NULL && src_profile != NULL ) {
icc_match = (des_profile->hashcode == src_profile->hashcode);
} else {
icc_match = -1;
@@ -1838,7 +1989,7 @@ pdf14_pop_transparency_mask(pdf14_ctx *ctx, gs_gstate *pgs, gx_device *dev)
global_index++;
#endif
} else {
- if ( icc_match == 1 || tos->n_chan == 2) {
+ if (icc_match == 1 || tos->n_chan == 2) {
#if RAW_DUMP
/* Dump the current buffer to see what we have. */
dump_raw_buffer(ctx->memory,
@@ -1939,11 +2090,13 @@ pdf14_mask_element_new(gs_memory_t *memory)
result = gs_alloc_struct(memory, pdf14_mask_t, &st_pdf14_mask,
"pdf14_mask_element_new");
+ if (result == NULL)
+ return NULL;
/* Get the reference counted mask */
result->rc_mask = NULL;
result->previous = NULL;
result->memory = memory;
- return(result);
+ return result;
}
static int
@@ -1961,7 +2114,7 @@ pdf14_push_transparency_state(gx_device *dev, gs_gstate *pgs)
/* We need to push the current mask buffer */
/* Allocate a new element for the stack.
Don't do anything if there is no mask present.*/
- if ( ctx->mask_stack != NULL ) {
+ if (ctx->mask_stack != NULL) {
new_mask = pdf14_mask_element_new(ctx->memory);
/* Duplicate and make the link */
new_mask->rc_mask = ctx->mask_stack->rc_mask;
@@ -1972,7 +2125,7 @@ pdf14_push_transparency_state(gx_device *dev, gs_gstate *pgs)
#ifdef DEBUG
pdf14_debug_mask_stack_state(pdev->ctx);
#endif
- return(0);
+ return 0;
}
static int
@@ -2014,25 +2167,25 @@ static int
pdf14_open(gx_device *dev)
{
pdf14_device *pdev = (pdf14_device *)dev;
- gs_int_rect rect;
- if_debug2m('v', dev->memory, "[v]pdf14_open: width = %d, height = %d\n",
- dev->width, dev->height);
- rect.p.x = 0;
- rect.p.y = 0;
- rect.q.x = dev->width;
- rect.q.y = dev->height;
/* If we are reenabling the device dont create a new ctx. Bug 697456 */
if (pdev->ctx == NULL) {
bool has_tags = device_encodes_tags(dev);
int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
dev->color_info.num_components);
- pdev->ctx = pdf14_ctx_new(&rect, dev->color_info.num_components,
- pdev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, dev,
- bits_per_comp > 8);
+ pdev->ctx = pdf14_ctx_new(dev, bits_per_comp > 8);
+ if (pdev->ctx == NULL)
+ return_error(gs_error_VMerror);
+
+ pdev->ctx->rect.p.x = 0;
+ pdev->ctx->rect.p.y = 0;
+ pdev->ctx->rect.q.x = dev->width;
+ pdev->ctx->rect.q.y = dev->height;
+ pdev->ctx->has_tags = has_tags;
+ pdev->ctx->num_spots = pdev->color_info.num_components - pdev->num_std_colorants;
+ pdev->ctx->additive = (pdev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE);
+ pdev->ctx->n_chan = pdev->color_info.num_components;
}
- if (pdev->ctx == NULL)
- return_error(gs_error_VMerror);
pdev->free_devicen = true;
pdev->text_group = PDF14_TEXTGROUP_NO_BT;
return 0;
@@ -2225,12 +2378,65 @@ pdf14_get_buffer_information(const gx_device * dev,
global_index++;
#endif
}
- return(0);
+ return 0;
}
typedef void(*blend_image_row_proc_t) (const byte *gs_restrict buf_ptr,
int planestride, int width, int num_comp, uint16_t bg, byte *gs_restrict linebuf);
+
+static int
+pdf14_put_image_color_convert(const pdf14_device* dev, gs_gstate* pgs, cmm_profile_t* src_profile,
+ cmm_dev_profile_t* dev_target_profile, pdf14_buf** buf,
+ byte** buf_ptr, bool was_blended, int x, int y, int width, int height)
+{
+ pdf14_buf* cm_result = NULL;
+ cmm_profile_t* des_profile;
+ gsicc_rendering_param_t render_cond;
+ bool did_alloc;
+ bool big_endian;
+
+ gsicc_extract_profile(GS_UNKNOWN_TAG, dev_target_profile, &des_profile,
+ &render_cond);
+
+#if RAW_DUMP
+ dump_raw_buffer(dev->ctx->memory,
+ height, width, (*buf)->n_planes, (*buf)->planestride,
+ (*buf)->rowstride, "pdf14_put_image_color_convert_pre", *buf_ptr, (*buf)->deep);
+ global_index++;
+#endif
+
+ /* If we are doing a 16 bit buffer it will be big endian if we have already done the
+ blend, otherwise it will be native endian */
+ if (was_blended && (*buf)->deep) {
+ big_endian = true;
+ } else {
+ big_endian = false;
+ }
+
+ cm_result = pdf14_transform_color_buffer_no_matte(pgs, dev->ctx, (gx_device*) dev, *buf,
+ *buf_ptr, src_profile, des_profile, x, y, width,
+ height, &did_alloc, (*buf)->deep, big_endian);
+
+ if (cm_result == NULL)
+ return_error(gs_error_VMerror);
+
+ /* Update */
+ *buf = cm_result;
+
+ /* Make sure our buf_ptr is pointing to the proper location */
+ if (did_alloc)
+ *buf_ptr = cm_result->data; /* Note the lack of offset */
+
+#if RAW_DUMP
+ dump_raw_buffer(dev->ctx->memory,
+ height, width, (*buf)->n_planes, (*buf)->planestride,
+ (*buf)->rowstride, "pdf14_put_image_color_convert_post", *buf_ptr, (*buf)->deep);
+ global_index++;
+#endif
+ return 0;
+}
+
/**
* pdf14_put_image: Put rendered image to target device.
* @pdev: The PDF 1.4 rendering device.
@@ -2250,27 +2456,42 @@ pdf14_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
gs_image1_t image;
gx_image_enum_common_t *info;
pdf14_buf *buf = pdev->ctx->stack;
- gs_int_rect rect = buf->rect;
+ gs_int_rect rect;
int y;
- int num_comp = buf->n_chan - 1;
+ int num_comp;
byte *linebuf, *linebuf_unaligned;
gs_color_space *pcs;
int x1, y1, width, height;
- byte *buf_ptr, *buf16_ptr = NULL;
+ byte *buf_ptr;
bool data_blended = false;
int num_rows_left;
- gsicc_rendering_param_t render_cond;
- cmm_dev_profile_t *dev_profile;
+ cmm_profile_t* src_profile = NULL;
+ cmm_profile_t* des_profile = NULL;
+ cmm_dev_profile_t *pdf14dev_profile;
cmm_dev_profile_t *dev_target_profile;
- uint16_t bg = pdev->ctx->additive ? 65535 : 0;
+ uint16_t bg;
bool has_tags = device_encodes_tags(dev);
- int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
- dev->color_info.num_components);
bool deep = pdev->ctx->deep;
- bool expand = (!deep && bits_per_comp > 8);
- int planestride = buf->planestride;
- int rowstride = buf->rowstride;
+ int planestride;
+ int rowstride;
blend_image_row_proc_t blend_row;
+ bool color_mismatch = false;
+ bool supports_alpha = false;
+ int i;
+ int alpha_offset, tag_offset;
+ const byte* buf_ptrs[GS_CLIENT_COLOR_MAX_COMPONENTS];
+
+ /* Nothing was ever drawn. */
+ if (buf == NULL)
+ return 0;
+
+ bg = buf->group_color_info->isadditive ? 65535 : 0;
+ src_profile = buf->group_color_info->icc_profile;
+
+ num_comp = buf->n_chan - 1;
+ rect = buf->rect;
+ planestride = buf->planestride;
+ rowstride = buf->rowstride;
/* Make sure that this is the only item on the stack. Fuzzing revealed a
potential problem. Bug 694190 */
@@ -2288,7 +2509,7 @@ pdf14_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
#endif
if (width <= 0 || height <= 0 || buf->data == NULL)
return 0;
- buf_ptr = buf->data + rect.p.y * rowstride + (rect.p.x<<deep);
+ buf_ptr = buf->data + (rect.p.y - buf->rect.p.y) * buf->rowstride + ((rect.p.x - buf->rect.p.x) << deep);
/* Check that target is OK. From fuzzing results the target could have been
destroyed, for e.g if it were a pattern accumulator that was closed
@@ -2300,148 +2521,158 @@ pdf14_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
if (dev_target_profile == NULL)
return gs_throw_code(gs_error_Fatal);
- /* See if the target device can handle the image data directly. If it cannot, then we will need to
- use the begin_typed_image interface, which cannot pass along tag nor
- alpha data to the target device. */
- {
- pdf14_buf *cm_result = NULL;
- int alpha_offset, tag_offset;
- const byte *buf_ptrs[GS_CLIENT_COLOR_MAX_COMPONENTS];
- int i;
+ if (src_profile == NULL) {
+ code = dev_proc(dev, get_profile)(dev, &pdf14dev_profile);
+ if (code < 0) {
+ return code;
+ }
+ src_profile = pdf14dev_profile->device_profile[0];
+ }
- /* If we are using a blending color space, take care of that first */
- if (pdev->using_blend_cs) {
- cmm_profile_t *src_profile;
- cmm_profile_t *des_profile;
- bool did_alloc;
+ /* Check if we have a color conversion issue */
+ if (!(src_profile->hash_is_valid)) {
+ gsicc_get_icc_buff_hash(src_profile->buffer,
+ &(src_profile->hashcode),
+ src_profile->buffer_size);
+ src_profile->hash_is_valid = true;
+ }
- code = dev_proc(dev, get_profile)(dev, &dev_profile);
- if (code < 0) {
- return code;
- }
- gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &src_profile,
- &render_cond);
- gsicc_extract_profile(GS_UNKNOWN_TAG, dev_target_profile, &des_profile,
- &render_cond);
+ des_profile = dev_target_profile->device_profile[0];
+ if (!(des_profile->hash_is_valid)) {
+ gsicc_get_icc_buff_hash(des_profile->buffer,
+ &(des_profile->hashcode),
+ des_profile->buffer_size);
+ des_profile->hash_is_valid = true;
+ }
+
+ if (pdev->using_blend_cs ||
+ des_profile->hashcode != src_profile->hashcode)
+ color_mismatch = true;
+
+ /* Check if target supports alpha */
+ supports_alpha = dev_proc(target, dev_spec_op)(target, gxdso_supports_alpha, NULL, 0);
+ code = 0;
#if RAW_DUMP
- dump_raw_buffer(pdev->ctx->memory,
- height, width, buf->n_planes, planestride,
- rowstride, "pre_blend_cs", buf_ptr, deep);
- global_index++;
+ dump_raw_buffer(pdev->ctx->memory, height, width, buf->n_planes,
+ pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
+ "pre_final_blend", buf_ptr, deep);
#endif
- cm_result = pdf14_transform_color_buffer_no_matte(pgs, pdev->ctx, dev, buf,
- buf_ptr, src_profile, des_profile, rect.p.x, rect.p.y, width,
- height, &did_alloc, buf->deep);
+ /* Note. The logic below will need a little rework if we ever
+ have a device that has tags and alpha support */
+ if (supports_alpha) {
+ if (!color_mismatch) {
+ alpha_offset = num_comp;
+ tag_offset = buf->has_tags ? buf->n_chan : 0;
- if (cm_result == NULL)
- return_error(gs_error_VMerror);
+ for (i = 0; i < buf->n_planes; i++)
+ buf_ptrs[i] = buf_ptr + i * planestride;
+ code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
+ rect.p.x, rect.p.y, width, height,
+ rowstride, alpha_offset,
+ tag_offset);
+ /* Right now code has number of rows written */
+ } else {
+ /* In this case, just color convert and maintain alpha. This is a case
+ where we either either blend in the right color space and have no
+ alpha for the output device or hand back the wrong color space with
+ alpha data. We choose the later. */
+ code = pdf14_put_image_color_convert(pdev, pgs, src_profile,
+ dev_target_profile, &buf, &buf_ptr, false, rect.p.x, rect.p.y,
+ width, height);
+ if (code < 0)
+ return code;
- /* Based upon our transform, do a bit of updating */
- buf = cm_result;
+ /* reset */
+ rowstride = buf->rowstride;
+ planestride = buf->planestride;
num_comp = buf->n_chan - 1;
+ alpha_offset = num_comp;
+ tag_offset = buf->has_tags ? buf->n_chan : 0;
- /* Make sure our buf_ptr is pointing to the proper location */
- if (did_alloc)
- buf_ptr = cm_result->data; /* Note the lack of offset */
+ /* And then out */
+ for (i = 0; i < buf->n_planes; i++)
+ buf_ptrs[i] = buf_ptr + i * planestride;
+ code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
+ rect.p.x, rect.p.y, width, height, rowstride, alpha_offset,
+ tag_offset);
+ /* Right now code has number of rows written */
+ }
+ } else if (has_tags) {
+ /* We are going out to a device that supports tags */
+ if (deep) {
+ gx_blend_image_buffer16(buf_ptr, width, height, rowstride,
+ buf->planestride, num_comp, bg);
+ } else {
+ gx_blend_image_buffer(buf_ptr, width, height, rowstride,
+ buf->planestride, num_comp, bg >> 8);
+ }
+
+#if RAW_DUMP
+ dump_raw_buffer(pdev->ctx->memory, height, width, buf->n_planes,
+ pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
+ "post_final_blend", buf_ptr, deep);
+#endif
+
+ /* Take care of color issues */
+ if (color_mismatch) {
+ /* In this case, just color convert and maintain alpha. This is a case
+ where we either either blend in the right color space and have no
+ alpha for the output device or hand back the wrong color space with
+ alpha data. We choose the later. */
+ code = pdf14_put_image_color_convert(pdev, pgs, src_profile, dev_target_profile,
+ &buf, &buf_ptr, true, rect.p.x, rect.p.y, width, height);
+ if (code < 0)
+ return code;
#if RAW_DUMP
- dump_raw_buffer(pdev->ctx->memory,
- height, width, buf->n_planes, planestride,
- rowstride, "post_blend_cs", buf_ptr, deep);
+ dump_raw_buffer(pdev->ctx->memory, height, width, buf->n_planes,
+ pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
+ "final_color_manage", buf_ptr, deep);
global_index++;
#endif
- /* May need to adjust background value due to color space change */
- if (des_profile->num_comps == 4)
- bg = 0;
- else
- bg = 65535;
}
- alpha_offset = num_comp;
+
+ /* reset */
+ rowstride = buf->rowstride;
+ planestride = buf->planestride;
+ num_comp = buf->n_chan - 1;
+ alpha_offset = 0; /* It is there but this indicates we have done the blend */
tag_offset = buf->has_tags ? buf->n_chan : 0;
- /* See if the target device can handle the data with alpha component */
+ /* And then out */
for (i = 0; i < buf->n_planes; i++)
buf_ptrs[i] = buf_ptr + i * planestride;
code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
- rect.p.x, rect.p.y, width, height,
- rowstride, alpha_offset,
- tag_offset);
- if (code == 0) {
- /* Device could not handle the alpha data. Go ahead and preblend
- now. Note that if we do this, and we end up in the default below,
- we only need to repack in chunky not blend */
-#if RAW_DUMP
- dump_raw_buffer(pdev->ctx->memory,
- height, width, buf->n_planes,
- pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
- "pre_final_blend",buf_ptr,deep);
- global_index++;
-#endif
- if (expand) {
- buf16_ptr = gs_alloc_bytes(pdev->memory,
- planestride * num_comp * 2, "pdf14_put_image");
- gx_blend_image_buffer8to16(buf_ptr, (unsigned short*) buf16_ptr,
- width, height, rowstride, planestride, num_comp, bg>>8);
- planestride = planestride * 2;
- rowstride = rowstride * 2;
- for (i = 0; i < num_comp; i++)
- buf_ptrs[i] = buf16_ptr + i * planestride;
- } else {
- if (deep) {
- gx_blend_image_buffer16(buf_ptr, width, height, rowstride,
- buf->planestride, num_comp, bg);
- } else {
- gx_blend_image_buffer(buf_ptr, width, height, rowstride,
- buf->planestride, num_comp, bg>>8);
- }
-#if RAW_DUMP
- dump_raw_buffer_be(pdev->ctx->memory,
- height, width, buf->n_planes,
- pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
- "post_final_blend", buf_ptr, deep);
- global_index++;
- clist_band_count++;
-#endif
- }
- data_blended = true;
+ rect.p.x, rect.p.y, width, height, rowstride, alpha_offset,
+ tag_offset);
+ /* Right now code has number of rows written */
+
+ }
- /* Try again now with just the tags */
- alpha_offset = 0;
+ /* If code > 0 then put image worked. Let it finish and then exit */
+ if (code > 0) {
+ /* We processed some or all of the rows. Continue until we are done */
+ num_rows_left = height - code;
+ while (num_rows_left > 0) {
code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
- rect.p.x, rect.p.y, width, height,
- rowstride, alpha_offset,
- tag_offset);
- }
- if (code > 0) {
- /* We processed some or all of the rows. Continue until we are done */
- num_rows_left = height - code;
- while (num_rows_left > 0) {
- code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
- rect.p.x, rect.p.y + code, width,
- num_rows_left, rowstride,
- alpha_offset, tag_offset);
- num_rows_left = num_rows_left - code;
- }
- if (buf16_ptr != NULL)
- gs_free_object(pdev->memory, buf16_ptr, "pdf14_put_image");
- return 0;
+ rect.p.x, rect.p.y + code, width,
+ num_rows_left, rowstride,
+ alpha_offset, tag_offset);
+ num_rows_left = num_rows_left - code;
}
+ return 0;
}
- /*
+ /* Target device did not support alpha or tags.
* Set color space in preparation for sending an image.
+ * color conversion will occur after blending with through
+ * the begin typed image work flow.
*/
- if (buf16_ptr != NULL) {
- /* If we ever hit this, then we've laboriously blended the
- * entire image for nothing. Check this doesn't happen in
- * normal use. */
- gs_free_object(pdev->memory, buf16_ptr, "pdf14_put_image");
- }
+
planestride = buf->planestride;
rowstride = buf->rowstride;
-
code = gs_cspace_build_ICC(&pcs, NULL, pgs->memory);
if (code < 0)
return code;
@@ -2452,13 +2683,8 @@ pdf14_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
for the pdf14 device to RGB and the target will be CIELAB. In addition,
the case when we have a blend color space that is different than the
target device color space */
- code = dev_proc(dev, get_profile)(dev, &dev_profile);
- if (code < 0) {
- rc_decrement_only_cs(pcs, "pdf14_put_image");
- return code;
- }
- gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile,
- &(pcs->cmm_icc_profile_data), &render_cond);
+ pcs->cmm_icc_profile_data = src_profile;
+
/* pcs takes a reference to the profile data it just retrieved. */
gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, 1, "pdf14_put_image");
gsicc_set_icc_range(&(pcs->cmm_icc_profile_data));
@@ -2468,6 +2694,7 @@ pdf14_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
image.Width = width;
image.Height = height;
image.BitsPerComponent = deep ? 16 : 8;
+ image.ColorSpace = pcs;
ctm_only_writable(pgs).xx = (float)width;
ctm_only_writable(pgs).xy = 0;
ctm_only_writable(pgs).yx = 0;
@@ -2556,6 +2783,452 @@ pdf14_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
return code;
}
+/* This is for the case where we have mixture of spots and additive color.
+ For example, RGB + spots or Gray + spots */
+static void
+gx_blend_image_mixed_buffer(byte* buf_ptr, int width, int height, int rowstride,
+ int planestride, int num_comp, int spot_start)
+{
+ int x, y;
+ int position;
+ byte comp, a;
+ int tmp, comp_num;
+
+ for (y = 0; y < height; y++) {
+ position = y * rowstride;
+ for (x = 0; x < width; x++) {
+ a = buf_ptr[position + planestride * num_comp];
+ if ((a + 1) & 0xfe) {
+ a ^= 0xff;
+ for (comp_num = 0; comp_num < spot_start; comp_num++) {
+ comp = buf_ptr[position + planestride * comp_num];
+ tmp = ((0xff - comp) * a) + 0x80;
+ comp += (tmp + (tmp >> 8)) >> 8;
+ buf_ptr[position + planestride * comp_num] = comp;
+ }
+ for (comp_num = spot_start; comp_num < num_comp; comp_num++) {
+ comp = buf_ptr[position + planestride * comp_num];
+ tmp = ((-comp) * a) + 0x80;
+ comp += (tmp + (tmp >> 8)) >> 8;
+ buf_ptr[position + planestride * comp_num] = comp;
+ }
+ } else if (a == 0) {
+ for (comp_num = 0; comp_num < spot_start; comp_num++) {
+ buf_ptr[position + planestride * comp_num] = 0xff;
+ }
+ for (comp_num = spot_start; comp_num < num_comp; comp_num++) {
+ buf_ptr[position + planestride * comp_num] = 0;
+ }
+ }
+ position += 1;
+ }
+ }
+}
+
+static void
+gx_blend_image_mixed_buffer16(byte* buf_ptr_, int width, int height, int rowstride,
+ int planestride, int num_comp, int spot_start)
+{
+ uint16_t* buf_ptr = (uint16_t*)(void*)buf_ptr_;
+ int x, y;
+ int position;
+ int comp, a;
+ int tmp, comp_num;
+
+ /* planestride and rowstride are in bytes, and we want them in shorts */
+ planestride >>= 1;
+ rowstride >>= 1;
+
+ /* Note that the input here is native endian, and the output must be in big endian! */
+ for (y = 0; y < height; y++) {
+ position = y * rowstride;
+ for (x = 0; x < width; x++) {
+ /* composite RGBA (or CMYKA, etc.) pixel with over solid background */
+ a = buf_ptr[position + planestride * num_comp];
+ if (a == 0) {
+ for (comp_num = 0; comp_num < spot_start; comp_num++) {
+ buf_ptr[position + planestride * comp_num] = 0xffff;
+ }
+ for (comp_num = spot_start; comp_num < num_comp; comp_num++) {
+ buf_ptr[position + planestride * comp_num] = 0;
+ }
+ } else if (a == 0xffff) {
+#if ARCH_IS_BIG_ENDIAN
+#else
+ /* Convert from native -> big endian */
+ for (comp_num = 0; comp_num < num_comp; comp_num++) {
+ comp = buf_ptr[position + planestride * comp_num];
+ ((byte*)&buf_ptr[position + planestride * comp_num])[0] = comp >> 8;
+ ((byte*)&buf_ptr[position + planestride * comp_num])[1] = comp;
+ }
+#endif
+ } else {
+ a ^= 0xffff;
+ a += a >> 15; /* a is now 0 to 0x10000 */
+ a >>= 1; /* We can only use 15 bits as bg-comp has a sign bit we can't lose */
+ for (comp_num = 0; comp_num < spot_start; comp_num++) {
+ comp = buf_ptr[position + planestride * comp_num];
+ tmp = ((0xffff - comp) * a) + 0x4000;
+ comp += (tmp >> 15); /* Errors in bit 16 upwards will be ignored */
+ /* Store as big endian */
+ ((byte*)&buf_ptr[position + planestride * comp_num])[0] = comp >> 8;
+ ((byte*)&buf_ptr[position + planestride * comp_num])[1] = comp;
+ }
+ for (comp_num = spot_start; comp_num < num_comp; comp_num++) {
+ comp = buf_ptr[position + planestride * comp_num];
+ tmp = ((0 - comp) * a) + 0x4000;
+ comp += (tmp >> 15); /* Errors in bit 16 upwards will be ignored */
+ /* Store as big endian */
+ ((byte*)&buf_ptr[position + planestride * comp_num])[0] = comp >> 8;
+ ((byte*)&buf_ptr[position + planestride * comp_num])[1] = comp;
+ }
+ }
+ position += 1;
+ }
+ }
+}
+
+static int
+pdf14_put_blended_image_cmykspot(gx_device* dev, gx_device* target,
+ gs_gstate* pgs, pdf14_buf* buf, int planestride_in,
+ int rowstride_in, int x0, int y0, int width, int height,
+ int num_comp, uint16_t bg, bool has_tags, gs_int_rect rect_in,
+ gs_separations* pseparations, bool deep)
+{
+ const pdf14_device* pdev = (pdf14_device*)dev;
+ int code = 0;
+ int x, y, tmp, comp_num, output_comp_num;
+ gx_color_index color;
+ gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
+ gx_color_value comp;
+ int input_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
+ int output_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
+ int num_known_comp = 0;
+ int output_num_comp = target->color_info.num_components;
+ int num_sep = pseparations->num_separations++;
+ int num_rows_left;
+ int i;
+ gx_drawing_color pdcolor;
+ gs_int_rect rect = rect_in;
+ gs_fixed_rect rect_fixed;
+ int planestride = planestride_in;
+ int rowstride = rowstride_in;
+ byte* buf_ptr = NULL;
+ cmm_profile_t* src_profile = buf->group_color_info->icc_profile;
+ cmm_profile_t* des_profile = NULL;
+ cmm_dev_profile_t* dev_target_profile;
+ cmm_dev_profile_t* pdf14dev_profile;
+ bool color_mismatch = false;
+ bool supports_alpha = false;
+ const byte* buf_ptrs[GS_CLIENT_COLOR_MAX_COMPONENTS];
+ int alpha_offset = num_comp;
+ int tag_offset = has_tags ? num_comp + 1 : 0;
+
+ /*
+ * The process color model for the PDF 1.4 compositor device is CMYK plus
+ * spot colors. The target device may have only some of these colorants due
+ * to the SeparationOrder device parameter. Thus we need to determine the
+ * mapping between the PDF 1.4 compositor and the target device. Note:
+ * There should not be a spot colorant in the PDF 1.4 device that is not
+ * present in the target device.
+ */
+ /* Check if target processes CMYK colorants. */
+ for (comp_num = 0; comp_num < 4; comp_num++) {
+ const char* pcomp_name = (const char*)DeviceCMYKComponents[comp_num];
+
+ output_comp_num = dev_proc(target, get_color_comp_index)
+ (target, pcomp_name, strlen(pcomp_name), NO_COMP_NAME_TYPE);
+ if (output_comp_num >= 0 &&
+ output_comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS) {
+ output_map[num_known_comp] = output_comp_num;
+ input_map[num_known_comp++] = comp_num;
+ }
+ }
+ /* Check if target processes our spot colorants. */
+ for (comp_num = 0; comp_num < num_sep; comp_num++) {
+ output_comp_num = dev_proc(target, get_color_comp_index)
+ (target, (const char*)(pseparations->names[comp_num].data),
+ pseparations->names[comp_num].size, NO_COMP_NAME_TYPE);
+ if (output_comp_num >= 0 &&
+ output_comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS) {
+ output_map[num_known_comp] = output_comp_num;
+ input_map[num_known_comp++] = comp_num + 4;
+ }
+ }
+
+ /* Check if group color space is CMYK based */
+ code = dev_proc(target, get_profile)(target, &dev_target_profile);
+ if (code < 0)
+ return code;
+ if (dev_target_profile == NULL)
+ return gs_throw_code(gs_error_Fatal);
+
+ if (src_profile == NULL) {
+ code = dev_proc(dev, get_profile)(dev, &pdf14dev_profile);
+ if (code < 0) {
+ return code;
+ }
+ src_profile = pdf14dev_profile->device_profile[0];
+ }
+
+ /* Check if we have a color conversion issue */
+ if (!(src_profile->hash_is_valid)) {
+ gsicc_get_icc_buff_hash(src_profile->buffer,
+ &(src_profile->hashcode),
+ src_profile->buffer_size);
+ src_profile->hash_is_valid = true;
+ }
+
+ des_profile = dev_target_profile->device_profile[0];
+ if (!(des_profile->hash_is_valid)) {
+ gsicc_get_icc_buff_hash(des_profile->buffer,
+ &(des_profile->hashcode),
+ des_profile->buffer_size);
+ des_profile->hash_is_valid = true;
+ }
+
+ if (pdev->using_blend_cs ||
+ des_profile->hashcode != src_profile->hashcode)
+ color_mismatch = true;
+
+ /* Check if target supports alpha */
+ supports_alpha = dev_proc(target, dev_spec_op)(target, gxdso_supports_alpha, NULL, 0);
+ code = 0;
+
+ buf_ptr = buf->data + (rect.p.y - buf->rect.p.y) * buf->rowstride + ((rect.p.x - buf->rect.p.x) << deep);
+
+ /* Note. The logic below will need a little rework if we ever
+ have a device that has tags and alpha support */
+ if (supports_alpha) {
+ if (!color_mismatch) {
+ for (i = 0; i < buf->n_planes; i++)
+ buf_ptrs[i] = buf_ptr + i * planestride;
+ code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
+ rect.p.x, rect.p.y, width, height,
+ rowstride, alpha_offset, tag_offset);
+ /* Right now code has number of rows written */
+ } else {
+ /* In this case, just color convert and maintain alpha.
+ This is a case where we either either blend in the
+ right color space and have no alpha for the output
+ device or hand back the wrong color space with
+ alpha data. We choose the later. */
+ code = pdf14_put_image_color_convert(pdev, pgs, src_profile,
+ dev_target_profile, &buf, &buf_ptr, false, rect.p.x,
+ rect.p.y, width, height);
+ if (code < 0)
+ return code;
+
+ /* reset */
+ rowstride = buf->rowstride;
+ planestride = buf->planestride;
+ num_comp = buf->n_chan - 1;
+ alpha_offset = num_comp;
+ tag_offset = buf->has_tags ? buf->n_chan : 0;
+
+ /* And then out */
+ for (i = 0; i < buf->n_planes; i++)
+ buf_ptrs[i] = buf_ptr + i * planestride;
+ code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
+ rect.p.x, rect.p.y, width, height, rowstride, alpha_offset,
+ tag_offset);
+ /* Right now code has number of rows written */
+ }
+ } else {
+ /* Device could not handle the alpha data (we actually don't have
+ a device that does spot colorants and has an alpha channel so
+ the above code is untested. Go ahead and
+ preblend now and then color convert if needed */
+#if RAW_DUMP
+ /* Dump before and after the blend to make sure we are doing that ok */
+ dump_raw_buffer(target->memory, height, width, num_comp + 1, planestride, rowstride,
+ "pre_final_blend", buf_ptr, deep);
+ global_index++;
+#endif
+ if (color_mismatch && (src_profile->data_cs == gsRGB || src_profile->data_cs == gsGRAY)) {
+ if (deep) {
+ gx_blend_image_mixed_buffer16(buf_ptr, width, height, rowstride,
+ planestride, num_comp, src_profile->num_comps);
+ } else {
+ gx_blend_image_mixed_buffer(buf_ptr, width, height, rowstride,
+ planestride, num_comp, src_profile->num_comps);
+ }
+ } else {
+ if (deep) {
+ gx_blend_image_buffer16(buf_ptr, width, height, rowstride,
+ planestride, num_comp, bg);
+ } else {
+ gx_blend_image_buffer(buf_ptr, width, height, rowstride,
+ planestride, num_comp, bg >> 8);
+ }
+ }
+
+ if (color_mismatch) {
+ code = pdf14_put_image_color_convert(pdev, pgs, src_profile, dev_target_profile,
+ &buf, &buf_ptr, true, rect.p.x, rect.p.y, width, height);
+ if (code < 0)
+ return code;
+
+ /* reset */
+ rowstride = buf->rowstride;
+ planestride = buf->planestride;
+ num_comp = buf->n_chan - 1;
+ alpha_offset = num_comp;
+ tag_offset = buf->has_tags ? buf->n_chan : 0;
+ }
+
+
+#if RAW_DUMP
+ /* Dump before and after the blend to make sure we are doing that ok */
+ dump_raw_buffer_be(target->memory, height, width, num_comp, planestride, rowstride,
+ "post_final_blend", buf_ptr, deep);
+ global_index++;
+ /* clist_band_count++; */
+#endif
+ /* Try put_image again now */
+ alpha_offset = 0;
+ for (i = 0; i < buf->n_planes; i++)
+ buf_ptrs[i] = buf_ptr + i * planestride;
+ code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
+ rect.p.x, rect.p.y, width, height,
+ rowstride, alpha_offset, tag_offset);
+ }
+ if (code > 0) {
+ /* We processed some or all of the rows. Continue until we are done */
+ num_rows_left = height - code;
+ while (num_rows_left > 0) {
+ code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
+ rect.p.x, rect.p.y + code, width,
+ num_rows_left, rowstride,
+ alpha_offset, tag_offset);
+ if (code < 0) {
+ return code;
+ }
+ num_rows_left = num_rows_left - code;
+ }
+ return 0;
+ }
+
+ /* No put_image working at all. Resort to fill_rect */
+
+ planestride = planestride_in;
+ rowstride = rowstride_in;
+
+ /* Clear all output colorants first */
+ for (comp_num = 0; comp_num < output_num_comp; comp_num++)
+ cv[comp_num] = 0;
+
+ /* Send pixel data to the target device. */
+ if (deep) {
+ /* NOTE: buf_ptr points to big endian data */
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+
+ /* composite CMYKA, etc. pixel with over solid background */
+#define GET16_BE2NATIVE(v) \
+((((byte *)&(v))[0]<<8) | (((byte *)&(v))[1]))
+ uint16_t a = GET16_BE2NATIVE(buf_ptr[x + planestride * num_comp]);
+
+ if (a == 0) {
+ for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+ cv[output_map[comp_num]] = bg;
+ }
+ } else if (a == 0xffff) {
+ for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+ comp = GET16_BE2NATIVE(buf_ptr[x + planestride * input_map[comp_num]]);
+ cv[output_map[comp_num]] = comp;
+ }
+ } else {
+ /* a ^= 0xff; */ /* No inversion here! Bug 689895 */
+ for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+ comp = GET16_BE2NATIVE(buf_ptr[x + planestride * input_map[comp_num]]);
+ tmp = ((comp - bg) * a) + 0x8000;
+ comp += (tmp + (tmp >> 16)) >> 16;
+ cv[output_map[comp_num]] = comp;
+ }
+ }
+
+ /* If we have spot colors we need to encode and fill as a high level
+ color if the device supports it which should always be the case
+ if we are in this procedure */
+ if (dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0)) {
+ for (i = 0; i < output_num_comp; i++) {
+ pdcolor.colors.devn.values[i] = cv[i];
+ }
+ pdcolor.type = gx_dc_type_devn;
+ rect_fixed.p.x = int2fixed(x + x0);
+ rect_fixed.p.y = int2fixed(y + y0);
+ rect_fixed.q.x = int2fixed(x + x0 + 1);
+ rect_fixed.q.y = int2fixed(y + y0 + 1);
+ code = dev_proc(target, fill_rectangle_hl_color)(target, &rect_fixed,
+ NULL, &pdcolor, NULL);
+ } else {
+ /* encode as a color index */
+ color = dev_proc(target, encode_color)(target, cv);
+ code = dev_proc(target, fill_rectangle)(target, x + x0, y + y0, 1, 1, color);
+ }
+ if (code < 0)
+ return code;
+ }
+
+ buf_ptr += rowstride;
+ }
+ } else {
+ bg >>= 8;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+
+ /* composite CMYKA, etc. pixel with over solid background */
+ byte a = buf_ptr[x + planestride * num_comp];
+
+ if ((a + 1) & 0xfe) {
+ /* a ^= 0xff; */ /* No inversion here! Bug 689895 */
+ for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+ comp = buf_ptr[x + planestride * input_map[comp_num]];
+ tmp = ((comp - bg) * a) + 0x80;
+ comp += tmp + (tmp >> 8);
+ cv[output_map[comp_num]] = comp;
+ }
+ } else if (a == 0) {
+ for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+ cv[output_map[comp_num]] = bg;
+ }
+ } else {
+ for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+ comp = buf_ptr[x + planestride * input_map[comp_num]];
+ cv[output_map[comp_num]] = (comp << 8) + comp;
+ }
+ }
+
+ /* If we have spot colors we need to encode and fill as a high level
+ color if the device supports it which should always be the case
+ if we are in this procedure */
+ if (dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0)) {
+ for (i = 0; i < output_num_comp; i++) {
+ pdcolor.colors.devn.values[i] = cv[i];
+ }
+ pdcolor.type = gx_dc_type_devn;
+ rect_fixed.p.x = int2fixed(x + x0);
+ rect_fixed.p.y = int2fixed(y + y0);
+ rect_fixed.q.x = int2fixed(x + x0 + 1);
+ rect_fixed.q.y = int2fixed(y + y0 + 1);
+ code = dev_proc(target, fill_rectangle_hl_color)(target, &rect_fixed,
+ NULL, &pdcolor, NULL);
+ } else {
+ /* encode as a color index */
+ color = dev_proc(target, encode_color)(target, cv);
+ code = dev_proc(target, fill_rectangle)(target, x + x0, y + y0, 1, 1, color);
+ }
+ if (code < 0)
+ return code;
+ }
+
+ buf_ptr += rowstride;
+ }
+ }
+ return code;
+}
+
/**
* pdf14_cmykspot_put_image: Put rendered image to target device.
* @pdev: The PDF 1.4 rendering device.
@@ -2568,20 +3241,29 @@ pdf14_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
* Return code: negative on error.
**/
static int
-pdf14_cmykspot_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
+pdf14_cmykspot_put_image(gx_device *dev, gs_gstate *pgs, gx_device *target)
{
- pdf14_device * pdev = (pdf14_device *)dev;
+ pdf14_device *pdev = (pdf14_device *)dev;
pdf14_buf *buf = pdev->ctx->stack;
- gs_int_rect rect = buf->rect;
+ gs_int_rect rect;
int x1, y1, width, height;
- gs_devn_params * pdevn_params = &pdev->devn_params;
- gs_separations * pseparations = &pdevn_params->separations;
- int planestride = buf->planestride;
- int rowstride = buf->rowstride;
+ gs_devn_params *pdevn_params = &pdev->devn_params;
+ gs_separations *pseparations = &pdevn_params->separations;
+ int planestride;
+ int rowstride;
bool deep = pdev->ctx->deep;
- const uint16_t bg = pdev->ctx->additive ? 65535 : 0;
- int num_comp = buf->n_chan - 1;
- byte *buf_ptr;
+ uint16_t bg;
+ int num_comp;
+
+ /* Nothing was ever drawn. */
+ if (buf == NULL)
+ return 0;
+
+ bg = buf->group_color_info->isadditive ? 65535 : 0;
+ num_comp = buf->n_chan - 1;
+ rect = buf->rect;
+ planestride = buf->planestride;
+ rowstride = buf->rowstride;
/* Make sure that this is the only item on the stack. Fuzzing revealed a
potential problem. Bug 694190 */
@@ -2596,7 +3278,7 @@ pdf14_cmykspot_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
height = y1 - rect.p.y;
if (width <= 0 || height <= 0 || buf->data == NULL)
return 0;
- buf_ptr = buf->data + rect.p.y * buf->rowstride + (rect.p.x<<deep);
+
#if RAW_DUMP
/* Dump the current buffer to see what we have. */
dump_raw_buffer(pdev->ctx->memory,
@@ -2610,7 +3292,9 @@ pdf14_cmykspot_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
global_index++;
clist_band_count++;
#endif
- return gx_put_blended_image_cmykspot(target, buf_ptr, planestride, rowstride,
+
+ return pdf14_put_blended_image_cmykspot(dev, target, pgs,
+ buf, planestride, rowstride,
rect.p.x, rect.p.y, width, height, num_comp, bg,
buf->has_tags, rect, pseparations, deep);
}
@@ -2632,15 +3316,27 @@ pdf14_custom_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
pdf14_device * pdev = (pdf14_device *)dev;
pdf14_buf *buf = pdev->ctx->stack;
bool deep = pdev->ctx->deep;
- gs_int_rect rect = buf->rect;
- int x0 = rect.p.x, y0 = rect.p.y;
- int planestride = buf->planestride;
- int rowstride = buf->rowstride;
- int num_comp = buf->n_chan - 1;
- const uint16_t bg = pdev->ctx->additive ? 0xffff : 0;
+ gs_int_rect rect;
+ int x0, y0;
+ int planestride;
+ int rowstride;
+ int num_comp;
+ uint16_t bg;
int x1, y1, width, height;
byte *buf_ptr;
+ /* Nothing was ever drawn. */
+ if (buf == NULL)
+ return 0;
+
+ bg = pdev->ctx->additive ? 0xffff : 0;
+ num_comp = buf->n_chan - 1;
+ rect = buf->rect;
+ x0 = rect.p.x;
+ y0 = rect.p.y;
+ planestride = buf->planestride;
+ rowstride = buf->rowstride;
+
/* Make sure that this is the only item on the stack. Fuzzing revealed a
potential problem. Bug 694190 */
if (buf->saved != NULL) {
@@ -2654,7 +3350,7 @@ pdf14_custom_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
height = y1 - rect.p.y;
if (width <= 0 || height <= 0 || buf->data == NULL)
return 0;
- buf_ptr = buf->data + rect.p.y * buf->rowstride + (rect.p.x<<deep);
+ buf_ptr = buf->data + (rect.p.y - buf->rect.p.y) * buf->rowstride + ((rect.p.x - buf->rect.p.x)<<deep);
return gx_put_blended_image_custom(target, buf_ptr,
planestride, rowstride,
@@ -2665,16 +3361,16 @@ pdf14_custom_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
* of one or more groups, we have to cycle through any ICC profile changes since the push
* putting everything back how it was, and cleaning up the reference counts.
*/
-static void pdf14_cleanup_parent_color_profiles (pdf14_device *pdev)
+static void pdf14_cleanup_group_color_profiles (pdf14_device *pdev)
{
- if (pdev->ctx) {
+ if (pdev->ctx && pdev->ctx->stack) {
pdf14_buf *buf, *next;
- for (buf = pdev->ctx->stack; buf != NULL; buf = next) {
- pdf14_parent_color_t *old_parent_color_info = buf->parent_color_info;
+ for (buf = pdev->ctx->stack->saved; buf != NULL; buf = next) {
+ pdf14_group_color_t *group_color_info = buf->group_color_info;
next = buf->saved;
- while (old_parent_color_info) {
- if (old_parent_color_info->icc_profile != NULL) {
+ while (group_color_info) {
+ if (group_color_info->icc_profile != NULL) {
cmm_profile_t *group_profile;
gsicc_rendering_param_t render_cond;
cmm_dev_profile_t *dev_profile;
@@ -2685,12 +3381,12 @@ static void pdf14_cleanup_parent_color_profiles (pdf14_device *pdev)
&render_cond);
gsicc_adjust_profile_rc(pdev->icc_struct->device_profile[0], -1, "pdf14_end_transparency_group");
- pdev->icc_struct->device_profile[0] = old_parent_color_info->icc_profile;
- old_parent_color_info->icc_profile = NULL;
+ pdev->icc_struct->device_profile[0] = group_color_info->icc_profile;
+ group_color_info->icc_profile = NULL;
}
}
- old_parent_color_info = old_parent_color_info->previous;
+ group_color_info = group_color_info->previous;
}
}
}
@@ -2701,7 +3397,7 @@ pdf14_close(gx_device *dev)
{
pdf14_device *pdev = (pdf14_device *)dev;
- pdf14_cleanup_parent_color_profiles (pdev);
+ pdf14_cleanup_group_color_profiles(pdev);
if (pdev->ctx) {
pdf14_ctx_free(pdev->ctx);
@@ -2720,7 +3416,7 @@ pdf14_discard_trans_layer(gx_device *dev, gs_gstate * pgs)
/* The things that need to be cleaned up */
pdf14_ctx *ctx = pdev->ctx;
pdf14_smaskcolor_t *smaskcolor = pdev->smaskcolor;
- pdf14_parent_color_t *group_procs = pdev->trans_group_parent_cmap_procs;
+ pdf14_group_color_t *group_color = pdev->color_model_stack;
/* Free up the smask color */
if (smaskcolor != NULL) {
@@ -2730,17 +3426,17 @@ pdf14_discard_trans_layer(gx_device *dev, gs_gstate * pgs)
}
/* Free up the nested color procs and decrement the profiles */
- if (group_procs != NULL) {
- while (group_procs->previous != NULL)
- pdf14_pop_parent_color(dev, pgs);
- gs_free_object(dev->memory->stable_memory, group_procs, "pdf14_discard_trans_layer");
- pdev->trans_group_parent_cmap_procs = NULL;
+ if (group_color != NULL) {
+ while (group_color->previous != NULL)
+ pdf14_pop_group_color(dev, pgs);
+ gs_free_object(dev->memory->stable_memory, group_color, "pdf14_discard_trans_layer");
+ pdev->color_model_stack = NULL;
}
/* Start the context clean up */
if (ctx != NULL) {
pdf14_buf *buf, *next;
- pdf14_parent_color_t *procs, *prev_procs;
+ pdf14_group_color_t *procs, *prev_procs;
if (ctx->mask_stack != NULL) {
pdf14_free_mask_stack(ctx, ctx->memory);
@@ -2758,14 +3454,14 @@ pdf14_discard_trans_layer(gx_device *dev, gs_gstate * pgs)
the ctx to the tos mask_stack. We are done with this now so it is safe
to free this one object */
gs_free_object(ctx->memory, buf->mask_stack, "pdf14_discard_trans_layer");
- for (procs = buf->parent_color_info; procs != NULL; procs = prev_procs) {
+ for (procs = buf->group_color_info; procs != NULL; procs = prev_procs) {
prev_procs = procs->previous;
gs_free_object(ctx->memory, procs, "pdf14_discard_trans_layer");
}
gs_free_object(ctx->memory, buf, "pdf14_discard_trans_layer");
}
/* Finally the context itself */
- gs_free_object (ctx->memory, ctx, "pdf14_discard_trans_layer");
+ gs_free_object(ctx->memory, ctx, "pdf14_discard_trans_layer");
pdev->ctx = NULL;
}
return 0;
@@ -2994,6 +3690,8 @@ push_shfill_group(pdf14_clist_device *pdev,
gs_rect cb;
gs_gstate fudged_pgs = *pgs;
+ params.shade_group = true;
+
/* gs_begin_transparency_group takes a bbox that it then
* transforms by ctm. Our bbox has already been transformed,
* so clear out the ctm. */
@@ -3010,6 +3708,7 @@ push_shfill_group(pdf14_clist_device *pdev,
params.Isolated = false;
params.Knockout = true;
+ params.page_group = false;
params.group_opacity = fudged_pgs.fillconstantalpha;
params.group_shape = 1.0;
code = gs_begin_transparency_group(&fudged_pgs, &params, &cb, PDF14_BEGIN_TRANS_GROUP);
@@ -3050,6 +3749,11 @@ pdf14_fill_path(gx_device *dev, const gs_gstate *pgs,
gs_pattern2_instance_t *pinst = NULL;
int push_group = 0;
+ code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
+ dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, pgs);
+ if (code < 0)
+ return code;
+
if (pdcolor == NULL)
return_error(gs_error_unknownerror); /* color must be defined */
if (gx_dc_is_pattern1_color(pdcolor)){
@@ -3177,6 +3881,12 @@ pdf14_stroke_path(gx_device *dev, const gs_gstate *pgs,
if (pdcolor == NULL)
return_error(gs_error_unknownerror); /* color must be defined */
+
+ code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
+ dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, pgs);
+ if (code < 0)
+ return code;
+
if (gx_dc_is_pattern2_color(pdcolor)) {
/* Non-idempotent blends require a transparency
* group to be pushed because shadings might
@@ -3278,6 +3988,11 @@ pdf14_fill_stroke_path(gx_device *dev, const gs_gstate *cpgs, gx_path *ppath,
(pgs->ctm.xx == 0.0 && pgs->ctm.xy == 0.0 && pgs->ctm.yx == 0.0 && pgs->ctm.yy == 0.0))
return 0;
+ code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
+ dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, cpgs);
+ if (code < 0)
+ return code;
+
code = gx_curr_fixed_bbox(pgs, &clip_bbox, NO_PATH);
if (code < 0 && code != gs_error_unknownerror)
return code;
@@ -3321,8 +4036,9 @@ pdf14_fill_stroke_path(gx_device *dev, const gs_gstate *cpgs, gx_path *ppath,
compatible overprint mode. Group will be composited with
original alpha and blend mode */
params.Isolated = false;
- params.group_color = UNKNOWN;
+ params.group_color_type = UNKNOWN;
params.Knockout = false;
+ params.page_group = false;
params.group_opacity = 1.0;
params.group_shape = fill_alpha;
@@ -3353,8 +4069,9 @@ pdf14_fill_stroke_path(gx_device *dev, const gs_gstate *cpgs, gx_path *ppath,
/* Push a non-isolated knockout group. Do not change the alpha or
blend modes. Note: we need to draw those that have alpha = 0 */
params.Isolated = false;
- params.group_color = UNKNOWN;
+ params.group_color_type = UNKNOWN;
params.Knockout = true;
+ params.page_group = false;
params.group_shape = 1.0;
params.group_opacity = 1.0;
@@ -3811,6 +4528,12 @@ pdf14_copy_alpha_color(gx_device * dev, const byte * data, int data_x,
int depth, bool devn)
{
bool deep = device_is_deep(dev);
+ int code;
+
+ code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
+ dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, NULL);
+ if (code < 0)
+ return code;
if (deep)
return do_pdf14_copy_alpha_color_16(dev, data, data_x, aa_raster,
@@ -3841,6 +4564,12 @@ pdf14_fill_mask(gx_device * orig_dev,
if (pdcolor == NULL)
return_error(gs_error_unknownerror); /* color must be defined */
+
+ code = pdf14_initialize_ctx(orig_dev, orig_dev->color_info.num_components,
+ orig_dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, NULL);
+ if (code < 0)
+ return code;
+
/* If we are doing a fill with a pattern that has a transparency then
go ahead and do a push and a pop of the transparency group */
if (gx_dc_is_pattern1_color(pdcolor)) {
@@ -3874,9 +4603,15 @@ pdf14_fill_mask(gx_device * orig_dev,
group_rect.q.x = x + w;
group_rect.q.y = y + h;
if (!(w <= 0 || h <= 0)) {
+
+ pdf14_group_color_t *group_color_info = pdf14_clone_group_color_info((gx_device *) p14dev, p14dev->ctx->stack->group_color_info);
+ if (group_color_info == NULL)
+ return gs_error_VMerror;
+
code = pdf14_push_transparency_group(p14dev->ctx, &group_rect,
1, 0, 65535, 65535, 65535, ptile->blending_mode, 0, 0,
- ptile->ttrans->n_chan-1, false, NULL, NULL, NULL, NULL);
+ ptile->ttrans->n_chan-1, false, false, NULL, NULL,
+ group_color_info, NULL, NULL);
if (code < 0)
return code;
/* Set up the output buffer information now that we have
@@ -3921,6 +4656,8 @@ pdf14_fill_mask(gx_device * orig_dev,
return code;
}
+
+
/* Used for filling rects when we are doing a fill with a pattern that
has transparency */
static int
@@ -3944,6 +4681,7 @@ pdf14_tile_pattern_fill(gx_device * pdev, const gs_gstate * pgs,
gx_clip_path cpath_intersection;
gx_path path_ttrans;
gs_blend_mode_t blend_mode;
+ pdf14_group_color_t *group_color_info;
if (ppath == NULL)
return_error(gs_error_unknownerror); /* should not happen */
@@ -4026,11 +4764,15 @@ pdf14_tile_pattern_fill(gx_device * pdev, const gs_gstate * pgs,
}
blend_mode = ptile->blending_mode;
memcpy(&save_pdf14_dev, p14dev, sizeof(pdf14_device));
+
+ group_color_info = pdf14_clone_group_color_info(pdev, p14dev->ctx->stack->group_color_info);
+ if (group_color_info == NULL)
+ return gs_error_VMerror;
+
code = pdf14_push_transparency_group(p14dev->ctx, &rect, 1, 0, (uint16_t)floor(65535 * p14dev->alpha + 0.5),
- (uint16_t)floor(65535 * p14dev->shape + 0.5), (uint16_t)floor(65535 * p14dev->opacity + 0.5),
- blend_mode, 0, 0, n_chan_tile-1,
- false, NULL, NULL, pgs_noconst,
- pdev);
+ (uint16_t)floor(65535 * p14dev->shape + 0.5), (uint16_t)floor(65535 * p14dev->opacity + 0.5),
+ blend_mode, 0, 0, n_chan_tile - 1, false, false,
+ NULL, NULL, group_color_info, pgs_noconst, pdev);
if (code < 0)
return code;
@@ -4269,18 +5011,22 @@ pdf14_patt_trans_image_fill(gx_device * dev, const gs_gstate * pgs,
if_debug2m('v', p14dev->ctx->memory,
"[v*] Pushing trans group patt_trans_image_fill, uid = %ld id = %ld \n",
ptile->uid.id, ptile->id);
+
code = pdf14_push_transparency_group(p14dev->ctx, &group_rect, 1, 0, 65535, 65535,
65535, pgs->blend_mode, 0, 0,
- ptile->ttrans->n_chan-1, false, NULL,
- NULL, (gs_gstate *)pgs, dev);
+ ptile->ttrans->n_chan-1, false, false,
+ NULL, NULL, NULL, (gs_gstate *)pgs, dev);
+
/* Set up the output buffer information now that we have
pushed the group */
fill_trans_buffer = new_pattern_trans_buff(pgs->memory);
pdf14_get_buffer_information(dev, fill_trans_buffer, NULL, false);
+
/* Store this in the appropriate place in pdcolor. This
is released later in pdf14_pattern_trans_render when
we are all done with the mask fill */
ptile->ttrans->fill_trans_buffer = fill_trans_buffer;
+
/* Change the renderer to handle this case so we can catch the
end. We will then pop the group and reset the pdcolor proc.
Keep the base renderer also. */
@@ -4303,6 +5049,11 @@ pdf14_begin_typed_image(gx_device * dev, const gs_gstate * pgs,
const gs_image_t *pim = (const gs_image_t *)pic;
int code;
+ code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
+ dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, pgs);
+ if (code < 0)
+ return code;
+
/* If we are filling an image mask with a pattern that has a transparency
then we need to do some special handling */
if (pim->ImageMask) {
@@ -4989,6 +5740,7 @@ pdf14_push_text_group(gx_device *dev, gs_gstate *pgs,
mode are correct */
params.Isolated = false;
params.Knockout = true;
+ params.page_group = false;
params.text_group = PDF14_TEXTGROUP_BT_PUSHED;
params.group_opacity = 1.0;
params.group_shape = 1.0;
@@ -5033,6 +5785,11 @@ pdf14_text_begin(gx_device * dev, gs_gstate * pgs,
bool text_stroke = (text_mode == 1 || text_mode == 2 || text_mode == 5 || text_mode == 6);
bool text_fill = (text_mode == 0 || text_mode == 2 || text_mode == 4 || text_mode == 6);
+ code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
+ dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, (const gs_gstate*) pgs);
+ if (code < 0)
+ return code;
+
if_debug0m('v', memory, "[v]pdf14_text_begin\n");
pdf14_set_marking_params(dev, pgs);
code = gx_default_text_begin(dev, pgs, text, font, path, pdcolor, pcpath,
@@ -5083,7 +5840,7 @@ pdf14_finish_copydevice(gx_device *new_dev, const gx_device *from_dev)
pdf14_device *pdev = (pdf14_device*)new_dev;
pdev->ctx = NULL;
- pdev->trans_group_parent_cmap_procs = NULL;
+ pdev->color_model_stack = NULL;
pdev->smaskcolor = NULL;
/* Only allow copying the prototype. */
@@ -5210,7 +5967,7 @@ pdf14_copy_planes(gx_device * dev, const byte * data, int data_x, int raster,
fake_tos.n_chan = dev->color_info.num_components;
fake_tos.n_planes = dev->color_info.num_components;
fake_tos.num_spots = 0;
- fake_tos.parent_color_info = NULL;
+ fake_tos.group_color_info = NULL;
fake_tos.planestride = raster * plane_height;
fake_tos.rect.p.x = x;
fake_tos.rect.p.y = y;
@@ -5232,11 +5989,18 @@ pdf14_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
const gx_clip_path *pcpath)
{
pdf14_device *pdev = (pdf14_device *)dev;
- pdf14_buf *buf = pdev->ctx->stack;
+ pdf14_buf* buf;
+ int code;
int x = fixed2int(rect->p.x);
int y = fixed2int(rect->p.y);
int w = fixed2int(rect->q.x) - x;
- int h = fixed2int(rect->q.y) -y;
+ int h = fixed2int(rect->q.y) - y;
+
+ code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
+ dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, pgs);
+ if (code < 0)
+ return code;
+ buf = pdev->ctx->stack;
fit_fill_xywh(dev, x, y, w, h);
if (w <= 0 || h <= 0)
@@ -5253,7 +6017,15 @@ pdf14_fill_rectangle(gx_device * dev,
int x, int y, int w, int h, gx_color_index color)
{
pdf14_device *pdev = (pdf14_device *)dev;
- pdf14_buf *buf = pdev->ctx->stack;
+ pdf14_buf *buf;
+ int code;
+
+ code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
+ dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, NULL);
+ if (code < 0)
+ return code;
+
+ buf = pdev->ctx->stack;
fit_fill_xywh(dev, x, y, w, h);
if (w <= 0 || h <= 0)
@@ -5300,59 +6072,64 @@ compute_group_device_int_rect(pdf14_device *pdev, gs_int_rect *rect,
}
static int
-pdf14_begin_transparency_group(gx_device *dev,
- const gs_transparency_group_params_t *ptgp,
- const gs_rect *pbbox,
- gs_gstate *pgs, gs_memory_t *mem)
+pdf14_begin_transparency_group(gx_device* dev,
+ const gs_transparency_group_params_t* ptgp,
+ const gs_rect* pbbox,
+ gs_gstate* pgs, gs_memory_t* mem)
{
- pdf14_device *pdev = (pdf14_device *)dev;
+ pdf14_device* pdev = (pdf14_device*)dev;
double alpha = ptgp->group_opacity * ptgp->group_shape;
gs_int_rect rect;
int code;
bool isolated = ptgp->Isolated;
- gs_transparency_color_t group_color;
- cmm_profile_t *group_profile;
- cmm_profile_t *tos_profile;
+ gs_transparency_color_t group_color_type;
+ cmm_profile_t* group_profile;
+ cmm_profile_t* tos_profile;
gsicc_rendering_param_t render_cond;
- cmm_dev_profile_t *dev_profile;
+ cmm_dev_profile_t* dev_profile;
bool cm_back_drop = false;
bool new_icc = false;
+ pdf14_group_color_t* group_color_info;
- code = dev_proc(dev, get_profile)(dev, &dev_profile);
+ code = dev_proc(dev, get_profile)(dev, &dev_profile);
if (code < 0)
return code;
gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &tos_profile, &render_cond);
if (ptgp->text_group == PDF14_TEXTGROUP_BT_PUSHED) {
- rect = pdev->ctx->rect; /* Use parent group for text_group. */
pdev->text_group = PDF14_TEXTGROUP_BT_PUSHED; /* For immediate mode and clist reading */
- } else
+ }
+
+ if (ptgp->text_group == PDF14_TEXTGROUP_BT_PUSHED)
+ rect = pdev->ctx->rect; /* Use parent group for text_group. */
+ else
code = compute_group_device_int_rect(pdev, &rect, pbbox, pgs);
if (code < 0)
return code;
- if_debug4m('v', pdev->memory,
- "[v]pdf14_begin_transparency_group, I = %d, K = %d, alpha = %g, bm = %d\n",
- ptgp->Isolated, ptgp->Knockout, alpha, pgs->blend_mode);
+ if_debug5m('v', pdev->memory,
+ "[v]pdf14_begin_transparency_group, I = %d, K = %d, alpha = %g, bm = %d page_group = %d\n",
+ ptgp->Isolated, ptgp->Knockout, alpha, pgs->blend_mode, ptgp->page_group);
/* If the group color is unknown then use the current device profile. */
- if (ptgp->group_color == UNKNOWN){
- group_color = ICC;
+ if (ptgp->group_color_type == UNKNOWN) {
+ group_color_type = ICC;
group_profile = tos_profile;
- } else {
- group_color = ptgp->group_color;
+ }
+ else {
+ group_color_type = ptgp->group_color_type;
group_profile = ptgp->iccprofile;
}
/* We have to handle case where the profile is in the clist */
if (group_profile == NULL && pdev->pclist_device != NULL) {
/* Get the serialized data from the clist. */
- gx_device_clist_reader *pcrdev = (gx_device_clist_reader *)(pdev->pclist_device);
- group_profile = gsicc_read_serial_icc((gx_device *) pcrdev, ptgp->icc_hashcode);
+ gx_device_clist_reader* pcrdev = (gx_device_clist_reader*)(pdev->pclist_device);
+ group_profile = gsicc_read_serial_icc((gx_device*)pcrdev, ptgp->icc_hashcode);
if (group_profile == NULL)
return gs_throw(gs_error_unknownerror, "ICC data not found in clist");
/* Keep a pointer to the clist device */
- group_profile->dev = (gx_device *) pcrdev;
+ group_profile->dev = (gx_device*)pcrdev;
new_icc = true;
}
if (group_profile != NULL) {
@@ -5360,8 +6137,8 @@ pdf14_begin_transparency_group(gx_device *dev,
we will need to CM the backdrop. */
if (!(group_profile->hash_is_valid)) {
gsicc_get_icc_buff_hash(group_profile->buffer,
- &(group_profile->hashcode),
- group_profile->buffer_size);
+ &(group_profile->hashcode),
+ group_profile->buffer_size);
group_profile->hash_is_valid = true;
}
if (group_profile->hashcode != tos_profile->hashcode) {
@@ -5369,93 +6146,122 @@ pdf14_begin_transparency_group(gx_device *dev,
}
}
- code = pdf14_update_device_color_procs(dev, group_color, ptgp->icc_hashcode,
- pgs, group_profile, false);
+ /* Always create the base color group information as it is only through
+ groups that we can have a color space change. This will survive
+ the life of the context. */
+ if (pdev->ctx->base_color == NULL) {
+ pdev->ctx->base_color = pdf14_make_base_group_color(dev);
+ }
+
+ /* If this is not the page group and we don't yet have a group, we need
+ to create a buffer for the whole page so that we can handle stuff drawn
+ outside this current group (e.g. two non inclusive groups drawn independently) */
+ if (pdev->ctx->stack == NULL && !ptgp->page_group) {
+ code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
+ dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, NULL);
+ if (code < 0)
+ return code;
+ pdev->ctx->stack->isolated = true;
+ }
+
+ group_color_info = pdf14_push_color_model(dev, group_color_type, ptgp->icc_hashcode,
+ group_profile, false);
+ if (group_color_info == NULL)
+ return gs_error_VMerror;
+
if_debug0m('v', dev->memory, "[v]Transparency group color space update\n");
if (code < 0)
return code;
+
code = pdf14_push_transparency_group(pdev->ctx, &rect, isolated, ptgp->Knockout,
(uint16_t)floor (65535 * alpha + 0.5),
(uint16_t)floor(65535 * ptgp->group_shape + 0.5),
(uint16_t)floor(65535 * ptgp->group_opacity + 0.5),
pgs->blend_mode, ptgp->idle,
ptgp->mask_id, pdev->color_info.num_components,
- cm_back_drop, group_profile, tos_profile,
- pgs, dev);
+ cm_back_drop, ptgp->shade_group,
+ group_profile, tos_profile, group_color_info, pgs, dev);
if (new_icc)
gsicc_adjust_profile_rc(group_profile, -1, "pdf14_begin_transparency_group");
return code;
}
+static void
+pdf14_pop_color_model(gx_device* dev, pdf14_group_color_t* group_color)
+{
+ pdf14_device* pdev = (pdf14_device*)dev;
+
+ if (group_color != NULL &&
+ !(group_color->group_color_mapping_procs == NULL &&
+ group_color->group_color_comp_index == NULL)) {
+ set_dev_proc(pdev, get_color_mapping_procs, group_color->group_color_mapping_procs);
+ set_dev_proc(pdev, get_color_comp_index, group_color->group_color_comp_index);
+ pdev->color_info.polarity = group_color->polarity;
+ pdev->color_info.num_components = group_color->num_components;
+ pdev->blend_procs = group_color->blend_procs;
+ pdev->ctx->additive = group_color->isadditive;
+ pdev->pdf14_procs = group_color->unpack_procs;
+ pdev->color_info.depth = group_color->depth;
+ pdev->color_info.max_color = group_color->max_color;
+ pdev->color_info.max_gray = group_color->max_gray;
+ memcpy(&(pdev->color_info.comp_bits), &(group_color->comp_bits),
+ GX_DEVICE_COLOR_MAX_COMPONENTS);
+ memcpy(&(pdev->color_info.comp_shift), &(group_color->comp_shift),
+ GX_DEVICE_COLOR_MAX_COMPONENTS);
+ if (group_color->icc_profile != NULL) {
+ /* make sure to decrement the device profile. If it was allocated
+ with the push then it will be freed. */
+ gsicc_adjust_profile_rc(pdev->icc_struct->device_profile[0], -1,
+ "pdf14_pop_color_model");
+ pdev->icc_struct->device_profile[0] = group_color->icc_profile;
+ }
+ }
+}
+
static int
-pdf14_end_transparency_group(gx_device *dev,
- gs_gstate *pgs)
+pdf14_end_transparency_group(gx_device* dev, gs_gstate* pgs)
{
- pdf14_device *pdev = (pdf14_device *)dev;
+ pdf14_device* pdev = (pdf14_device*)dev;
int code;
- pdf14_parent_color_t *parent_color;
- cmm_profile_t *group_profile;
+ cmm_profile_t* group_profile;
gsicc_rendering_param_t render_cond;
- cmm_dev_profile_t *dev_profile;
+ cmm_dev_profile_t* dev_profile;
- code = dev_proc(dev, get_profile)(dev, &dev_profile);
+ code = dev_proc(dev, get_profile)(dev, &dev_profile);
if (code < 0)
return code;
+
gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &group_profile,
- &render_cond);
+ &render_cond);
if_debug0m('v', dev->memory, "[v]pdf14_end_transparency_group\n");
+
code = pdf14_pop_transparency_group(pgs, pdev->ctx, pdev->blend_procs,
- pdev->color_info.num_components, group_profile,
- (gx_device *) pdev);
+ pdev->color_info.num_components, group_profile, (gx_device*)pdev);
#ifdef DEBUG
pdf14_debug_mask_stack_state(pdev->ctx);
#endif
- /* May need to reset some color stuff related
- * to a mismatch between the parents color space
- * and the group blending space */
- parent_color = pdev->ctx->stack->parent_color_info;
- if (!(parent_color->parent_color_mapping_procs == NULL &&
- parent_color->parent_color_comp_index == NULL)) {
- pgs->get_cmap_procs = parent_color->get_cmap_procs;
- gx_set_cmap_procs(pgs, dev);
- set_dev_proc(pdev, get_color_mapping_procs, parent_color->parent_color_mapping_procs);
- set_dev_proc(pdev, get_color_comp_index, parent_color->parent_color_comp_index);
- pdev->color_info.polarity = parent_color->polarity;
- pdev->color_info.num_components = parent_color->num_components;
- pdev->blend_procs = parent_color->parent_blending_procs;
- pdev->ctx->additive = parent_color->isadditive;
- pdev->pdf14_procs = parent_color->unpack_procs;
- pdev->color_info.depth = parent_color->depth;
- pdev->color_info.max_color = parent_color->max_color;
- pdev->color_info.max_gray = parent_color->max_gray;
- memcpy(&(pdev->color_info.comp_bits),&(parent_color->comp_bits),
- GX_DEVICE_COLOR_MAX_COMPONENTS);
- memcpy(&(pdev->color_info.comp_shift),&(parent_color->comp_shift),
- GX_DEVICE_COLOR_MAX_COMPONENTS);
- parent_color->get_cmap_procs = NULL;
- parent_color->parent_color_comp_index = NULL;
- parent_color->parent_color_mapping_procs = NULL;
- if (parent_color->icc_profile != NULL) {
- /* make sure to decrement the device profile. If it was allocated
- with the push then it will be freed. */
- gsicc_adjust_profile_rc(dev->icc_struct->device_profile[0], -1, "pdf14_end_transparency_group");
- dev->icc_struct->device_profile[0] = parent_color->icc_profile;
- parent_color->icc_profile = NULL;
- }
+ /* If this group is the base group, then restore the color model
+ of the device at this time. Note that during the actual device pop
+ we will need to use the profile of the buffer not the pdf14 device
+ as the source color space */
+ if (pdev->ctx->stack->group_popped) {
+ pdf14_pop_color_model(dev, pdev->ctx->base_color);
+ } else {
+ pdf14_pop_color_model(dev, pdev->ctx->stack->group_color_info);
}
+
return code;
}
-static int
-pdf14_update_device_color_procs(gx_device *dev,
- gs_transparency_color_t group_color,
- int64_t icc_hashcode, gs_gstate *pgs,
- cmm_profile_t *iccprofile, bool is_mask)
+static pdf14_group_color_t*
+pdf14_push_color_model(gx_device *dev, gs_transparency_color_t group_color_type,
+ int64_t icc_hashcode, cmm_profile_t *iccprofile,
+ bool is_mask)
{
pdf14_device *pdevproto = NULL;
pdf14_device *pdev = (pdf14_device *)dev;
const pdf14_procs_t *new_14procs = NULL;
- pdf14_parent_color_t *parent_color_info;
+ pdf14_group_color_t *group_color;
gx_color_polarity_t new_polarity;
uchar new_num_comps;
bool new_additive;
@@ -5464,37 +6270,19 @@ pdf14_update_device_color_procs(gx_device *dev,
byte comp_shift[GX_DEVICE_COLOR_MAX_COMPONENTS];
int k;
bool has_tags = device_encodes_tags(dev);
- gsicc_rendering_param_t render_cond;
- cmm_dev_profile_t *dev_profile;
bool deep = pdev->ctx->deep;
- if (pdev->ctx->stack != NULL){
- parent_color_info = pdev->ctx->stack->parent_color_info;
- } else {
- /* This should not occur */
- return_error(gs_error_undefined);
- }
- if_debug0m('v', dev->memory, "[v]pdf14_update_device_color_procs\n");
+ if_debug0m('v', dev->memory, "[v]pdf14_push_color_model\n");
- memset(comp_bits, 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
- memset(comp_shift, 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
+ group_color = gs_alloc_struct(dev->memory->stable_memory,
+ pdf14_group_color_t, &st_pdf14_clr,
+ "pdf14_push_color_model");
+ if (group_color == NULL)
+ return NULL;
+
+ memset(group_color, 0, sizeof(pdf14_group_color_t));
- /* Update the device procs at this stage. Many of the procs are based upon
- the color space of the device. We want to remain in the color space
- defined by the color space of the soft mask or transparency group as
- opposed to the device color space. Later, when we pop the softmask we will
- collapse it to a single band and then compose with it to the device color
- space (or the parent layer space). In the case where we pop an isolated
- transparency group, we will do the blending in the proper color space and
- then transform the data when we pop the group. Remember that only isolated
- groups can have color spaces that are different than their parent.
- Separation devices that have to maintain separate spot color planes need
- special handling here */
- parent_color_info->get_cmap_procs = NULL;
- parent_color_info->parent_color_mapping_procs = NULL;
- parent_color_info->parent_color_comp_index = NULL;
-
- switch (group_color) {
+ switch (group_color_type) {
case GRAY_SCALE:
new_polarity = GX_CINFO_POLARITY_ADDITIVE;
new_num_comps = 1;
@@ -5543,16 +6331,19 @@ pdf14_update_device_color_procs(gx_device *dev,
iccprofile = gsicc_read_serial_icc((gx_device *) pcrdev,
icc_hashcode);
if (iccprofile == NULL)
- return gs_throw(gs_error_unknownerror, "ICC data not found in clist");
+ return NULL;
/* Keep a pointer to the clist device */
iccprofile->dev = (gx_device *) pcrdev;
} else {
/* Go ahead and rc increment right now. This way when
we pop, we will make sure to decrement and avoid a
- leak for the above profile that we just created */
+ leak for the above profile that we just created. This
+ goes with the assignment to the device's profile.
+ Note that we still do the increment for the group_color
+ assignment below. */
if (iccprofile == NULL)
- return gs_throw(gs_error_unknownerror, "ICC data unknown");
- gsicc_adjust_profile_rc(iccprofile, 1, "pdf14_update_device_color_procs");
+ return NULL;
+ gsicc_adjust_profile_rc(iccprofile, 1, "pdf14_push_color_model");
}
new_num_comps = iccprofile->num_comps;
if (new_num_comps == 4) {
@@ -5602,48 +6393,25 @@ pdf14_update_device_color_procs(gx_device *dev,
}
break;
default:
- return_error(gs_error_rangecheck);
+ return NULL;
break;
}
break;
default:
- return_error(gs_error_rangecheck);
+ return NULL;
break;
}
- /* Save the old information */
- parent_color_info->get_cmap_procs = pgs->get_cmap_procs;
- parent_color_info->parent_color_mapping_procs =
- dev_proc(pdev, get_color_mapping_procs);
- parent_color_info->parent_color_comp_index =
- dev_proc(pdev, get_color_comp_index);
- parent_color_info->parent_blending_procs = pdev->blend_procs;
- parent_color_info->polarity = pdev->color_info.polarity;
- parent_color_info->num_components = pdev->color_info.num_components;
- parent_color_info->isadditive = pdev->ctx->additive;
- parent_color_info->unpack_procs = pdev->pdf14_procs;
- parent_color_info->depth = pdev->color_info.depth;
- parent_color_info->max_color = pdev->color_info.max_color;
- parent_color_info->max_gray = pdev->color_info.max_gray;
- parent_color_info->encode = dev_proc(pdev, encode_color);
- parent_color_info->decode = dev_proc(pdev, decode_color);
- memcpy(&(parent_color_info->comp_bits), &(pdev->color_info.comp_bits),
- GX_DEVICE_COLOR_MAX_COMPONENTS);
- memcpy(&(parent_color_info->comp_shift), &(pdev->color_info.comp_shift),
- GX_DEVICE_COLOR_MAX_COMPONENTS);
-
- /* Don't increment the space since we are going to remove it from the
- ICC manager anyway. */
- if (group_color == ICC && iccprofile != NULL) {
- dev_proc(dev, get_profile)(dev, &dev_profile);
- gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile,
- &(parent_color_info->icc_profile), &render_cond);
- }
- /* Set new information */
+
+ if (group_color_type == ICC && iccprofile != NULL) {
+ group_color->icc_profile = iccprofile;
+ gsicc_adjust_profile_rc(iccprofile, 1, "pdf14_push_color_model");
+ }
+
/* If we are a sep device and this is not a softmask, ensure we maintain the
spot colorants and know how to index into them */
if (pdev->sep_device && !is_mask) {
- int num_spots = parent_color_info->num_components -
- parent_color_info->icc_profile->num_comps;
+ int num_spots = dev->color_info.num_components -
+ dev->icc_struct->device_profile[0]->num_comps;
if (num_spots > 0) {
new_num_comps += num_spots;
@@ -5653,16 +6421,19 @@ pdf14_update_device_color_procs(gx_device *dev,
}
}
}
+
+ /* Set device values now and store settings in group_color. Then they
+ are available when we pop the previous group */
if_debug2m('v', pdev->memory,
- "[v]pdf14_update_device_color_procs,num_components_old = %d num_components_new = %d\n",
+ "[v]pdf14_push_color_model, num_components_old = %d num_components_new = %d\n",
pdev->color_info.num_components,new_num_comps);
set_dev_proc(pdev, get_color_mapping_procs, pdevproto->static_procs->get_color_mapping_procs);
set_dev_proc(pdev, get_color_comp_index, pdevproto->static_procs->get_color_comp_index);
- pdev->blend_procs = pdevproto->blend_procs;
- pdev->color_info.polarity = new_polarity;
- pdev->color_info.num_components = new_num_comps;
- pdev->ctx->additive = new_additive;
- pdev->pdf14_procs = new_14procs;
+ group_color->blend_procs = pdev->blend_procs = pdevproto->blend_procs;
+ group_color->polarity = pdev->color_info.polarity = new_polarity;
+ group_color->num_components = pdev->color_info.num_components = new_num_comps;
+ group_color->isadditive = pdev->ctx->additive = new_additive;
+ group_color->unpack_procs = pdev->pdf14_procs = new_14procs;
pdev->color_info.depth = new_num_comps * (8<<deep);
memset(&(pdev->color_info.comp_bits), 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
memset(&(pdev->color_info.comp_shift), 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
@@ -5672,34 +6443,43 @@ pdf14_update_device_color_procs(gx_device *dev,
pdev->color_info.comp_shift[pdev->color_info.num_components] = pdev->color_info.depth;
pdev->color_info.depth += 8;
}
- pdev->color_info.max_color = deep ? 65535 : 255;
- pdev->color_info.max_gray = deep ? 65535 : 255;
+ group_color->max_color = pdev->color_info.max_color = deep ? 65535 : 255;
+ group_color->max_gray = pdev->color_info.max_gray = deep ? 65535 : 255;
+ group_color->depth = pdev->color_info.depth;
+ group_color->decode = dev_proc(pdev, decode_color);
+ group_color->encode = dev_proc(pdev, encode_color);
+ group_color->group_color_mapping_procs = dev_proc(pdev, get_color_mapping_procs);
+ group_color->group_color_comp_index = dev_proc(pdev, get_color_comp_index);
+ memcpy(&(group_color->comp_bits), &(pdev->color_info.comp_bits),
+ GX_DEVICE_COLOR_MAX_COMPONENTS);
+ memcpy(&(group_color->comp_shift), &(pdev->color_info.comp_shift),
+ GX_DEVICE_COLOR_MAX_COMPONENTS);
+ group_color->get_cmap_procs = pdf14_get_cmap_procs;
+
/* If the CS was ICC based, we need to update the device ICC profile
in the ICC manager, since that is the profile that is used for the
PDF14 device */
- if (group_color == ICC && iccprofile != NULL) {
+ if (group_color_type == ICC && iccprofile != NULL) {
/* iccprofile was incremented above if we had not just created it.
When we do the pop we will decrement and if we just created it, it
will be destroyed */
dev->icc_struct->device_profile[0] = iccprofile;
}
- return 1; /* Lets us detect that we did do an update */
+ return group_color;
}
-/* A new version that works with the color_procs stack
- for transparency groups */
static int
-pdf14_update_device_color_procs_push_c(gx_device *dev,
- gs_transparency_color_t group_color,
- int64_t icc_hashcode,
- gs_gstate *pgs,
- cmm_profile_t *icc_profile,
- bool is_mask)
-{
- pdf14_device *pdevproto;
- pdf14_device *pdev = (pdf14_device *)dev;
- gx_device_clist_writer * cldev = (gx_device_clist_writer *)pdev->pclist_device;
- const pdf14_procs_t *new_14procs;
+pdf14_clist_push_color_model(gx_device *dev, gx_device* cdev, gs_gstate *pgs,
+ const gs_pdf14trans_t *pdf14pct, gs_memory_t* mem,
+ bool is_mask)
+{
+ pdf14_device* pdev = (pdf14_device*)dev;
+ pdf14_group_color_t* new_group_color;
+ gsicc_rendering_param_t render_cond;
+ cmm_dev_profile_t* dev_profile;
+ pdf14_device* pdevproto;
+ gx_device_clist_writer* cldev = (gx_device_clist_writer*)pdev->pclist_device;
+ const pdf14_procs_t* new_14procs;
bool update_color_info;
gx_color_polarity_t new_polarity;
int new_num_comps;
@@ -5709,146 +6489,192 @@ pdf14_update_device_color_procs_push_c(gx_device *dev,
byte comp_shift[GX_DEVICE_COLOR_MAX_COMPONENTS];
int k;
bool has_tags = device_encodes_tags(dev);
- cmm_profile_t *icc_profile_dev = NULL;
- gsicc_rendering_param_t render_cond;
- cmm_dev_profile_t *dev_profile;
bool deep = device_is_deep(dev);
+ gs_transparency_color_t group_color_type = pdf14pct->params.group_color_type;
+ cmm_profile_t *new_profile = pdf14pct->params.iccprofile;
+ cmm_profile_t *old_profile = NULL;
+
+ dev_proc(dev, get_profile)(dev, &dev_profile);
+ gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &old_profile,
+ &render_cond);
+ if_debug0m('v', dev->memory, "[v]pdf14_clist_push_color_model\n");
+
+ /* Allocate a new one */
+ new_group_color = gs_alloc_struct(dev->memory->stable_memory, pdf14_group_color_t,
+ &st_pdf14_clr, "pdf14_clist_push_color_model");
+
+ /* Link to old one */
+ new_group_color->previous = pdev->color_model_stack;
+
+ /* Reassign new one to dev */
+ pdev->color_model_stack = new_group_color;
+
+ /* Initialize with values */
+ new_group_color->get_cmap_procs = pgs->get_cmap_procs;
+ new_group_color->group_color_mapping_procs =
+ dev_proc(pdev, get_color_mapping_procs);
+ new_group_color->group_color_comp_index =
+ dev_proc(pdev, get_color_comp_index);
+ new_group_color->blend_procs = pdev->blend_procs;
+ new_group_color->polarity = pdev->color_info.polarity;
+ new_group_color->num_components = pdev->color_info.num_components;
+ new_group_color->unpack_procs = pdev->pdf14_procs;
+ new_group_color->depth = pdev->color_info.depth;
+ new_group_color->max_color = pdev->color_info.max_color;
+ new_group_color->max_gray = pdev->color_info.max_gray;
+ new_group_color->decode = dev_proc(pdev, decode_color);
+ new_group_color->encode = dev_proc(pdev, encode_color);
+ memcpy(&(new_group_color->comp_bits), &(pdev->color_info.comp_bits),
+ GX_DEVICE_COLOR_MAX_COMPONENTS);
+ memcpy(&(new_group_color->comp_shift), &(pdev->color_info.comp_shift),
+ GX_DEVICE_COLOR_MAX_COMPONENTS);
+
+ if (new_profile == NULL)
+ new_group_color->icc_profile = NULL;
+
+ /* isadditive is only used in ctx */
+ if (pdev->ctx) {
+ new_group_color->isadditive = pdev->ctx->additive;
+ }
memset(comp_bits, 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
memset(comp_shift, 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
- if (group_color == ICC && icc_profile == NULL)
+ if (group_color_type == ICC && new_profile == NULL)
return gs_throw(gs_error_undefinedresult, "Missing ICC data");
- if_debug0m('v', cldev->memory, "[v]pdf14_update_device_color_procs_push_c\n");
- /* Check if we need to alter the device procs at this stage. Many of the procs
- are based upon the color space of the device. We want to remain in the
- color space defined by the color space of the soft mask or transparency
- group as opposed to the device color space. Later, when we pop the softmask
- we will collapse it to a single band and then compose with it to the device
- color space (or the parent layer space). In the case where we pop an
- isolated transparency group, we will do the blending in the proper color
- space and then transform the data when we pop the group. Remember that only
- isolated groups can have color spaces that are different than their parent. */
+ if_debug0m('v', cldev->memory, "[v]pdf14_clist_push_color_model\n");
+ /* Check if we need to alter the device procs at this stage. Many of the procs
+ are based upon the color space of the device. We want to remain in the
+ color space defined by the color space of the soft mask or transparency
+ group as opposed to the device color space. Later, when we pop the softmask
+ we will collapse it to a single band and then compose with it to the device
+ color space (or the parent layer space). In the case where we pop an
+ isolated transparency group, we will do the blending in the proper color
+ space and then transform the data when we pop the group. Remember that only
+ isolated groups can have color spaces that are different than their parent. */
update_color_info = false;
- switch (group_color) {
- case GRAY_SCALE:
- if (pdev->color_info.num_components != 1){
- update_color_info = true;
+ switch (group_color_type) {
+ case GRAY_SCALE:
+ if (pdev->color_info.num_components != 1) {
+ update_color_info = true;
+ new_polarity = GX_CINFO_POLARITY_ADDITIVE;
+ new_num_comps = 1;
+ pdevproto = (pdf14_device*)&gs_pdf14_Gray_device;
+ new_additive = true;
+ new_14procs = &gray_pdf14_procs;
+ new_depth = 8 << deep;
+ comp_bits[0] = 8 << deep;
+ comp_shift[0] = 0;
+ }
+ break;
+ case DEVICE_RGB:
+ case CIE_XYZ:
+ if (pdev->color_info.num_components != 3) {
+ update_color_info = true;
+ new_polarity = GX_CINFO_POLARITY_ADDITIVE;
+ new_num_comps = 3;
+ pdevproto = (pdf14_device*)&gs_pdf14_RGB_device;
+ new_additive = true;
+ new_14procs = &rgb_pdf14_procs;
+ new_depth = 24 << deep;
+ for (k = 0; k < 3; k++) {
+ comp_bits[k] = 8 << deep;
+ comp_shift[k] = (2 - k) * (8 << deep);
+ }
+ }
+ break;
+ case DEVICE_CMYK:
+ if (pdev->color_info.num_components != 4) {
+ update_color_info = true;
+ new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
+ new_num_comps = 4;
+ pdevproto = (pdf14_device*)&gs_pdf14_CMYK_device;
+ new_additive = false;
+ /* This is needed due to the mismatched compressed encode decode
+ between the device procs and the pdf14 procs */
+ if (dev->color_info.num_components > 4) {
+ new_14procs = &cmykspot_pdf14_procs;
+ }
+ else {
+ new_14procs = &cmyk_pdf14_procs;
+ }
+ new_depth = 32 << deep;
+ for (k = 0; k < 4; k++) {
+ comp_bits[k] = 8 << deep;
+ comp_shift[k] = (3 - k) * (8 << deep);
+ }
+ }
+ break;
+ case ICC:
+ /* Check if the profile is different. */
+ if (old_profile->hashcode != new_profile->hashcode) {
+ update_color_info = true;
+ new_num_comps = new_profile->num_comps;
+ new_depth = new_profile->num_comps * (8 << deep);
+ switch (new_num_comps) {
+ case 1:
+ if (pdev->sep_device && !is_mask) {
+ pdevproto = (pdf14_device*)&gs_pdf14_Grayspot_device;
+ new_14procs = &grayspot_pdf14_procs;
+ }
+ else {
+ pdevproto = (pdf14_device*)&gs_pdf14_Gray_device;
+ new_14procs = &gray_pdf14_procs;
+ }
new_polarity = GX_CINFO_POLARITY_ADDITIVE;
- new_num_comps = 1;
- pdevproto = (pdf14_device *)&gs_pdf14_Gray_device;
new_additive = true;
- new_14procs = &gray_pdf14_procs;
- new_depth = 8<<deep;
- comp_bits[0] = 8<<deep;
+ comp_bits[0] = 8 << deep;
comp_shift[0] = 0;
- }
- break;
- case DEVICE_RGB:
- case CIE_XYZ:
- if (pdev->color_info.num_components != 3){
- update_color_info = true;
+ break;
+ case 3:
+ if (pdev->sep_device) {
+ pdevproto = (pdf14_device*)&gs_pdf14_RGBspot_device;
+ new_14procs = &rgbspot_pdf14_procs;
+ }
+ else {
+ pdevproto = (pdf14_device*)&gs_pdf14_RGB_device;
+ new_14procs = &rgb_pdf14_procs;
+ }
new_polarity = GX_CINFO_POLARITY_ADDITIVE;
- new_num_comps = 3;
- pdevproto = (pdf14_device *)&gs_pdf14_RGB_device;
new_additive = true;
- new_14procs = &rgb_pdf14_procs;
- new_depth = 24<<deep;
for (k = 0; k < 3; k++) {
- comp_bits[k] = 8<<deep;
- comp_shift[k] = (2-k)*(8<<deep);
+ comp_bits[k] = 8 << deep;
+ comp_shift[k] = (2 - k) * (8 << deep);
}
- }
- break;
- case DEVICE_CMYK:
- if (pdev->color_info.num_components != 4){
- update_color_info = true;
- new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
- new_num_comps = 4;
- pdevproto = (pdf14_device *)&gs_pdf14_CMYK_device;
- new_additive = false;
- /* This is needed due to the mismatched compressed encode decode
- between the device procs and the pdf14 procs */
- if (dev->color_info.num_components > 4){
+ break;
+ case 4:
+ if (pdev->sep_device) {
+ pdevproto = (pdf14_device*)&gs_pdf14_CMYKspot_device;
new_14procs = &cmykspot_pdf14_procs;
- } else {
+ }
+ else {
+ pdevproto = (pdf14_device*)&gs_pdf14_CMYK_device;
new_14procs = &cmyk_pdf14_procs;
}
- new_depth = 32<<deep;
+ new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
+ new_additive = false;
for (k = 0; k < 4; k++) {
- comp_bits[k] = 8<<deep;
- comp_shift[k] = (3-k)*(8<<deep);
- }
- }
- break;
- case ICC:
- /* Check if the profile is different. */
- dev_proc(dev, get_profile)(dev, &dev_profile);
- gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile,
- &icc_profile_dev, &render_cond);
- if (icc_profile_dev->hashcode != icc_profile->hashcode) {
- update_color_info = true;
- new_num_comps = icc_profile->num_comps;
- new_depth = icc_profile->num_comps * (8<<deep);
- switch (new_num_comps) {
- case 1:
- if (pdev->sep_device && !is_mask) {
- pdevproto = (pdf14_device *)&gs_pdf14_Grayspot_device;
- new_14procs = &grayspot_pdf14_procs;
- } else {
- pdevproto = (pdf14_device *)&gs_pdf14_Gray_device;
- new_14procs = &gray_pdf14_procs;
- }
- new_polarity = GX_CINFO_POLARITY_ADDITIVE;
- new_additive = true;
- comp_bits[0] = 8<<deep;
- comp_shift[0] = 0;
- break;
- case 3:
- if (pdev->sep_device) {
- pdevproto = (pdf14_device *)&gs_pdf14_RGBspot_device;
- new_14procs = &rgbspot_pdf14_procs;
- } else {
- pdevproto = (pdf14_device *)&gs_pdf14_RGB_device;
- new_14procs = &rgb_pdf14_procs;
- }
- new_polarity = GX_CINFO_POLARITY_ADDITIVE;
- new_additive = true;
- for (k = 0; k < 3; k++) {
- comp_bits[k] = 8<<deep;
- comp_shift[k] = (2-k)*(8<<deep);
- }
- break;
- case 4:
- if (pdev->sep_device) {
- pdevproto = (pdf14_device *)&gs_pdf14_CMYKspot_device;
- new_14procs = &cmykspot_pdf14_procs;
- } else {
- pdevproto = (pdf14_device *)&gs_pdf14_CMYK_device;
- new_14procs = &cmyk_pdf14_procs;
- }
- new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
- new_additive = false;
- for (k = 0; k < 4; k++) {
- comp_bits[k] = 8<<deep;
- comp_shift[k] = (3-k)*(8<<deep);
- }
- break;
- default:
- return gs_throw(gs_error_undefinedresult,
- "ICC Number of colorants illegal");
+ comp_bits[k] = 8 << deep;
+ comp_shift[k] = (3 - k) * (8 << deep);
}
+ break;
+ default:
+ return gs_throw(gs_error_undefinedresult,
+ "ICC Number of colorants illegal");
}
- break;
- case UNKNOWN:
- return 0;
- break;
- default:
- return_error(gs_error_rangecheck);
- break;
+ }
+ break;
+ case UNKNOWN:
+ return 0;
+ break;
+ default:
+ return_error(gs_error_rangecheck);
+ break;
}
if (!update_color_info) {
+ /* Profile not updated */
+ new_group_color->icc_profile = NULL;
if_debug0m('v', pdev->memory, "[v]procs not updated\n");
return 0;
}
@@ -5856,26 +6682,26 @@ pdf14_update_device_color_procs_push_c(gx_device *dev,
if (pdev->sep_device && !is_mask) {
int num_spots;
- if (icc_profile_dev == NULL)
+ if (old_profile == NULL)
return_error(gs_error_undefined);
- num_spots = pdev->color_info.num_components - icc_profile_dev->num_comps;
+ num_spots = pdev->color_info.num_components - old_profile->num_comps;
if (num_spots > 0) {
new_num_comps += num_spots;
for (k = 0; k < new_num_comps; k++) {
- comp_bits[k] = 8<<deep;
- comp_shift[k] = (new_num_comps - k - 1) * (8<<deep);
+ comp_bits[k] = 8 << deep;
+ comp_shift[k] = (new_num_comps - k - 1) * (8 << deep);
}
- new_depth = (8<<deep) * new_num_comps;
+ new_depth = (8 << deep) * new_num_comps;
}
}
if (has_tags) {
new_depth += 8;
}
if_debug2m('v', pdev->memory,
- "[v]pdf14_update_device_color_procs_push_c,num_components_old = %d num_components_new = %d\n",
- pdev->color_info.num_components,new_num_comps);
+ "[v]pdf14_clist_push_color_model, num_components_old = %d num_components_new = %d\n",
+ pdev->color_info.num_components, new_num_comps);
/* Set new information in the device */
set_dev_proc(pdev, get_color_mapping_procs, pdevproto->static_procs->get_color_mapping_procs);
set_dev_proc(pdev, get_color_comp_index, pdevproto->static_procs->get_color_comp_index);
@@ -5886,8 +6712,8 @@ pdf14_update_device_color_procs_push_c(gx_device *dev,
pdev->color_info.max_gray = deep ? 65535 : 255;
pdev->pdf14_procs = new_14procs;
pdev->color_info.depth = new_depth;
- memset(&(pdev->color_info.comp_bits),0,GX_DEVICE_COLOR_MAX_COMPONENTS);
- memset(&(pdev->color_info.comp_shift),0,GX_DEVICE_COLOR_MAX_COMPONENTS);
+ memset(&(pdev->color_info.comp_bits), 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
+ memset(&(pdev->color_info.comp_shift), 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
memcpy(&(pdev->color_info.comp_bits), comp_bits, new_num_comps);
memcpy(&(pdev->color_info.comp_shift), comp_shift, new_num_comps);
pdev->color_info.comp_shift[new_num_comps] = new_depth - 8; /* in case we has_tags is set */
@@ -5905,55 +6731,55 @@ pdf14_update_device_color_procs_push_c(gx_device *dev,
cldev->clist_color_info.max_color = pdev->color_info.max_color;
cldev->clist_color_info.max_gray = pdev->color_info.max_gray;
/* For the ICC profiles, we want to update the ICC profile for the
- device in the ICC manager. We already stored in in pdf14_parent_color_t.
+ device. We store the original in group_color.
That will be stored in the clist and restored during the reading phase. */
- if (group_color == ICC) {
- gsicc_adjust_profile_rc(icc_profile, 1, "pdf14_update_device_color_procs_push_c");
- gsicc_adjust_profile_rc(dev->icc_struct->device_profile[0], -1, "pdf14_update_device_color_procs_push_c");
- dev->icc_struct->device_profile[0] = icc_profile;
+ if (group_color_type == ICC) {
+ gsicc_adjust_profile_rc(new_profile, 1, "pdf14_clist_push_color_model");
+ new_group_color->icc_profile = dev->icc_struct->device_profile[0];
+ dev->icc_struct->device_profile[0] = new_profile;
}
if (pdev->ctx) {
pdev->ctx->additive = new_additive;
}
- return(1); /* Lets us detect that we did do an update */
+ return 1; /* Lets us detect that we did do an update */
}
static int
-pdf14_update_device_color_procs_pop_c(gx_device *dev,gs_gstate *pgs)
+pdf14_clist_pop_color_model(gx_device *dev, gs_gstate *pgs)
{
pdf14_device *pdev = (pdf14_device *)dev;
- pdf14_parent_color_t *parent_color = pdev->trans_group_parent_cmap_procs;
+ pdf14_group_color_t *group_color = pdev->color_model_stack;
gx_device_clist_writer * cldev = (gx_device_clist_writer *)pdev->pclist_device;
- if (parent_color == NULL)
+ if (group_color == NULL)
return_error(gs_error_unknownerror); /* Unmatched group pop */
- if_debug0m('v', pdev->memory, "[v]pdf14_update_device_color_procs_pop_c\n");
+ if_debug0m('v', pdev->memory, "[v]pdf14_clist_pop_color_model\n");
/* The color procs are always pushed. Simply restore them. */
- if (parent_color->parent_color_mapping_procs == NULL &&
- parent_color->parent_color_comp_index == NULL) {
- if_debug0m('v', dev->memory, "[v]pdf14_update_device_color_procs_pop_c ERROR \n");
+ if (group_color->group_color_mapping_procs == NULL &&
+ group_color->group_color_comp_index == NULL) {
+ if_debug0m('v', dev->memory, "[v]pdf14_clist_pop_color_model ERROR \n");
} else {
if_debug2m('v', pdev->memory,
- "[v]pdf14_update_device_color_procs_pop_c,num_components_old = %d num_components_new = %d\n",
- pdev->color_info.num_components,parent_color->num_components);
- pgs->get_cmap_procs = parent_color->get_cmap_procs;
+ "[v]pdf14_clist_pop_color_model, num_components_old = %d num_components_new = %d\n",
+ pdev->color_info.num_components,group_color->num_components);
+ pgs->get_cmap_procs = group_color->get_cmap_procs;
gx_set_cmap_procs(pgs, dev);
- set_dev_proc(pdev, get_color_mapping_procs, parent_color->parent_color_mapping_procs);
- set_dev_proc(pdev, get_color_comp_index, parent_color->parent_color_comp_index);
- pdev->color_info.polarity = parent_color->polarity;
- pdev->color_info.depth = parent_color->depth;
- pdev->color_info.num_components = parent_color->num_components;
- pdev->blend_procs = parent_color->parent_blending_procs;
- pdev->pdf14_procs = parent_color->unpack_procs;
- pdev->color_info.max_color = parent_color->max_color;
- pdev->color_info.max_gray = parent_color->max_gray;
- set_dev_proc(pdev, encode_color, parent_color->encode);
- set_dev_proc(pdev, decode_color, parent_color->decode);
- memcpy(&(pdev->color_info.comp_bits),&(parent_color->comp_bits),
+ set_dev_proc(pdev, get_color_mapping_procs, group_color->group_color_mapping_procs);
+ set_dev_proc(pdev, get_color_comp_index, group_color->group_color_comp_index);
+ pdev->color_info.polarity = group_color->polarity;
+ pdev->color_info.depth = group_color->depth;
+ pdev->color_info.num_components = group_color->num_components;
+ pdev->blend_procs = group_color->blend_procs;
+ pdev->pdf14_procs = group_color->unpack_procs;
+ pdev->color_info.max_color = group_color->max_color;
+ pdev->color_info.max_gray = group_color->max_gray;
+ set_dev_proc(pdev, encode_color, group_color->encode);
+ set_dev_proc(pdev, decode_color, group_color->decode);
+ memcpy(&(pdev->color_info.comp_bits),&(group_color->comp_bits),
GX_DEVICE_COLOR_MAX_COMPONENTS);
- memcpy(&(pdev->color_info.comp_shift),&(parent_color->comp_shift),
+ memcpy(&(pdev->color_info.comp_shift),&(group_color->comp_shift),
GX_DEVICE_COLOR_MAX_COMPONENTS);
/* clist writer fill rect has no access to gs_gstate */
/* and it forwards the target device. this information */
@@ -5963,95 +6789,42 @@ pdf14_update_device_color_procs_pop_c(gx_device *dev,gs_gstate *pgs)
cldev->clist_color_info.num_components = pdev->color_info.num_components;
cldev->clist_color_info.max_color = pdev->color_info.max_color;
cldev->clist_color_info.max_gray = pdev->color_info.max_gray;
- memcpy(&(cldev->clist_color_info.comp_bits),&(parent_color->comp_bits),
+ memcpy(&(cldev->clist_color_info.comp_bits),&(group_color->comp_bits),
GX_DEVICE_COLOR_MAX_COMPONENTS);
- memcpy(&(cldev->clist_color_info.comp_shift),&(parent_color->comp_shift),
+ memcpy(&(cldev->clist_color_info.comp_shift),&(group_color->comp_shift),
GX_DEVICE_COLOR_MAX_COMPONENTS);
if (pdev->ctx){
- pdev->ctx->additive = parent_color->isadditive;
+ pdev->ctx->additive = group_color->isadditive;
}
/* The device profile must be restored. */
- gsicc_adjust_profile_rc(dev->icc_struct->device_profile[0], -1, "pdf14_update_device_color_procs_pop_c");
- dev->icc_struct->device_profile[0] = parent_color->icc_profile;
- parent_color->icc_profile = NULL;
+ if (group_color->icc_profile != NULL) {
+ gsicc_adjust_profile_rc(dev->icc_struct->device_profile[0], -1, "pdf14_clist_pop_color_model");
+ dev->icc_struct->device_profile[0] = group_color->icc_profile;
+ }
if_debug0m('v', dev->memory, "[v]procs updated\n");
}
- pdf14_pop_parent_color(dev, pgs);
+ pdf14_pop_group_color(dev, pgs);
return 0;
}
-/* When a transparency group is pushed, the parent colorprocs are initialized.
- Since the color mapping procs are all based upon the device, we must have
- a nested list based upon the transparency group color space. This nesting
- must be outside the nested ctx structures to allow the nesting for the clist
- writer */
-static void
-pdf14_push_parent_color(gx_device *dev, const gs_gstate *pgs)
-{
- pdf14_device *pdev = (pdf14_device *)dev;
- pdf14_parent_color_t *new_parent_color;
- cmm_profile_t *icc_profile;
- gsicc_rendering_param_t render_cond;
- cmm_dev_profile_t *dev_profile;
-
- dev_proc(dev, get_profile)(dev, &dev_profile);
- gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile,
- &render_cond);
- if_debug0m('v', dev->memory, "[v]pdf14_push_parent_color\n");
- /* Allocate a new one */
- new_parent_color = gs_alloc_struct(dev->memory->stable_memory, pdf14_parent_color_t,
- &st_pdf14_clr,"pdf14_clr_new");
- /* Link to old one */
- new_parent_color->previous = pdev->trans_group_parent_cmap_procs;
- /* Reassign new one to dev */
- pdev->trans_group_parent_cmap_procs = new_parent_color;
- /* Initialize with values */
- new_parent_color->get_cmap_procs = pgs->get_cmap_procs;
- new_parent_color->parent_color_mapping_procs =
- dev_proc(pdev, get_color_mapping_procs);
- new_parent_color->parent_color_comp_index =
- dev_proc(pdev, get_color_comp_index);
- new_parent_color->parent_blending_procs = pdev->blend_procs;
- new_parent_color->polarity = pdev->color_info.polarity;
- new_parent_color->num_components = pdev->color_info.num_components;
- new_parent_color->unpack_procs = pdev->pdf14_procs;
- new_parent_color->depth = pdev->color_info.depth;
- new_parent_color->max_color = pdev->color_info.max_color;
- new_parent_color->max_gray = pdev->color_info.max_gray;
- new_parent_color->decode = dev_proc(pdev, decode_color);
- new_parent_color->encode = dev_proc(pdev, encode_color);
- memcpy(&(new_parent_color->comp_bits), &(pdev->color_info.comp_bits),
- GX_DEVICE_COLOR_MAX_COMPONENTS);
- memcpy(&(new_parent_color->comp_shift), &(pdev->color_info.comp_shift),
- GX_DEVICE_COLOR_MAX_COMPONENTS);
- /* The ICC manager has the ICC profile for the device */
- new_parent_color->icc_profile = icc_profile;
- gsicc_adjust_profile_rc(icc_profile, 1, "pdf14_push_parent_color");
- /* isadditive is only used in ctx */
- if (pdev->ctx) {
- new_parent_color->isadditive = pdev->ctx->additive;
- }
-}
-
/* When a transparency group is popped, the parent colorprocs must be restored.
Since the color mapping procs are all based upon the device, we must have a
nested list based upon the transparency group color space. This nesting
must be outside the nested ctx structures to allow the nesting for the
clist writer */
static void
-pdf14_pop_parent_color(gx_device *dev, const gs_gstate *pgs)
+pdf14_pop_group_color(gx_device *dev, const gs_gstate *pgs)
{
pdf14_device *pdev = (pdf14_device *)dev;
- pdf14_parent_color_t *old_parent_color_info = pdev->trans_group_parent_cmap_procs;
+ pdf14_group_color_t *group_color = pdev->color_model_stack;
+
+ if_debug0m('v', dev->memory, "[v]pdf14_pop_group_color\n");
- if_debug0m('v', dev->memory, "[v]pdf14_pop_parent_color\n");
- /* We need to compliment pdf14_push_parent color */
- if (old_parent_color_info->icc_profile != NULL)
- gsicc_adjust_profile_rc(old_parent_color_info->icc_profile, -1, "pdf14_pop_parent_color");
/* Update the link */
- pdev->trans_group_parent_cmap_procs = old_parent_color_info->previous;
+ pdev->color_model_stack = group_color->previous;
+
/* Free the old one */
- gs_free_object(dev->memory->stable_memory, old_parent_color_info, "pdf14_clr_free");
+ gs_free_object(dev->memory->stable_memory, group_color, "pdf14_clr_free");
}
static int
@@ -6066,8 +6839,14 @@ pdf14_begin_transparency_mask(gx_device *dev,
gs_int_rect rect;
int code;
int group_color_numcomps;
- gs_transparency_color_t group_color;
+ gs_transparency_color_t group_color_type;
bool deep = device_is_deep(dev);
+ pdf14_group_color_t* group_color_info;
+
+ code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
+ dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, (const gs_gstate*)pgs);
+ if (code < 0)
+ return code;
if (ptmp->subtype == TRANSPARENCY_MASK_None) {
pdf14_ctx *ctx = pdev->ctx;
@@ -6096,7 +6875,7 @@ pdf14_begin_transparency_mask(gx_device *dev,
memcpy(transfer_fn, ptmp->transfer_fn, (256+deep)<<deep);
/* If the group color is unknown, then we must use the previous group color
space or the device process color space */
- if (ptmp->group_color == UNKNOWN){
+ if (ptmp->group_color_type == UNKNOWN){
if (pdev->ctx->stack){
/* Use previous group color space */
group_color_numcomps = pdev->ctx->stack->n_chan-1; /* Remove alpha */
@@ -6106,30 +6885,30 @@ pdf14_begin_transparency_mask(gx_device *dev,
}
switch (group_color_numcomps) {
case 1:
- group_color = GRAY_SCALE;
+ group_color_type = GRAY_SCALE;
break;
case 3:
- group_color = DEVICE_RGB;
+ group_color_type = DEVICE_RGB;
break;
case 4:
- group_color = DEVICE_CMYK;
+ group_color_type = DEVICE_CMYK;
break;
default:
/* We can end up here if we are in a deviceN color space and
we have a sep output device */
- group_color = DEVICEN;
+ group_color_type = DEVICEN;
break;
}
} else {
- group_color = ptmp->group_color;
+ group_color_type = ptmp->group_color_type;
group_color_numcomps = ptmp->group_color_numcomps;
}
- /* Always update the color mapping procs. Otherwise we end up
- fowarding to the target device. */
- code = pdf14_update_device_color_procs(dev, group_color, ptmp->icc_hashcode,
- pgs, ptmp->iccprofile, true);
- if (code < 0)
- return code;
+
+ group_color_info = pdf14_push_color_model(dev, group_color_type, ptmp->icc_hashcode,
+ ptmp->iccprofile, true);
+ if (group_color_info == NULL)
+ return gs_error_VMerror;
+
/* Note that the soft mask always follows the group color requirements even
when we have a separable device */
code = pdf14_push_transparency_mask(pdev->ctx, &rect, bg_alpha,
@@ -6141,7 +6920,8 @@ pdf14_begin_transparency_mask(gx_device *dev,
ptmp->Background,
ptmp->Matte_components,
ptmp->Matte,
- ptmp->GrayBackground);
+ ptmp->GrayBackground,
+ group_color_info);
if (code < 0)
return code;
@@ -6152,7 +6932,7 @@ static int
pdf14_end_transparency_mask(gx_device *dev, gs_gstate *pgs)
{
pdf14_device *pdev = (pdf14_device *)dev;
- pdf14_parent_color_t *parent_color;
+ pdf14_group_color_t *group_color;
int ok;
if_debug0m('v', dev->memory, "pdf14_end_transparency_mask\n");
@@ -6165,35 +6945,31 @@ pdf14_end_transparency_mask(gx_device *dev, gs_gstate *pgs)
* to a mismatch between the Smask color space
* and the Smask blending space */
if (pdev->ctx->stack != NULL ) {
- parent_color = pdev->ctx->stack->parent_color_info;
- if (!(parent_color->parent_color_mapping_procs == NULL &&
- parent_color->parent_color_comp_index == NULL)) {
- pgs->get_cmap_procs = parent_color->get_cmap_procs;
+ group_color = pdev->ctx->stack->group_color_info;
+ if (!(group_color->group_color_mapping_procs == NULL &&
+ group_color->group_color_comp_index == NULL)) {
+ pgs->get_cmap_procs = group_color->get_cmap_procs;
gx_set_cmap_procs(pgs, dev);
- set_dev_proc(pdev, get_color_mapping_procs, parent_color->parent_color_mapping_procs);
- set_dev_proc(pdev, get_color_comp_index, parent_color->parent_color_comp_index);
- pdev->color_info.polarity = parent_color->polarity;
- pdev->color_info.num_components = parent_color->num_components;
- pdev->color_info.depth = parent_color->depth;
- pdev->blend_procs = parent_color->parent_blending_procs;
- pdev->ctx->additive = parent_color->isadditive;
- pdev->pdf14_procs = parent_color->unpack_procs;
- pdev->color_info.max_color = parent_color->max_color;
- pdev->color_info.max_gray = parent_color->max_gray;
- parent_color->get_cmap_procs = NULL;
- parent_color->parent_color_comp_index = NULL;
- parent_color->parent_color_mapping_procs = NULL;
- set_dev_proc(pdev, encode_color, parent_color->encode);
- set_dev_proc(pdev, decode_color, parent_color->decode);
- memcpy(&(pdev->color_info.comp_bits),&(parent_color->comp_bits),
+ set_dev_proc(pdev, get_color_mapping_procs, group_color->group_color_mapping_procs);
+ set_dev_proc(pdev, get_color_comp_index, group_color->group_color_comp_index);
+ pdev->color_info.polarity = group_color->polarity;
+ pdev->color_info.num_components = group_color->num_components;
+ pdev->color_info.depth = group_color->depth;
+ pdev->blend_procs = group_color->blend_procs;
+ pdev->ctx->additive = group_color->isadditive;
+ pdev->pdf14_procs = group_color->unpack_procs;
+ pdev->color_info.max_color = group_color->max_color;
+ pdev->color_info.max_gray = group_color->max_gray;
+ set_dev_proc(pdev, encode_color, group_color->encode);
+ set_dev_proc(pdev, decode_color, group_color->decode);
+ memcpy(&(pdev->color_info.comp_bits),&(group_color->comp_bits),
GX_DEVICE_COLOR_MAX_COMPONENTS);
- memcpy(&(pdev->color_info.comp_shift),&(parent_color->comp_shift),
+ memcpy(&(pdev->color_info.comp_shift),&(group_color->comp_shift),
GX_DEVICE_COLOR_MAX_COMPONENTS);
/* Take care of the ICC profile */
- if (parent_color->icc_profile != NULL) {
+ if (group_color->icc_profile != NULL) {
gsicc_adjust_profile_rc(dev->icc_struct->device_profile[0], -1, "pdf14_end_transparency_mask");
- dev->icc_struct->device_profile[0] = parent_color->icc_profile;
- parent_color->icc_profile = NULL;
+ dev->icc_struct->device_profile[0] = group_color->icc_profile;
}
}
}
@@ -7156,12 +7932,14 @@ gs_pdf14_device_push(gs_memory_t *mem, gs_gstate * pgs,
p14dev->color_info.comp_shift[p14dev->color_info.num_components] = p14dev->color_info.depth;
p14dev->color_info.depth += 8;
}
+
/* by definition pdf14_encode _is_ standard */
p14dev->color_info.separable_and_linear = GX_CINFO_SEP_LIN_STANDARD;
gx_device_fill_in_procs((gx_device *)p14dev);
p14dev->save_get_cmap_procs = pgs->get_cmap_procs;
pgs->get_cmap_procs = pdf14_get_cmap_procs;
gx_set_cmap_procs(pgs, (gx_device *)p14dev);
+
/* Components shift, etc have to be based upon 8 (or 16) bit */
for (k = 0; k < p14dev->color_info.num_components; k++) {
p14dev->color_info.comp_bits[k] = 8<<deep;
@@ -7178,21 +7956,19 @@ gs_pdf14_device_push(gs_memory_t *mem, gs_gstate * pgs,
code = dev_proc((gx_device *) p14dev, open_device) ((gx_device *) p14dev);
*pdev = (gx_device *) p14dev;
pdf14_set_marking_params((gx_device *)p14dev, pgs);
- p14dev->trans_group_parent_cmap_procs = NULL;
+ p14dev->color_model_stack = NULL;
+
/* In case we have alphabits set */
p14dev->color_info.anti_alias = target->color_info.anti_alias;
-#if RAW_DUMP
- /* Dump the current buffer to see what we have. */
- dump_raw_buffer(p14dev->ctx->memory,
- p14dev->ctx->stack->rect.q.y-p14dev->ctx->stack->rect.p.y,
- p14dev->ctx->stack->rect.q.x-p14dev->ctx->stack->rect.p.x,
- p14dev->ctx->stack->n_planes,
- p14dev->ctx->stack->planestride, p14dev->ctx->stack->rowstride,
- "Device_Push", p14dev->ctx->stack->data,
- p14dev->ctx->stack->deep);
- global_index++;
-#endif
+ if (pdf14pct->params.is_pattern) {
+ code = pdf14_initialize_ctx((gx_device*)p14dev,
+ p14dev->color_info.num_components,
+ p14dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, (const gs_gstate*) pgs);
+ if (code < 0)
+ return code;
+ }
+
/* We should never go into this when using a blend color space */
if (use_pdf14_accum) {
const gx_device_pdf14_accum *accum_proto = NULL;
@@ -7412,18 +8188,20 @@ c_pdf14trans_write(const gs_composite_t * pct, byte * data, uint * psize,
return code;
*pbuf++ = (pparams->Isolated & 1) + ((pparams->Knockout & 1) << 1);
*pbuf++ = pparams->blend_mode;
- *pbuf++ = pparams->group_color;
+ *pbuf++ = pparams->group_color_type;
+ *pbuf++ = pparams->page_group;
put_value(pbuf, pparams->group_color_numcomps);
put_value(pbuf, pparams->opacity);
put_value(pbuf, pparams->shape);
put_value(pbuf, pparams->bbox);
+ put_value(pbuf, pparams->shade_group);
put_value(pbuf, pparams->text_group);
mask_id = pparams->mask_id;
put_value(pbuf, mask_id);
/* Color space information maybe ICC based
in this case we need to store the ICC
profile or the ID if it is cached already */
- if (pparams->group_color == ICC) {
+ if (pparams->group_color_type == ICC) {
/* Check if it is already in the ICC clist table */
hashcode = pparams->iccprofile->hashcode;
found_icc = clist_icc_searchtable(cdev, hashcode);
@@ -7448,7 +8226,7 @@ c_pdf14trans_write(const gs_composite_t * pct, byte * data, uint * psize,
if (code < 0)
return code;
put_value(pbuf, pparams->subtype);
- *pbuf++ = pparams->group_color;
+ *pbuf++ = pparams->group_color_type;
put_value(pbuf, pparams->group_color_numcomps);
*pbuf++ = pparams->replacing;
*pbuf++ = (pparams->function_is_identity) | (deep<<1);
@@ -7476,7 +8254,7 @@ c_pdf14trans_write(const gs_composite_t * pct, byte * data, uint * psize,
/* Color space information may be ICC based
in this case we need to store the ICC
profile or the ID if it is cached already */
- if (pparams->group_color == ICC) {
+ if (pparams->group_color_type == ICC) {
/* Check if it is already in the ICC clist table */
hashcode = pparams->iccprofile->hashcode;
found_icc = clist_icc_searchtable(cdev, hashcode);
@@ -7632,11 +8410,13 @@ c_pdf14trans_read(gs_composite_t * * ppct, const byte * data,
params.Isolated = (*data) & 1;
params.Knockout = (*data++ >> 1) & 1;
params.blend_mode = *data++;
- params.group_color = *data++; /* Trans group color */
+ params.group_color_type = *data++; /* Trans group color */
+ params.page_group = *data++;
read_value(data,params.group_color_numcomps); /* color group size */
read_value(data, params.opacity);
read_value(data, params.shape);
read_value(data, params.bbox);
+ read_value(data, params.shade_group);
read_value(data, params.text_group);
read_value(data, params.mask_id);
read_value(data, params.icc_hash);
@@ -7656,7 +8436,7 @@ c_pdf14trans_read(gs_composite_t * * ppct, const byte * data,
*/
data = cmd_read_matrix(&params.ctm, data);
read_value(data, params.subtype);
- params.group_color = *data++;
+ params.group_color_type = *data++;
read_value(data, params.group_color_numcomps);
params.replacing = *data++;
params.function_is_identity = *data & 1;
@@ -8559,7 +9339,7 @@ pdf14_ret_devn_params(gx_device *pdev)
{
pdf14_device *p14dev = (pdf14_device *)pdev;
- return(&(p14dev->devn_params));
+ return &(p14dev->devn_params);
}
/*
@@ -8570,7 +9350,7 @@ pdf14_accum_ret_devn_params(gx_device *pdev)
{
gx_device_pdf14_accum *p14dev = (gx_device_pdf14_accum *)pdev;
- return(&(p14dev->devn_params));
+ return &(p14dev->devn_params);
}
static int
@@ -8822,18 +9602,15 @@ pdf14_clist_create_compositor(gx_device * dev, gx_device ** pcdev,
pdf14pct->params.Background_components !=
pdev->color_info.num_components)
return_error(gs_error_rangecheck);
+
/* We need to update the clist writer device procs based upon the
- the group color space. For simplicity, the list item is
+ the group color space. This ensures the proper color data is
+ written out to the device. For simplicity, the list item is
created even if the color space did not change */
- /* First store the current ones */
- pdf14_push_parent_color(dev, pgs);
-
- code = pdf14_update_device_color_procs_push_c(dev,
- pdf14pct->params.group_color,
- pdf14pct->params.icc_hash, pgs,
- pdf14pct->params.iccprofile, false);
+ code = pdf14_clist_push_color_model(dev, cdev, pgs, pdf14pct, mem, false);
if (code < 0)
return code;
+
break;
case PDF14_BEGIN_TRANS_MASK:
/* We need to update the clist writer device procs based upon the
@@ -8842,32 +9619,12 @@ pdf14_clist_create_compositor(gx_device * dev, gx_device ** pcdev,
/* First store the current ones */
if (pdf14pct->params.subtype == TRANSPARENCY_MASK_None)
break;
- pdf14_push_parent_color(dev, pgs);
- /* If we are playing back from a clist, the iccprofile may need to be loaded */
- if (pdf14pct->params.iccprofile == NULL) {
- gs_pdf14trans_params_t *pparams_noconst = (gs_pdf14trans_params_t *)&(pdf14pct->params);
-
- pparams_noconst->iccprofile = gsicc_read_serial_icc((gx_device *) cdev,
- pdf14pct->params.icc_hash);
- if (pparams_noconst->iccprofile == NULL)
- return gs_throw(-1, "ICC data not found in clist");
- /* Keep a pointer to the clist device */
- pparams_noconst->iccprofile->dev = (gx_device *)cdev;
- /* Now we need to load the rest of the profile buffer */
- if (pparams_noconst->iccprofile->buffer == NULL) {
- gcmmhprofile_t dummy = gsicc_get_profile_handle_clist(pparams_noconst->iccprofile, mem);
-
- if (dummy == NULL)
- return_error(gs_error_VMerror);
- }
- }
- /* Now update the device procs */
- code = pdf14_update_device_color_procs_push_c(dev,
- pdf14pct->params.group_color,
- pdf14pct->params.icc_hash, pgs,
- pdf14pct->params.iccprofile, true);
+
+ /* Update the color settings of the clist writer. Store information in stack */
+ code = pdf14_clist_push_color_model(dev, cdev, pgs, pdf14pct, mem, true);
if (code < 0)
return code;
+
/* Also, if the BC is a value that may end up as something other
than transparent. We must use the parent colors bounding box in
determining the range of bands in which this mask can affect.
@@ -8888,7 +9645,7 @@ pdf14_clist_create_compositor(gx_device * dev, gx_device ** pcdev,
return 0; /* Avoids spurious ET calls in interpreter */
}
pdev->text_group = PDF14_TEXTGROUP_NO_BT; /* These can't be nested */
- code = pdf14_update_device_color_procs_pop_c(dev, pgs);
+ code = pdf14_clist_pop_color_model(dev, pgs);
if (code < 0)
return code;
break;
@@ -8902,7 +9659,7 @@ pdf14_clist_create_compositor(gx_device * dev, gx_device ** pcdev,
case PDF14_END_TRANS_GROUP:
/* We need to update the clist writer device procs based upon the
the group color space. */
- code = pdf14_update_device_color_procs_pop_c(dev,pgs);
+ code = pdf14_clist_pop_color_model(dev, pgs);
if (pdev->depth_within_smask)
pdev->depth_within_smask--;
if (code < 0)
@@ -9323,7 +10080,7 @@ pdf14_clist_stroke_path(gx_device *dev, const gs_gstate *pgs,
* paint several pixels twice. */
push_group = pgs->strokeconstantalpha != 1.0 ||
!blend_is_idempotent(gs_currentblendmode(pgs));
- if (pdev->trans_group_parent_cmap_procs != NULL) {
+ if (pdev->color_model_stack != NULL) {
pinst =
(gs_pattern2_instance_t *)pdcolor->ccolor.pattern;
pinst->saved->has_transparency = true;
@@ -9470,8 +10227,9 @@ pdf14_clist_fill_stroke_path_pattern_setup(gx_device* dev, const gs_gstate* cpgs
dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) {
params.Isolated = false;
- params.group_color = UNKNOWN;
+ params.group_color_type = UNKNOWN;
params.Knockout = false;
+ params.page_group = false;
params.group_opacity = fill_alpha;
params.group_shape = 1.0;
@@ -9497,8 +10255,9 @@ pdf14_clist_fill_stroke_path_pattern_setup(gx_device* dev, const gs_gstate* cpgs
/* Push a non-isolated knockout group. Do not change the alpha or
blend modes */
params.Isolated = false;
- params.group_color = UNKNOWN;
+ params.group_color_type = UNKNOWN;
params.Knockout = true;
+ params.page_group = false;
params.group_opacity = 1.0;
params.group_shape = 1.0;
@@ -9795,6 +10554,7 @@ pdf14_clist_begin_typed_image(gx_device * dev, const gs_gstate * pgs,
if_debug0m('v', pgs->memory, "[v]Pushing special trans group for image\n");
tgp.Isolated = true;
tgp.Knockout = false;
+ tgp.page_group = false;
tgp.mask_id = 0;
tgp.image_with_SMask = false;
tgp.idle = false;
@@ -10124,7 +10884,7 @@ c_pdf14trans_clist_read_update(gs_composite_t * pcte, gx_device * cdev,
writing. */
cdev->color_info = p14dev->saved_target_color_info;
# endif
- break;
+ break;
default:
break; /* do nothing for remaining ops */
@@ -10388,9 +11148,13 @@ pdf14_increment_smask_color(gs_gstate * pgs, gx_device * dev)
result = gs_alloc_struct(pdev->memory->stable_memory, pdf14_smaskcolor_t,
&st_pdf14_smaskcolor,
"pdf14_increment_smask_color");
- if (result == NULL ) return(-1);
+ if (result == NULL)
+ return gs_error_VMerror;
+
result->profiles = gsicc_new_iccsmask(pdev->memory->stable_memory);
- if (result->profiles == NULL ) return(-1);
+ if (result->profiles == NULL)
+ return gs_error_VMerror;
+
pdev->smaskcolor = result;
result->profiles->smask_gray = pgs->icc_manager->default_gray;
@@ -10445,7 +11209,7 @@ pdf14_increment_smask_color(gs_gstate * pgs, gx_device * dev)
}
}
}
- return(0);
+ return 0;
}
static int
@@ -10527,7 +11291,7 @@ pdf14_decrement_smask_color(gs_gstate * pgs, gx_device * dev)
pdf14_free_smask_color(pdev);
}
}
- return(0);
+ return 0;
}
static void
@@ -10552,15 +11316,15 @@ pdf14_device_finalize(const gs_memory_t *cmem, void *vptr)
gx_device * const dev = (gx_device *)vptr;
pdf14_device * pdev = (pdf14_device *)dev;
- pdf14_cleanup_parent_color_profiles (pdev);
+ pdf14_cleanup_group_color_profiles (pdev);
if (pdev->ctx) {
pdf14_ctx_free(pdev->ctx);
pdev->ctx = NULL;
}
- while (pdev->trans_group_parent_cmap_procs) {
- pdf14_pop_parent_color(dev, NULL);
+ while (pdev->color_model_stack) {
+ pdf14_pop_group_color(dev, NULL);
}
gx_device_finalize(cmem, vptr);
}
diff --git a/base/gdevp14.h b/base/gdevp14.h
index 12186ddf1..635ab1113 100644
--- a/base/gdevp14.h
+++ b/base/gdevp14.h
@@ -97,18 +97,15 @@ struct pdf14_mask_s {
};
-/* A structure to hold information
- * about the parent color related
- * procs and other information.
- * These may change depending upon
- * if the blending space is different
- * than the base space. The structure
- * is a list that is updated upon
- * every transparency group push and pop */
-
-typedef struct pdf14_parent_color_s pdf14_parent_color_t;
-
-struct pdf14_parent_color_s {
+/* A structure to hold information about the group color related
+ * procs and other information. These may change depending upon
+ * if the blending space is different than the base space.
+ * The structure is a list that is updated upo every transparency
+ * group push and pop */
+
+typedef struct pdf14_group_color_s pdf14_group_color_t;
+
+struct pdf14_group_color_s {
int num_components;
bool isadditive;
gx_color_polarity_t polarity;
@@ -119,14 +116,14 @@ struct pdf14_parent_color_s {
uint max_color; /* Causes issues if these are not maintained */
const gx_color_map_procs *(*get_cmap_procs)(const gs_gstate *,
const gx_device *);
- const gx_cm_color_map_procs *(*parent_color_mapping_procs)(const gx_device *);
+ const gx_cm_color_map_procs *(*group_color_mapping_procs)(const gx_device *);
gx_color_index (*encode)(gx_device *, const gx_color_value value[]);
int (*decode)(gx_device *, gx_color_index, gx_color_value *);
- int (*parent_color_comp_index)(gx_device *, const char *, int, int);
+ int (*group_color_comp_index)(gx_device *, const char *, int, int);
const pdf14_procs_t * unpack_procs;
- const pdf14_nonseparable_blending_procs_t * parent_blending_procs;
+ const pdf14_nonseparable_blending_procs_t * blend_procs;
cmm_profile_t *icc_profile; /* Opaque to GC. Allocated in non-gc memory */
- pdf14_parent_color_t *previous;
+ pdf14_group_color_t *previous;
};
typedef struct pdf14_ctx_s pdf14_ctx;
@@ -146,7 +143,9 @@ struct pdf14_buf_s {
bool has_tags;
bool deep; /* false => 8 bits, true => 16 bits */
bool page_group;
-
+ bool group_popped; /* Can occur in cases where clist created shading groups */
+ /* If there is a group and is pushed and popped, with
+ nothing drawn AND the clist created shading groups */
gs_int_rect rect;
/* Note: the traditional GS name for rowstride is "raster" */
@@ -169,7 +168,7 @@ struct pdf14_buf_s {
gs_transparency_mask_subtype_t SMask_SubType;
uint mask_id;
- pdf14_parent_color_t *parent_color_info;
+ pdf14_group_color_t *group_color_info;
gs_transparency_color_t color_space; /* Different groups can have different spaces for blending */
gs_memory_t *memory;
@@ -190,6 +189,9 @@ struct pdf14_ctx_s {
int smask_depth; /* used to catch smasks embedded in smasks. bug691803 */
bool smask_blend;
bool deep; /* If true, 16 bit data, false, 8 bit data. */
+ bool has_tags;
+ int num_spots;
+ pdf14_group_color_t* base_color;
};
typedef struct gs_pdf14trans_params_s gs_pdf14trans_params_t;
@@ -268,7 +270,7 @@ typedef struct pdf14_device_s {
dev_proc_get_color_mapping_procs(*my_get_color_mapping_procs);
dev_proc_get_color_comp_index(*my_get_color_comp_index);
- pdf14_parent_color_t *trans_group_parent_cmap_procs;
+ pdf14_group_color_t *color_model_stack;
} pdf14_device_t;
@@ -318,4 +320,6 @@ int gs_pdf14_device_color_mon_set(gx_device *pdev, bool monitoring);
/* depth are critical since these must match when reading back colors. */
bool pdf14_ok_to_optimize(gx_device *bdev);
+
+
#endif /* gdevp14_INCLUDED */
diff --git a/base/gsicc_cache.c b/base/gsicc_cache.c
index f77232e10..bc1d7a9f5 100644
--- a/base/gsicc_cache.c
+++ b/base/gsicc_cache.c
@@ -1790,9 +1790,11 @@ gsicc_init_buffer(gsicc_bufferdesc_t *buffer_desc, unsigned char num_chan, unsig
buffer_desc->num_rows = num_rows;
buffer_desc->pixels_per_row = pixels_per_row;
- /* sample endianess is consistent across platforms */
+#if ARCH_IS_BIG_ENDIAN
+ buffer_desc->little_endian = false;
+#else
buffer_desc->little_endian = true;
-
+#endif
}
/* Return the proper component numbers based upon the profiles of the device.
diff --git a/base/gstparam.h b/base/gstparam.h
index 10b37a4b9..44093bc93 100644
--- a/base/gstparam.h
+++ b/base/gstparam.h
@@ -76,10 +76,12 @@ typedef struct gs_transparency_group_params_s {
float group_opacity;
bool image_with_SMask;
int text_group;
+ bool shade_group;
+ bool page_group;
bool idle;
uint mask_id;
int group_color_numcomps;
- gs_transparency_color_t group_color;
+ gs_transparency_color_t group_color_type;
int64_t icc_hashcode; /* Needed when we are doing clist reading */
cmm_profile_t *iccprofile; /* The profile */
} gs_transparency_group_params_t;
@@ -117,7 +119,7 @@ typedef struct gs_transparency_mask_params_s {
typedef struct gx_transparency_mask_params_s {
gs_transparency_mask_subtype_t subtype;
int group_color_numcomps;
- gs_transparency_color_t group_color;
+ gs_transparency_color_t group_color_type;
int Background_components;
int Matte_components;
float Background[GS_CLIENT_COLOR_MAX_COMPONENTS];
diff --git a/base/gstrans.c b/base/gstrans.c
index 1d8d6f07d..fba21f7b0 100644
--- a/base/gstrans.c
+++ b/base/gstrans.c
@@ -170,12 +170,14 @@ gs_trans_group_params_init(gs_transparency_group_params_t *ptgp, float opacity)
ptgp->ColorSpace = NULL; /* bogus, but can't do better */
ptgp->Isolated = false;
ptgp->Knockout = false;
+ ptgp->page_group = false;
ptgp->text_group = PDF14_TEXTGROUP_NO_BT;
ptgp->image_with_SMask = false;
ptgp->mask_id = 0;
ptgp->iccprofile = NULL;
ptgp->group_opacity = opacity;
ptgp->group_shape = 1.0;
+ ptgp->shade_group = false;
}
int
@@ -209,12 +211,14 @@ gs_begin_transparency_group(gs_gstate *pgs,
params.pdf14_op = group_type;
params.Isolated = ptgp->Isolated;
params.Knockout = ptgp->Knockout;
+ if (group_type == PDF14_BEGIN_TRANS_PAGE_GROUP)
+ params.page_group = true;
params.image_with_SMask = ptgp->image_with_SMask;
params.opacity = ptgp->group_opacity;
params.shape = ptgp->group_shape;
params.blend_mode = pgs->blend_mode;
params.text_group = ptgp->text_group;
-
+ params.shade_group = ptgp->shade_group;
/* This function is called during the c-list writer side.
Store some information so that we know what the color space is
so that we can adjust according later during the clist reader.
@@ -239,11 +243,14 @@ gs_begin_transparency_group(gs_gstate *pgs,
target device (process color model). Here we just want
to set it as a unknown type for clist writing, as we will take care
of using the parent group color space later during clist reading.
- */
-
+ Also, if the group was not isolated we MUST use the parent group
+ color space regardless of what the group color space is specified to be.
+ Note that the page group should always be isolated */
+ if (group_type == PDF14_BEGIN_TRANS_PAGE_GROUP)
+ params.Isolated = true;
if (ptgp->ColorSpace == NULL || params.Isolated != true) {
- params.group_color = UNKNOWN;
+ params.group_color_type = UNKNOWN;
params.group_color_numcomps = 0;
} else {
/* The /CS parameter was present. Use what was set. Currently
@@ -258,7 +265,7 @@ gs_begin_transparency_group(gs_gstate *pgs,
/* Blending space is ICC based. If we are doing c-list rendering
we will need to write this color space into the clist.
*/
- params.group_color = ICC;
+ params.group_color_type = ICC;
params.group_color_numcomps =
blend_color_space->cmm_icc_profile_data->num_comps;
/* Get the ICC profile */
@@ -281,12 +288,12 @@ gs_begin_transparency_group(gs_gstate *pgs,
/* We can end up here if we are in a deviceN color space and
we have a sep output device */
profile = NULL;
- params.group_color = DEVICEN;
+ params.group_color_type = DEVICEN;
params.group_color_numcomps = cs_num_components(blend_color_space);
break;
}
if (profile != NULL) {
- params.group_color = ICC;
+ params.group_color_type = ICC;
params.group_color_numcomps = profile->num_comps;
params.iccprofile = profile;
params.icc_hash = profile->hashcode;
@@ -306,8 +313,8 @@ gs_begin_transparency_group(gs_gstate *pgs,
else
dmputs(pgs->memory, " (no CS)");
- dmprintf3(pgs->memory, " Isolated = %d Knockout = %d text_group = %d\n",
- ptgp->Isolated, ptgp->Knockout, ptgp->text_group);
+ dmprintf4(pgs->memory, " Isolated = %d Knockout = %d text_group = %d page_group = %d\n",
+ ptgp->Isolated, ptgp->Knockout, ptgp->text_group, ptgp->page_group);
}
#endif
params.bbox = *pbbox;
@@ -326,12 +333,14 @@ gx_begin_transparency_group(gs_gstate * pgs, gx_device * pdev,
return_error(gs_error_rangecheck);
tgp.Isolated = pparams->Isolated;
tgp.Knockout = pparams->Knockout;
+ tgp.page_group = pparams->page_group;
tgp.idle = pparams->idle;
tgp.mask_id = pparams->mask_id;
tgp.text_group = pparams->text_group;
+ tgp.shade_group = pparams->shade_group;
/* Needed so that we do proper blending */
- tgp.group_color = pparams->group_color;
+ tgp.group_color_type = pparams->group_color_type;
tgp.group_color_numcomps = pparams->group_color_numcomps;
tgp.iccprofile = pparams->iccprofile;
tgp.icc_hashcode = pparams->icc_hash;
@@ -355,8 +364,8 @@ gx_begin_transparency_group(gs_gstate * pgs, gx_device * pdev,
cs_names[(int)gs_color_space_get_index(tgp.ColorSpace)]);
else
dmputs(pdev->memory, " (no CS)");
- dmprintf2(pdev->memory, " Isolated = %d Knockout = %d\n",
- tgp.Isolated, tgp.Knockout);
+ dmprintf2(pdev->memory, " Isolated = %d Knockout = %d page_group = %d\n",
+ tgp.Isolated, tgp.Knockout, tgp.page_group);
if (tgp.iccprofile)
dmprintf(pdev->memory, " Have ICC Profile for blending\n");
@@ -615,7 +624,7 @@ gs_begin_transparency_mask(gs_gstate * pgs,
if ( blend_color_space->cmm_icc_profile_data != NULL ) {
/* Blending space is ICC based. If we are doing c-list rendering we will
need to write this color space into the clist. */
- params.group_color = ICC;
+ params.group_color_type = ICC;
params.group_color_numcomps =
blend_color_space->cmm_icc_profile_data->num_comps;
/* Get the ICC profile */
@@ -625,7 +634,7 @@ gs_begin_transparency_mask(gs_gstate * pgs,
params.iccprofile = blend_color_space->cmm_icc_profile_data;
params.icc_hash = blend_color_space->cmm_icc_profile_data->hashcode;
} else {
- params.group_color = GRAY_SCALE;
+ params.group_color_type = GRAY_SCALE;
params.group_color_numcomps = 1; /* Need to check */
}
/* Explicitly decrement the profile data since blend_color_space may not
@@ -647,7 +656,7 @@ gx_begin_transparency_mask(gs_gstate * pgs, gx_device * pdev,
const int l = sizeof(pparams->Background[0]) * pparams->Background_components;
const int m = sizeof(pparams->Matte[0]) * pparams->Matte_components;
- tmp.group_color = pparams->group_color;
+ tmp.group_color_type = pparams->group_color_type;
tmp.subtype = pparams->subtype;
tmp.group_color_numcomps = pparams->group_color_numcomps;
tmp.Background_components = pparams->Background_components;
@@ -660,7 +669,7 @@ gx_begin_transparency_mask(gs_gstate * pgs, gx_device * pdev,
tmp.replacing = pparams->replacing;
tmp.mask_id = pparams->mask_id;
- if (tmp.group_color == ICC ) {
+ if (tmp.group_color_type == ICC ) {
/* Do I need to ref count here? */
tmp.iccprofile = pparams->iccprofile;
tmp.icc_hashcode = pparams->icc_hash;
diff --git a/base/gstrans.h b/base/gstrans.h
index 1a2f77d5f..a441bbef8 100644
--- a/base/gstrans.h
+++ b/base/gstrans.h
@@ -119,7 +119,9 @@ struct gs_pdf14trans_params_s {
gs_blend_mode_t blend_mode;
bool text_knockout;
int text_group;
+ bool page_group;
bool ais;
+ bool shade_group;
float opacity;
float shape;
float fillconstantalpha;
@@ -134,7 +136,7 @@ struct gs_pdf14trans_params_s {
bool idle; /* For clist reader.*/
uint mask_id; /* For clist reader.*/
int group_color_numcomps;
- gs_transparency_color_t group_color;
+ gs_transparency_color_t group_color_type;
int64_t icc_hash;
cmm_profile_t *iccprofile; /* The profile */
bool crop_blend_params; /* This is used when the blend params are updated
diff --git a/base/gxblend.h b/base/gxblend.h
index da15f7f39..0ac938776 100644
--- a/base/gxblend.h
+++ b/base/gxblend.h
@@ -392,10 +392,6 @@ void gx_blend_image_buffer16(byte *buf_ptr, int width, int height,
int rowstride, int planestride, int num_comp, uint16_t bg);
void gx_blend_image_buffer8to16(const byte *buf_ptr, unsigned short *buf_ptr_out,
int width, int height, int rowstride, int planestride, int num_comp, byte bg);
-int gx_put_blended_image_cmykspot(gx_device *target, byte *buf_ptr,
- int planestride, int rowstride,
- int x0, int y0, int width, int height, int num_comp, uint16_t bg,
- bool has_tags, gs_int_rect rect, gs_separations *pseparations, bool deep);
int gx_put_blended_image_custom(gx_device *target, byte *buf_ptr,
int planestride, int rowstride,
int x0, int y0, int width, int height, int num_comp, uint16_t bg, bool deep);
diff --git a/base/gxblend1.c b/base/gxblend1.c
index ae66583f5..4a10be4e6 100644
--- a/base/gxblend1.c
+++ b/base/gxblend1.c
@@ -867,14 +867,14 @@ gx_blend_image_buffer16(byte *buf_ptr_, int width, int height, int rowstride,
buf_ptr[position + planestride * comp_num] = bebg;
}
} else if (a == 0xffff) {
- /* Convert from native -> big endian */
- /* FIXME: Are compilers smart enough to spot that this is
- * a no-op on big endian hosts? */
+#if ARCH_IS_BIG_ENDIAN
+#else
for (comp_num = 0; comp_num < num_comp; comp_num++) {
comp = buf_ptr[position + planestride * comp_num];
((byte *)&buf_ptr[position + planestride * comp_num])[0] = comp>>8;
((byte *)&buf_ptr[position + planestride * comp_num])[1] = comp;
}
+#endif
} else {
a ^= 0xffff;
a += a>>15; /* a is now 0 to 0x10000 */
@@ -935,262 +935,6 @@ gx_blend_image_buffer8to16(const byte *buf_ptr_in, unsigned short *buf_ptr_out,
}
int
-gx_put_blended_image_cmykspot(gx_device *target, byte *buf_ptr, int planestride_in,
- int rowstride_in, int x0, int y0, int width, int height,
- int num_comp, uint16_t bg, bool has_tags, gs_int_rect rect,
- gs_separations * pseparations, bool deep)
-{
- int code = 0;
- int x, y, tmp, comp_num, output_comp_num;
- gx_color_index color;
- gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
- gx_color_value comp;
- int input_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
- int output_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
- int num_known_comp = 0;
- int output_num_comp = target->color_info.num_components;
- int num_sep = pseparations->num_separations++;
- int num_rows_left;
- int i;
- gx_drawing_color pdcolor;
- gs_fixed_rect rect_fixed;
- int bits_per_comp = ((target->color_info.depth - has_tags*8) /
- target->color_info.num_components);
- bool expand = (!deep && bits_per_comp > 8);
- int planestride = planestride_in;
- int rowstride = rowstride_in;
- byte *buf16_ptr = NULL;
-
- /*
- * The process color model for the PDF 1.4 compositor device is CMYK plus
- * spot colors. The target device may have only some of these colorants due
- * to the SeparationOrder device parameter. Thus we need to determine the
- * mapping between the PDF 1.4 compositor and the target device. Note:
- * There should not be a spot colorant in the PDF 1.4 device that is not
- * present in the target device.
- */
- /* Check if target processes CMYK colorants. */
- for (comp_num = 0; comp_num < 4; comp_num++) {
- const char * pcomp_name = (const char *)DeviceCMYKComponents[comp_num];
-
- output_comp_num = dev_proc(target, get_color_comp_index)
- (target, pcomp_name, strlen(pcomp_name), NO_COMP_NAME_TYPE);
- if (output_comp_num >=0 &&
- output_comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS) {
- output_map[num_known_comp] = output_comp_num;
- input_map[num_known_comp++] = comp_num;
- }
- }
- /* Check if target processes our spot colorants. */
- for (comp_num = 0; comp_num < num_sep; comp_num++) {
- output_comp_num = dev_proc(target, get_color_comp_index)
- (target, (const char *)(pseparations->names[comp_num].data),
- pseparations->names[comp_num].size, NO_COMP_NAME_TYPE);
- if (output_comp_num >= 0 &&
- output_comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS) {
- output_map[num_known_comp] = output_comp_num;
- input_map[num_known_comp++] = comp_num + 4;
- }
- }
-
- {
- /* See if the target device can handle the data in its current
- form with the alpha component */
- int alpha_offset = num_comp;
- int tag_offset = has_tags ? num_comp + 1 : 0;
- const byte *buf_ptrs[GS_CLIENT_COLOR_MAX_COMPONENTS];
-
- for (i = 0; i < num_comp; i++)
- buf_ptrs[i] = buf_ptr + i * planestride;
- code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
- rect.p.x, rect.p.y, width, height,
- rowstride,
- num_comp, tag_offset);
- if (code == 0) {
- /* Device could not handle the alpha data. Go ahead and
- preblend now. Note that if we do this, and we end up in the
- default below, we only need to repack in chunky not blend. Add
- in conversion to 16 bits if the target device is planar and
- a 16 bit device. */
-#if RAW_DUMP
- /* Dump before and after the blend to make sure we are doing that ok */
- dump_raw_buffer(target->memory, height, width, num_comp + 1, planestride, rowstride,
- "pre_final_blend", buf_ptr, deep);
- global_index++;
-#endif
- if (expand) {
- buf16_ptr = gs_alloc_bytes(target->memory,
- planestride * num_comp * 2, "gx_put_blended_image_cmykspot");
- gx_blend_image_buffer8to16(buf_ptr, (unsigned short*)buf16_ptr, width, height,
- rowstride, planestride, num_comp, bg>>8);
- planestride = planestride_in * 2;
- rowstride = rowstride_in * 2;
- for (i = 0; i < num_comp; i++)
- buf_ptrs[i] = buf16_ptr + i * planestride;
- } else {
- if (deep) {
- gx_blend_image_buffer16(buf_ptr, width, height, rowstride,
- planestride, num_comp, bg);
- } else {
- gx_blend_image_buffer(buf_ptr, width, height, rowstride,
- planestride, num_comp, bg>>8);
- }
-#if RAW_DUMP
- /* Dump before and after the blend to make sure we are doing that ok */
- dump_raw_buffer_be(target->memory, height, width, num_comp, planestride, rowstride,
- "post_final_blend", buf_ptr, deep);
- global_index++;
- /* clist_band_count++; */
-#endif
- }
- /* Try again now */
- alpha_offset = 0;
- code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
- rect.p.x, rect.p.y, width, height,
- rowstride, alpha_offset, tag_offset);
- if (code > 0) {
- /* We processed some or all of the rows. Continue until we are done */
- num_rows_left = height - code;
- while (num_rows_left > 0) {
- code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
- rect.p.x, rect.p.y + code, width,
- num_rows_left, rowstride,
- alpha_offset, tag_offset);
- if (code < 0) {
- if (buf16_ptr != NULL)
- gs_free_object(target->memory, buf16_ptr, "gx_put_blended_image_cmykspot");
- return code;
- }
- num_rows_left = num_rows_left - code;
- }
- }
- if (buf16_ptr != NULL)
- gs_free_object(target->memory, buf16_ptr, "gx_put_blended_image_cmykspot");
- return 0;
- }
- }
-
- if (buf16_ptr != NULL)
- gs_free_object(target->memory, buf16_ptr, "gx_put_blended_image_cmykspot");
- planestride = planestride_in;
- rowstride = rowstride_in;
-
- /* Clear all output colorants first */
- for (comp_num = 0; comp_num < output_num_comp; comp_num++)
- cv[comp_num] = 0;
-
- /* Send pixel data to the target device. */
- if (deep) {
- /* NOTE: buf_ptr points to big endian data */
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
-
- /* composite CMYKA, etc. pixel with over solid background */
-#define GET16_BE2NATIVE(v) \
- ((((byte *)&(v))[0]<<8) | (((byte *)&(v))[1]))
- uint16_t a = GET16_BE2NATIVE(buf_ptr[x + planestride * num_comp]);
-
- if (a == 0) {
- for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
- cv[output_map[comp_num]] = bg;
- }
- } else if (a == 0xffff) {
- for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
- comp = GET16_BE2NATIVE(buf_ptr[x + planestride * input_map[comp_num]]);
- cv[output_map[comp_num]] = comp;
- }
- } else {
- /* a ^= 0xff; */ /* No inversion here! Bug 689895 */
- for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
- comp = GET16_BE2NATIVE(buf_ptr[x + planestride * input_map[comp_num]]);
- tmp = ((comp - bg) * a) + 0x8000;
- comp += (tmp + (tmp >> 16))>>16;
- cv[output_map[comp_num]] = comp;
- }
- }
-
- /* If we have spot colors we need to encode and fill as a high level
- color if the device supports it which should always be the case
- if we are in this procedure */
- if (dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0)) {
- for (i = 0; i < output_num_comp; i++) {
- pdcolor.colors.devn.values[i] = cv[i];
- }
- pdcolor.type = gx_dc_type_devn;
- rect_fixed.p.x = int2fixed(x + x0);
- rect_fixed.p.y = int2fixed(y + y0);
- rect_fixed.q.x = int2fixed(x + x0 + 1);
- rect_fixed.q.y = int2fixed(y + y0 + 1);
- code = dev_proc(target, fill_rectangle_hl_color)(target, &rect_fixed,
- NULL, &pdcolor, NULL);
- } else {
- /* encode as a color index */
- color = dev_proc(target, encode_color)(target, cv);
- code = dev_proc(target, fill_rectangle)(target, x + x0, y + y0, 1, 1, color);
- }
- if (code < 0)
- return code;
- }
-
- buf_ptr += rowstride;
- }
- } else {
- bg >>= 8;
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
-
- /* composite CMYKA, etc. pixel with over solid background */
- byte a = buf_ptr[x + planestride * num_comp];
-
- if ((a + 1) & 0xfe) {
- /* a ^= 0xff; */ /* No inversion here! Bug 689895 */
- for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
- comp = buf_ptr[x + planestride * input_map[comp_num]];
- tmp = ((comp - bg) * a) + 0x80;
- comp += tmp + (tmp >> 8);
- cv[output_map[comp_num]] = comp;
- }
- } else if (a == 0) {
- for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
- cv[output_map[comp_num]] = bg;
- }
- } else {
- for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
- comp = buf_ptr[x + planestride * input_map[comp_num]];
- cv[output_map[comp_num]] = (comp << 8) + comp;
- }
- }
-
- /* If we have spot colors we need to encode and fill as a high level
- color if the device supports it which should always be the case
- if we are in this procedure */
- if (dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0)) {
- for (i = 0; i < output_num_comp; i++) {
- pdcolor.colors.devn.values[i] = cv[i];
- }
- pdcolor.type = gx_dc_type_devn;
- rect_fixed.p.x = int2fixed(x + x0);
- rect_fixed.p.y = int2fixed(y + y0);
- rect_fixed.q.x = int2fixed(x + x0 + 1);
- rect_fixed.q.y = int2fixed(y + y0 + 1);
- code = dev_proc(target, fill_rectangle_hl_color)(target, &rect_fixed,
- NULL, &pdcolor, NULL);
- } else {
- /* encode as a color index */
- color = dev_proc(target, encode_color)(target, cv);
- code = dev_proc(target, fill_rectangle)(target, x + x0, y + y0, 1, 1, color);
- }
- if (code < 0)
- return code;
- }
-
- buf_ptr += rowstride;
- }
- }
- return code;
-}
-
-int
gx_put_blended_image_custom(gx_device *target, byte *buf_ptr_,
int planestride, int rowstride,
int x0, int y0, int width, int height,
@@ -1275,4 +1019,4 @@ gx_put_blended_image_custom(gx_device *target, byte *buf_ptr_,
}
}
return code;
-}
+} \ No newline at end of file
diff --git a/base/gxdevsop.h b/base/gxdevsop.h
index dc7f05acf..3ba09fd2b 100644
--- a/base/gxdevsop.h
+++ b/base/gxdevsop.h
@@ -372,6 +372,13 @@ enum {
/* Private dso used to check that a printer device properly forwards to the default */
gxdso_debug_printer_check,
#endif
+ /* gxdso_supports_alpha:
+ * data = NULL
+ * size = 0
+ * Returns 1 if the rendering device supports alpha,
+ * 0 otherwise.
+ */
+ gxdso_supports_alpha,
/* Add new gxdso_ keys above this. */
gxdso_pattern__LAST
};
diff --git a/devices/devs.mak b/devices/devs.mak
index c687339dc..fe736800a 100644
--- a/devices/devs.mak
+++ b/devices/devs.mak
@@ -1464,7 +1464,7 @@ libpng_dev=$(PNGGENDIR)$(D)libpng.dev
png_i_=-include $(PNGGENDIR)$(D)libpng
$(DEVOBJ)gdevpng.$(OBJ) : $(DEVSRC)gdevpng.c\
- $(gdevprn_h) $(gdevpccm_h) $(gscdefs_h) $(png__h) $(DEVS_MAK) $(MAKEDIRS)
+ $(gdevprn_h) $(gdevpccm_h) $(gscdefs_h) $(png__h) $(gxdevsop_h) $(DEVS_MAK) $(MAKEDIRS)
$(CC_) $(I_)$(DEVI_) $(II)$(PI_)$(_I) $(PCF_) $(GLF_) $(DEVO_)gdevpng.$(OBJ) $(C_) $(DEVSRC)gdevpng.c
$(DD)pngmono.dev : $(libpng_dev) $(png_) $(GLD)page.dev $(GDEV) \
diff --git a/devices/gdevpng.c b/devices/gdevpng.c
index 4ab844fc1..fbfb3e060 100644
--- a/devices/gdevpng.c
+++ b/devices/gdevpng.c
@@ -55,6 +55,7 @@
#include "gdevpccm.h"
#include "gscdefs.h"
#include "gxdownscale.h"
+#include "gxdevsop.h"
/* ------ The device descriptors ------ */
@@ -79,6 +80,7 @@ static dev_proc_get_params(png_get_params_downscale);
static dev_proc_put_params(png_put_params_downscale);
static dev_proc_get_params(png_get_params_downscale_mfs);
static dev_proc_put_params(png_put_params_downscale_mfs);
+static dev_proc_dev_spec_op(pngalpha_spec_op);
typedef struct gx_device_png_s gx_device_png;
struct gx_device_png_s {
@@ -280,7 +282,8 @@ static const gx_device_procs pngalpha_procs =
pngalpha_fillpage,
NULL, /* push_transparency_state */
NULL, /* pop_transparency_state */
- pngalpha_put_image
+ pngalpha_put_image,
+ pngalpha_spec_op /* dev_spec_op */\
};
const gx_device_pngalpha gs_pngalpha_device = {
@@ -1072,3 +1075,15 @@ pngalpha_copy_alpha(gx_device * dev, const byte * data, int data_x,
return code;
}
}
+
+static int
+pngalpha_spec_op(gx_device* pdev, int dso, void* ptr, int size)
+{
+ switch (dso)
+ {
+ case gxdso_supports_alpha:
+ return 1;
+ }
+
+ return gdev_prn_dev_spec_op(pdev, dso, ptr, size);
+}
diff --git a/devices/vector/gdevpdft.c b/devices/vector/gdevpdft.c
index 82ed9f4b1..a963cb512 100644
--- a/devices/vector/gdevpdft.c
+++ b/devices/vector/gdevpdft.c
@@ -107,7 +107,7 @@ pdf_make_group_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams
a group color specified.
In this case, the parent group is inherited from
the previous group or the device color space */
- if (pgs != NULL && pparams->group_color != UNKNOWN) {
+ if (pgs != NULL && pparams->group_color_type != UNKNOWN) {
const gs_color_space *cs = gs_currentcolorspace_inline(pgs);
code = pdf_color_space_named(pdev, pgs, &cs_value, NULL, cs,