summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2011-05-19 15:34:31 +0100
committerRobin Watts <Robin.Watts@artifex.com>2011-05-19 15:34:31 +0100
commit44e59fd123729ba05f8728f01d13406d3e283855 (patch)
tree4b6cc65a8f893629ec21f91b40d98d398b7cb70a
parente60ed1f615f7347dc9318b2c8e17851fb3a6199a (diff)
parent3bf453e7987830459ca677c8fa1b93fbd6c4a7e3 (diff)
Merge branch 'patt_trans_clist'
-rw-r--r--gs/base/gdevnfwd.c40
-rw-r--r--gs/base/gdevp14.c528
-rw-r--r--gs/base/gdevp14.h5
-rw-r--r--gs/base/gscdevn.c13
-rw-r--r--gs/base/gscscie.c32
-rw-r--r--gs/base/gscspace.c80
-rw-r--r--gs/base/gsicc.c15
-rw-r--r--gs/base/gsicc_manage.c41
-rw-r--r--gs/base/gsptype1.c76
-rw-r--r--gs/base/gsptype1.h2
-rw-r--r--gs/base/gstrans.c6
-rw-r--r--gs/base/gstrans.h10
-rw-r--r--gs/base/gxclip.c2
-rw-r--r--gs/base/gxclrast.c12
-rw-r--r--gs/base/gxdevice.h1
-rw-r--r--gs/base/gxfillsl.h2
-rw-r--r--gs/base/gxipixel.c2
-rw-r--r--gs/base/gxp1fill.c235
-rw-r--r--gs/base/gxpcmap.c209
-rw-r--r--gs/base/gxpcolor.h16
-rw-r--r--gs/base/gxshade.c2
-rw-r--r--gs/ghostscript.vcproj4
-rw-r--r--gs/psi/zicc.c9
-rw-r--r--gs/psi/zpcolor.c24
-rw-r--r--gs/psi/ztrans.c5
-rwxr-xr-xgs/toolbin/leaks.tcl4
-rw-r--r--svg/svgdoc.c4
-rw-r--r--xps/xpspage.c8
28 files changed, 910 insertions, 477 deletions
diff --git a/gs/base/gdevnfwd.c b/gs/base/gdevnfwd.c
index 75ce84e33..da4ac2d3f 100644
--- a/gs/base/gdevnfwd.c
+++ b/gs/base/gdevnfwd.c
@@ -137,7 +137,7 @@ gx_forward_close_device(gx_device * dev)
: dev_proc(tdev, close_device)(tdev);
if (tdev)
- tdev->is_open = false; /* flag corresponds to the state */
+ tdev->is_open = false; /* flag corresponds to the state */
return code;
}
@@ -750,7 +750,7 @@ gx_forward_decode_color(gx_device * dev, gx_color_index cindex, gx_color_value c
gx_device_forward * const fdev = (gx_device_forward *)dev;
gx_device *tdev = fdev->target;
- if (tdev == 0) /* If no device - just clear the color values */
+ if (tdev == 0) /* If no device - just clear the color values */
memset(colors, 0, sizeof(gx_color_value[GX_DEVICE_COLOR_MAX_COMPONENTS]));
else
dev_proc(tdev, decode_color)(tdev, cindex, colors);
@@ -892,6 +892,20 @@ gx_forward_fillpage(gx_device *dev, gs_imager_state * pis, gx_device_color *pdev
}
int
+gx_forward_create_compositor(gx_device * dev, gx_device ** pcdev,
+ const gs_composite_t * pcte,
+ gs_imager_state * pis, gs_memory_t * memory,
+ gx_device *cdev)
+{
+ gx_device_forward * const fdev = (gx_device_forward *)dev;
+ gx_device *tdev = fdev->target;
+
+ return (tdev == 0 ?
+ gx_no_create_compositor(dev, pcdev, pcte, pis, memory, cdev) :
+ dev_proc(tdev, create_compositor)(tdev, pcdev, pcte, pis, memory, cdev));
+}
+
+int
gx_forward_get_profile(gx_device *dev, cmm_dev_profile_t **profile)
{
gx_device_forward * const fdev = (gx_device_forward *)dev;
@@ -943,7 +957,7 @@ static dev_proc_strip_copy_rop(null_strip_copy_rop);
gx_forward_get_xfont_procs,\
gx_forward_get_xfont_device,\
gx_forward_map_rgb_alpha_color,\
- get_page_device, /* differs */\
+ get_page_device, /* differs */\
gx_default_get_alpha_bits,\
null_copy_alpha,\
gx_forward_get_band,\
@@ -968,15 +982,15 @@ static dev_proc_strip_copy_rop(null_strip_copy_rop);
gx_forward_get_hardware_params,\
gx_default_text_begin,\
gx_default_finish_copydevice,\
- NULL, /* begin_transparency_group */\
- NULL, /* end_transparency_group */\
- NULL, /* begin_transparency_mask */\
- NULL, /* end_transparency_mask */\
- NULL, /* discard_transparency_layer */\
- gx_default_DevGray_get_color_mapping_procs, /* get_color_mapping_procs */\
+ NULL, /* begin_transparency_group */\
+ NULL, /* end_transparency_group */\
+ NULL, /* begin_transparency_mask */\
+ NULL, /* end_transparency_mask */\
+ NULL, /* discard_transparency_layer */\
+ gx_default_DevGray_get_color_mapping_procs, /* get_color_mapping_procs */\
gx_default_DevGray_get_color_comp_index,/* get_color_comp_index */\
- gx_default_gray_fast_encode, /* encode_color */\
- null_decode_color, /* decode_color */\
+ gx_default_gray_fast_encode, /* encode_color */\
+ null_decode_color, /* decode_color */\
NULL, /* pattern_manage */\
gx_default_fill_rectangle_hl_color,\
gx_default_include_color_space,\
@@ -1000,7 +1014,7 @@ const gx_device_null gs_null_device = {
0, 0, NULLD_X_RES, NULLD_Y_RES),
null_procs(gx_forward_upright_get_initial_matrix, /* upright matrix */
gx_default_get_page_device /* not a page device */ ),
- 0 /* target */
+ 0 /* target */
};
const gx_device_null gs_nullpage_device = {
@@ -1010,7 +1024,7 @@ std_device_std_body_type_open(gx_device_null, 0, "nullpage", &st_device_null,
NULLD_X_RES, NULLD_Y_RES),
null_procs( gx_forward_get_initial_matrix, /* default matrix */
gx_page_device_get_page_device /* a page device */ ),
- 0 /* target */
+ 0 /* target */
};
static void
diff --git a/gs/base/gdevp14.c b/gs/base/gdevp14.c
index 6785c8237..3f0455474 100644
--- a/gs/base/gdevp14.c
+++ b/gs/base/gdevp14.c
@@ -866,8 +866,8 @@ pdf14_pop_transparency_group(gs_imager_state *pis, pdf14_ctx *ctx,
with a mask with transparency. In that case, the parent
and the child will have the same color space anyway */
icc_link = gsicc_get_link_profile(pis, dev, curr_icc_profile,
- nos->parent_color_info_procs->icc_profile,
- &rendering_params, pis->memory, false);
+ nos->parent_color_info_procs->icc_profile,
+ &rendering_params, pis->memory, false);
/* If the link is the identity, then we don't need to do
any color conversions */
if ( !(icc_link->is_identity) ) {
@@ -881,12 +881,12 @@ pdf14_pop_transparency_group(gs_imager_state *pis, pdf14_ctx *ctx,
new_data_buf = gs_alloc_bytes(ctx->memory,
tos->planestride*new_num_planes,
"pdf14_buf_new");
- if (new_data_buf == NULL)
- return_error(gs_error_VMerror);
+ if (new_data_buf == NULL)
+ return_error(gs_error_VMerror);
/* Copy over the noncolor planes. */
memcpy(new_data_buf + tos->planestride * num_newcolor_planes,
- tos->data + tos->planestride * curr_num_color_comp,
- tos->planestride * num_noncolor_planes);
+ tos->data + tos->planestride * curr_num_color_comp,
+ tos->planestride * num_noncolor_planes);
} else {
/* In place color conversion! */
new_data_buf = tos->data;
@@ -898,25 +898,27 @@ pdf14_pop_transparency_group(gs_imager_state *pis, pdf14_ctx *ctx,
num_rows = tos->rect.q.y - tos->rect.p.y;
num_cols = tos->rect.q.x - tos->rect.p.x;
gsicc_init_buffer(&input_buff_desc, curr_num_color_comp, 1,
- false, false, true, tos->planestride, tos->rowstride,
- num_rows, num_cols);
+ false, false, true,
+ tos->planestride, tos->rowstride,
+ num_rows, num_cols);
gsicc_init_buffer(&output_buff_desc,
- nos->parent_color_info_procs->num_components, 1,
- false, false, true, tos->planestride,
- tos->rowstride, num_rows, num_cols);
+ nos->parent_color_info_procs->num_components,
+ 1, false, false, true, tos->planestride,
+ tos->rowstride, num_rows, num_cols);
/* Transform the data. Since the pdf14 device should be
using RGB, CMYK or Gray buffers, this transform
does not need to worry about the cmap procs of
the target device. Those are handled when we do
the pdf14 put image operation */
gscms_transform_color_buffer(icc_link, &input_buff_desc,
- &output_buff_desc, tos->data,
- new_data_buf);
+ &output_buff_desc, tos->data,
+ new_data_buf);
}
/* Release the link */
gsicc_release_link(icc_link);
/* free the old object if the color spaces were different sizes */
- if( num_newcolor_planes != curr_num_color_comp ) {
+ if( !(icc_link->is_identity) &&
+ num_newcolor_planes != curr_num_color_comp ) {
gs_free_object(ctx->memory, tos->data, "pdf14_buf_free");
tos->data = new_data_buf;
}
@@ -1333,13 +1335,16 @@ pdf14_cmykspot_get_color_mapping_procs(const gx_device * dev)
return &pdf14_DeviceCMYKspot_procs;
}
-/* Used to passed along information about the buffer created by the
+/* Used to pass along information about the buffer created by the
pdf14 device. This is used by the pattern accumulator when the
- pattern contains transparency */
+ pattern contains transparency. Note that if free_device is true then
+ we need to go ahead and get the buffer data copied and free up the
+ device. This only occurs at the end of a pattern accumulation operation */
int
-pdf14_get_buffer_information(const gx_device * dev, gx_pattern_trans_t *transbuff)
+pdf14_get_buffer_information(const gx_device * dev,
+ gx_pattern_trans_t *transbuff, gs_memory_t *mem,
+ bool free_device)
{
-
const pdf14_device * pdev = (pdf14_device *)dev;
pdf14_buf *buf;
gs_int_rect rect;
@@ -1357,22 +1362,75 @@ pdf14_get_buffer_information(const gx_device * dev, gx_pattern_trans_t *transbuf
height = y1 - rect.p.y;
if (width <= 0 || height <= 0 || buf->data == NULL)
return 0;
- transbuff->pdev14 = dev;
- transbuff->n_chan = buf->n_chan;
- transbuff->planestride = buf->planestride;
- transbuff->rowstride = buf->rowstride;
- transbuff->transbytes = buf->data;
+ transbuff->n_chan = buf->n_chan;
transbuff->has_shape = buf->has_shape;
- transbuff->width = width;
- transbuff->height = height;
- transbuff->rect = rect;
+ transbuff->width = buf->rect.q.x - buf->rect.p.x;
+ transbuff->height = buf->rect.q.y - buf->rect.p.y;
+ if (free_device) {
+ transbuff->pdev14 = NULL;
+ transbuff->rect = rect;
+ if ((width < transbuff->width) || (height < transbuff->height)) {
+ /* If the bbox is smaller than the whole buffer than go ahead and
+ create a new one to use. This can occur if we drew in a smaller
+ area than was specified by the transparency group rect. */
+ int rowstride = (width + 3) & -4;
+ int planestride = rowstride * height;
+ int k, j;
+ byte *buff_ptr_src, *buff_ptr_des;
+
+ transbuff->planestride = planestride;
+ transbuff->rowstride = rowstride;
+ transbuff->transbytes = gs_alloc_bytes(mem, planestride*buf->n_chan,
+ "pdf14_get_buffer_information");
+ transbuff->mem = mem;
+ for (j = 0; j < transbuff->n_chan; j++) {
+ buff_ptr_src = buf->data + j * buf->planestride +
+ buf->rowstride * rect.p.y + rect.p.x;
+ buff_ptr_des = transbuff->transbytes + j * planestride;
+ for (k = 0; k < height; k++) {
+ memcpy(buff_ptr_des, buff_ptr_src,rowstride);
+ buff_ptr_des += rowstride;
+ buff_ptr_src += buf->rowstride;
+ }
+ }
+ } else {
+ /* The entire buffer is used. Go ahead and grab the pointer and
+ clear the pointer in the pdf14 device data buffer so it is not
+ freed when we close the device */
+ transbuff->planestride = buf->planestride;
+ transbuff->rowstride = buf->rowstride;
+ transbuff->transbytes = buf->data;
+ transbuff->mem = dev->memory;
+ buf->data = NULL; /* So that the buffer is not freed */
+ }
+ /* Go ahead and free up the pdf14 device */
+ dev_proc(dev, close_device)((gx_device *)dev);
+#if RAW_DUMP
+ /* Dump the buffer that should be going into the pattern */;
+ dump_raw_buffer(height, width, transbuff->n_chan,
+ transbuff->planestride, transbuff->rowstride,
+ "pdf14_pattern_buff", transbuff->transbytes);
+ global_index++;
+#endif
+ } else {
+ /* Here we are coming from one of the fill image / pattern / mask
+ operations */
+ transbuff->pdev14 = dev;
+ transbuff->planestride = buf->planestride;
+ transbuff->rowstride = buf->rowstride;
+ transbuff->transbytes = buf->data;
+ transbuff->mem = dev->memory;
+ transbuff->rect = rect;
#if RAW_DUMP
/* Dump the buffer that should be going into the pattern */;
dump_raw_buffer(height, width, buf->n_chan,
pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
- "pdf14_pattern_buff",buf->data);
+ "pdf14_pattern_buff", buf->data +
+ transbuff->rowstride * transbuff->rect.p.y +
+ transbuff->rect.p.x);
global_index++;
#endif
+ }
return(0);
}
@@ -1509,10 +1567,11 @@ pdf14_put_image(gx_device * dev, gs_imager_state * pis, gx_device * target)
default RGB to CIELAB in the put image operation. That will happen
here as we should have set the profile for the pdf14 device to RGB
and the target will be CIELAB */
+
code = dev_proc(dev, get_profile)(dev, &dev_profile);
gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile,
&(pcs->cmm_icc_profile_data), &rendering_intent);
- /* Increment to match the release of the pcs below */
+ /* pcs takes a reference to the profile data it just retrieved. */
rc_increment(pcs->cmm_icc_profile_data);
gs_image_t_init_adjust(&image, pcs, false);
image.ImageMatrix.xx = (float)width;
@@ -1876,7 +1935,8 @@ pdf14_fill_path(gx_device *dev, const gs_imager_state *pis,
gs_pattern2_instance_t *pinst = NULL;
if (pdcolor != NULL && gx_dc_is_pattern1_color(pdcolor)){
- if( gx_pattern1_get_transptr(pdcolor) != NULL){
+ if( gx_pattern1_get_transptr(pdcolor) != NULL ||
+ gx_pattern1_clist_has_trans(pdcolor) ){
/* In this case, we need to push a transparency group
and tile the pattern color, which is stored in
a pdf14 device buffer in the ctile object memember
@@ -1884,22 +1944,35 @@ pdf14_fill_path(gx_device *dev, const gs_imager_state *pis,
#if RAW_DUMP
/* Since we do not get a put_image to view what
we have do it now */
- pdf14_device * ppatdev14 = pdcolor->colors.pattern.p_tile->ttrans->pdev14;
- if (ppatdev14 != NULL) { /* can occur during clist reading */
- dump_raw_buffer(ppatdev14->ctx->stack->rect.q.y-ppatdev14->ctx->stack->rect.p.y,
- ppatdev14->ctx->stack->rect.q.x-ppatdev14->ctx->stack->rect.p.x,
- ppatdev14->ctx->stack->n_planes, ppatdev14->ctx->stack->planestride,
- ppatdev14->ctx->stack->rowstride,
- "Pattern_Fill",ppatdev14->ctx->stack->data);
- global_index++;
- } else {
- gx_pattern_trans_t *patt_trans = pdcolor->colors.pattern.p_tile->ttrans;
- dump_raw_buffer(patt_trans->rect.q.y-patt_trans->rect.p.y,
- patt_trans->rect.q.x-patt_trans->rect.p.x,
- patt_trans->n_chan,
- patt_trans->planestride, patt_trans->rowstride,
- "Pattern_Fill_clist",patt_trans->transbytes);
- global_index++;
+ if (gx_pattern1_get_transptr(pdcolor) != NULL) {
+ pdf14_device * ppatdev14 =
+ pdcolor->colors.pattern.p_tile->ttrans->pdev14;
+ if (ppatdev14 != NULL) { /* can occur during clist reading */
+ byte *buf_ptr = ppatdev14->ctx->stack->data +
+ ppatdev14->ctx->stack->rect.p.y *
+ ppatdev14->ctx->stack->rowstride +
+ ppatdev14->ctx->stack->rect.p.x;
+ dump_raw_buffer(ppatdev14->ctx->stack->rect.q.y -
+ ppatdev14->ctx->stack->rect.p.y,
+ ppatdev14->ctx->stack->rect.q.x -
+ ppatdev14->ctx->stack->rect.p.x,
+ ppatdev14->ctx->stack->n_planes,
+ ppatdev14->ctx->stack->planestride,
+ ppatdev14->ctx->stack->rowstride,
+ "Pattern_Fill",buf_ptr);
+ global_index++;
+ } else {
+ gx_pattern_trans_t *patt_trans =
+ pdcolor->colors.pattern.p_tile->ttrans;
+ dump_raw_buffer(patt_trans->rect.q.y-patt_trans->rect.p.y,
+ patt_trans->rect.q.x-patt_trans->rect.p.x,
+ patt_trans->n_chan,
+ patt_trans->planestride, patt_trans->rowstride,
+ "Pattern_Fill_clist", patt_trans->transbytes +
+ patt_trans->rect.p.y * patt_trans->rowstride +
+ patt_trans->rect.p.x);
+ global_index++;
+ }
}
#endif
code = pdf14_tile_pattern_fill(dev, &new_is, ppath,
@@ -1909,7 +1982,7 @@ pdf14_fill_path(gx_device *dev, const gs_imager_state *pis,
return code;
}
}
- if (pdcolor != NULL && gx_dc_is_pattern2_color(pdcolor)) {
+ if (pdcolor != NULL && gx_dc_is_pattern2_color(pdcolor)) {
pinst =
(gs_pattern2_instance_t *)pdcolor->ccolor.pattern;
pinst->saved->has_transparency = true;
@@ -2171,7 +2244,7 @@ pdf14_fill_mask(gx_device * orig_dev,
pushed the group */
fill_trans_buffer = new_pattern_trans_buff(p14dev->memory);
pdf14_get_buffer_information((gx_device *) p14dev,
- fill_trans_buffer);
+ fill_trans_buffer, NULL, false);
/* Store this in the appropriate place in pdcolor. This
is released later after the mask fill */
ptile->ttrans->fill_trans_buffer = fill_trans_buffer;
@@ -2211,8 +2284,9 @@ pdf14_fill_mask(gx_device * orig_dev,
has transparency */
static int
pdf14_tile_pattern_fill(gx_device * pdev, const gs_imager_state * pis,
- gx_path * ppath, const gx_fill_params * params,
- const gx_device_color * pdevc, const gx_clip_path * pcpath)
+ gx_path * ppath, const gx_fill_params * params,
+ const gx_device_color * pdevc,
+ const gx_clip_path * pcpath)
{
int code = 0;
gs_imager_state *pis_noconst = (gs_imager_state *)pis; /* Break const. */
@@ -2221,15 +2295,17 @@ pdf14_tile_pattern_fill(gx_device * pdev, const gs_imager_state * pis,
pdf14_device * p14dev = (pdf14_device *)pdev;
gs_int_rect rect;
gx_clip_rect *curr_clip_rect;
- gx_color_tile *ptile;
+ gx_color_tile *ptile = NULL;
int k;
- gx_pattern_trans_t *fill_trans_buffer;
+ gx_pattern_trans_t *fill_trans_buffer = NULL;
int ok;
gs_int_point phase; /* Needed during clist rendering for band offset */
-
+ int n_chan_tile;
gx_clip_path cpath_intersection;
+ gx_path path_ttrans;
+
if (pcpath != NULL) {
- code = gx_cpath_init_local_shared(&cpath_intersection, pcpath, pdev->memory);
+ code = gx_cpath_init_local_shared(&cpath_intersection, pcpath, ppath->memory);
if (code < 0)
return code;
} else {
@@ -2237,13 +2313,49 @@ pdf14_tile_pattern_fill(gx_device * pdev, const gs_imager_state * pis,
gx_cpath_init_local(&cpath_intersection, ppath->memory);
code = gx_cpath_from_rectangle(&cpath_intersection, &clip_box);
}
- if (ppath != NULL)
+ if (ppath != NULL) {
code = gx_cpath_intersect_with_params(&cpath_intersection, ppath,
params->rule, pis_noconst, params);
-
- /* Now let us push a transparency group into which we are
- going to tile the pattern. */
+ }
+ /* One (common) case worth optimising for is where we have a pattern that
+ * is positioned such that only one repeat of the tile is actually
+ * visible. In this case, we can restrict the size of the blending group
+ * we need to produce to be that of the actual area of the tile that is
+ * used. */
+ ptile = pdevc->colors.pattern.p_tile;
+ if (ptile->ttrans != NULL)
+ {
+ if ((cpath_intersection.outer_box.p.x < 0) ||
+ (cpath_intersection.outer_box.p.y < 0) ||
+ (cpath_intersection.outer_box.q.x > int2fixed(ptile->ttrans->width)) ||
+ (cpath_intersection.outer_box.q.y > int2fixed(ptile->ttrans->height)))
+ {
+ /* More than one repeat of the tile would be visible, so we can't
+ * use the optimisation here. (Actually, this test isn't quite
+ * right - it actually tests whether more than the '0th' repeat
+ * of the tile is visible. A better test would test if just one
+ * repeat of the tile was visible, irrespective of which one.
+ * This is (hopefully) relatively rare, and would make the code
+ * below more complex too, so we're ignoring that for now. If it
+ * becomes evident that it's a case that matters we can revisit
+ * it.) */
+ } else {
+ /* Only the 0th repeat is visible. Restrict the size further to
+ * just the used area of that patch. */
+ gx_path_init_local(&path_ttrans, ppath->memory);
+ gx_path_add_rectangle(&path_ttrans,
+ int2fixed(ptile->ttrans->rect.p.x),
+ int2fixed(ptile->ttrans->rect.p.y),
+ int2fixed(ptile->ttrans->rect.q.x),
+ int2fixed(ptile->ttrans->rect.q.y));
+ code = gx_cpath_intersect(&cpath_intersection, &path_ttrans,
+ params->rule, pis_noconst);
+ }
+ }
+ /* Now let us push a transparency group into which we are
+ * going to tile the pattern. */
if (ppath != NULL && code >= 0) {
+
gx_cpath_outer_box(&cpath_intersection, &outer_box);
rect.p.x = fixed2int(outer_box.p.x);
rect.p.y = fixed2int(outer_box.p.y);
@@ -2257,71 +2369,102 @@ pdf14_tile_pattern_fill(gx_device * pdev, const gs_imager_state * pis,
occuring it will be blended in the proper manner i.e in the tile
underlying color space. */
ptile = pdevc->colors.pattern.p_tile;
+ if (ptile->cdev == NULL) {
+ n_chan_tile = ptile->ttrans->n_chan;
+ } else {
+ n_chan_tile = ptile->cdev->common.color_info.num_components+1;
+ }
code = pdf14_push_transparency_group(p14dev->ctx, &rect,
1, 0, 255,255,
pis->blend_mode, 0,
- 0, ptile->ttrans->n_chan-1);
-
+ 0, n_chan_tile-1);
/* Set the blending procs and the is_additive setting based
upon the number of channels */
- if (ptile->ttrans->n_chan-1 < 4){
- ptile->ttrans->blending_procs = &rgb_blending_procs;
- ptile->ttrans->is_additive = true;
- } else {
- ptile->ttrans->blending_procs = &cmyk_blending_procs;
- ptile->ttrans->is_additive = false;
+ if (ptile->cdev == NULL) {
+ if (n_chan_tile-1 < 4) {
+ ptile->ttrans->blending_procs = &rgb_blending_procs;
+ ptile->ttrans->is_additive = true;
+ } else {
+ ptile->ttrans->blending_procs = &cmyk_blending_procs;
+ ptile->ttrans->is_additive = false;
+ }
}
- /* Fix the reversed bbox. Not clear on why the push group does that */
- p14dev->ctx->stack->bbox.p.x = p14dev->ctx->rect.p.x;
- p14dev->ctx->stack->bbox.p.y = p14dev->ctx->rect.p.y;
- p14dev->ctx->stack->bbox.q.x = p14dev->ctx->rect.q.x;
- p14dev->ctx->stack->bbox.q.y = p14dev->ctx->rect.q.y;
+ /* pdf14_push_transparency_group leaves the groups bbox with an
+ * invalid rectangle, presumably so that future accumulations will
+ * turn it into a valid one. Given that we have no more acumulations
+ * to do, force the bbox to our known target. */
+ *&p14dev->ctx->stack->bbox = *&rect;
/* Now lets go through the rect list and fill with the pattern */
/* First get the buffer that we will be filling */
- fill_trans_buffer = new_pattern_trans_buff(pis->memory);
- pdf14_get_buffer_information(pdev, fill_trans_buffer);
- /* Set the blending mode in the ptile based upon the current
- setting in the imager state */
- ptile->ttrans->blending_mode = pis->blend_mode;
- /* fill the rectangles */
- phase.x = pdevc->phase.x;
- phase.y = pdevc->phase.y;
- /* Based upon if the tiles overlap pick the type of rect fill that we will
- want to use */
- if (ptile->has_overlap) {
- /* This one does blending since there is tile overlap */
- ptile->ttrans->pat_trans_fill = &tile_rect_trans_blend;
- } else {
- /* This one does no blending since there is no tile overlap */
- ptile->ttrans->pat_trans_fill = &tile_rect_trans_simple;
- }
- if (cpath_intersection.rect_list->list.head != NULL){
- curr_clip_rect = cpath_intersection.rect_list->list.head->next;
- for( k = 0; k< cpath_intersection.rect_list->list.count; k++){
+ if (ptile->cdev == NULL) {
+ fill_trans_buffer = new_pattern_trans_buff(pis->memory);
+ pdf14_get_buffer_information(pdev, fill_trans_buffer, NULL, false);
+ /* Set the blending mode in the ptile based upon the current
+ setting in the imager state */
+ ptile->ttrans->blending_mode = pis->blend_mode;
+ /* Based upon if the tiles overlap pick the type of rect fill that we will
+ want to use */
+ if (ptile->has_overlap) {
+ /* This one does blending since there is tile overlap */
+ ptile->ttrans->pat_trans_fill = &tile_rect_trans_blend;
+ } else {
+ /* This one does no blending since there is no tile overlap */
+ ptile->ttrans->pat_trans_fill = &tile_rect_trans_simple;
+ }
+ /* fill the rectangles */
+ phase.x = pdevc->phase.x;
+ phase.y = pdevc->phase.y;
+ if (cpath_intersection.rect_list->list.head != NULL){
+ curr_clip_rect = cpath_intersection.rect_list->list.head->next;
+ for( k = 0; k< cpath_intersection.rect_list->list.count; k++){
+ if_debug5('v', "[v]pdf14_tile_pattern_fill, (%d, %d), %d x %d pat_id %d \n",
+ curr_clip_rect->xmin, curr_clip_rect->ymin,
+ curr_clip_rect->xmax-curr_clip_rect->xmin,
+ curr_clip_rect->ymax-curr_clip_rect->ymin, ptile->id);
+ ok = gx_trans_pattern_fill_rect(curr_clip_rect->xmin, curr_clip_rect->ymin,
+ curr_clip_rect->xmax, curr_clip_rect->ymax, ptile,
+ fill_trans_buffer, phase, pdev, pdevc);
+ curr_clip_rect = curr_clip_rect->next;
+ }
+ } else if (cpath_intersection.rect_list->list.count == 1) {
+ /* The case when there is just a single rect */
if_debug5('v', "[v]pdf14_tile_pattern_fill, (%d, %d), %d x %d pat_id %d \n",
- curr_clip_rect->xmin, curr_clip_rect->ymin,
- curr_clip_rect->xmax-curr_clip_rect->xmin,
- curr_clip_rect->ymax-curr_clip_rect->ymin, ptile->id);
- ok = gx_trans_pattern_fill_rect(curr_clip_rect->xmin, curr_clip_rect->ymin,
- curr_clip_rect->xmax, curr_clip_rect->ymax, ptile, fill_trans_buffer, phase);
- curr_clip_rect = curr_clip_rect->next;
+ cpath_intersection.rect_list->list.single.xmin,
+ cpath_intersection.rect_list->list.single.ymin,
+ cpath_intersection.rect_list->list.single.xmax-
+ cpath_intersection.rect_list->list.single.xmin,
+ cpath_intersection.rect_list->list.single.ymax-
+ cpath_intersection.rect_list->list.single.ymin,
+ ptile->id);
+ ok = gx_trans_pattern_fill_rect(cpath_intersection.rect_list->list.single.xmin,
+ cpath_intersection.rect_list->list.single.ymin,
+ cpath_intersection.rect_list->list.single.xmax,
+ cpath_intersection.rect_list->list.single.ymax,
+ ptile, fill_trans_buffer, phase, pdev, pdevc);
}
- } else if (cpath_intersection.rect_list->list.count == 1) {
- /* The case when there is just a single rect */
- if_debug5('v', "[v]pdf14_tile_pattern_fill, (%d, %d), %d x %d pat_id %d \n",
- cpath_intersection.rect_list->list.single.xmin, cpath_intersection.rect_list->list.single.ymin,
- cpath_intersection.rect_list->list.single.xmax-cpath_intersection.rect_list->list.single.xmin,
- cpath_intersection.rect_list->list.single.ymax-cpath_intersection.rect_list->list.single.ymin,
- ptile->id);
- ok = gx_trans_pattern_fill_rect(cpath_intersection.rect_list->list.single.xmin,
- cpath_intersection.rect_list->list.single.ymin,
- cpath_intersection.rect_list->list.single.xmax,
- cpath_intersection.rect_list->list.single.ymax,
- ptile, fill_trans_buffer, phase);
+ } else {
+ /* Clist pattern with transparency. Create a clip device from our
+ cpath_intersection. The above non-clist case could probably be
+ done this way too, which will reduce the amount of code here.
+ That is for another day though due to time constraints*/
+ gx_device *dev;
+ gx_device_clip clipdev;
+
+ gx_make_clip_device_on_stack(&clipdev, &cpath_intersection, pdev);
+ dev = (gx_device *)&clipdev;
+ phase.x = pdevc->phase.x;
+ phase.y = pdevc->phase.y;
+ ok = gx_trans_pattern_fill_rect(rect.p.x, rect.p.y,
+ rect.q.x - rect.p.x,
+ rect.q.y - rect.p.y,
+ ptile, fill_trans_buffer, phase,
+ dev, pdevc);
}
/* free our buffer object */
- gs_free_object(pis->memory, fill_trans_buffer, "pdf14_tile_pattern_fill");
- ptile->ttrans->fill_trans_buffer = NULL; /* Avoid GC issues */
+ if (fill_trans_buffer != NULL) {
+ gs_free_object(pis->memory, fill_trans_buffer, "pdf14_tile_pattern_fill");
+ ptile->ttrans->fill_trans_buffer = NULL; /* Avoid GC issues */
+ }
/* pop our transparency group which will force the blending */
code = pdf14_pop_transparency_group(pis, p14dev->ctx, p14dev->blend_procs,
p14dev->color_info.num_components,
@@ -2443,7 +2586,7 @@ pdf14_patt_trans_image_fill(gx_device * dev, const gs_imager_state * pis,
/* Set up the output buffer information now that we have
pushed the group */
fill_trans_buffer = new_pattern_trans_buff(pis->memory);
- pdf14_get_buffer_information(dev, fill_trans_buffer);
+ 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 */
@@ -2865,34 +3008,38 @@ gx_update_pdf14_compositor(gx_device * pdev, gs_imager_state * pis,
default: /* Should not occur. */
break;
case PDF14_PUSH_DEVICE:
- p14dev->blend_mode = 0;
- p14dev->opacity = p14dev->shape = 0.0;
- pdf14_recreate_device(mem, pis, pdev, pdf14pct);
+ if (!(params.is_pattern)) {
+ p14dev->blend_mode = 0;
+ p14dev->opacity = p14dev->shape = 0.0;
+ pdf14_recreate_device(mem, pis, pdev, pdf14pct);
+ }
break;
case PDF14_POP_DEVICE:
- if_debug0('v', "[v]gx_update_pdf14_compositor(PDF14_POP_DEVICE)\n");
- pis->get_cmap_procs = p14dev->save_get_cmap_procs;
- gx_set_cmap_procs(pis, p14dev->target);
- /* Send image out raster data to output device */
- {
- /* Make a copy so we can change the ROP */
- gs_imager_state new_is = *pis;
-
- /* We don't use the imager state log_op since this is for the */
- /* clist playback. Putting the image (band in the case of the */
- /* clist) only needs to use the default ROP to copy the data */
- new_is.log_op = rop3_default;
- p14dev->pdf14_procs->put_image(pdev, &new_is, p14dev->target);
- }
- /* Before we disable the device release any deviceN structures.
- free_devicen is set if the pdf14 device had inherited its
- deviceN parameters from the target clist device. In this
- case they should not be freed */
- if (p14dev->free_devicen) {
- devn_free_params(pdev);
+ if (!(params.is_pattern)) {
+ if_debug0('v', "[v]gx_update_pdf14_compositor(PDF14_POP_DEVICE)\n");
+ pis->get_cmap_procs = p14dev->save_get_cmap_procs;
+ gx_set_cmap_procs(pis, p14dev->target);
+ /* Send image out raster data to output device */
+ {
+ /* Make a copy so we can change the ROP */
+ gs_imager_state new_is = *pis;
+
+ /* We don't use the imager state log_op since this is for the */
+ /* clist playback. Putting the image (band in the case of the */
+ /* clist) only needs to use the default ROP to copy the data */
+ new_is.log_op = rop3_default;
+ p14dev->pdf14_procs->put_image(pdev, &new_is, p14dev->target);
+ }
+ /* Before we disable the device release any deviceN structures.
+ free_devicen is set if the pdf14 device had inherited its
+ deviceN parameters from the target clist device. In this
+ case they should not be freed */
+ if (p14dev->free_devicen) {
+ devn_free_params(pdev);
+ }
+ pdf14_disable_device(pdev);
+ pdf14_close(pdev);
}
- pdf14_disable_device(pdev);
- pdf14_close(pdev);
break;
case PDF14_BEGIN_TRANS_GROUP:
code = gx_begin_transparency_group(pis, pdev, &params);
@@ -2968,8 +3115,8 @@ pdf14_create_compositor(gx_device * dev, gx_device * * pcdev,
const gs_composite_t * pct, gs_imager_state * pis,
gs_memory_t * mem, gx_device *cdev)
{
- pdf14_device *p14dev = (pdf14_device *)dev;
- if (gs_is_pdf14trans_compositor(pct)) {
+ pdf14_device *p14dev = (pdf14_device *)dev;
+ if (gs_is_pdf14trans_compositor(pct)) {
const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
*pcdev = dev;
/* cdev, may be the clist reader device which may contain information that
@@ -3236,6 +3383,7 @@ pdf14_begin_transparency_group(gx_device *dev,
ptgp->icc_hashcode, pis, curr_profile);
if_debug0('v', "[v]Transparency group color space update\n");
} else {
+ code = 0;
/* Sep devices always blend in the components */
isolated = ptgp->Isolated;
group_color_numcomps = pdev->color_info.num_components;
@@ -4841,6 +4989,7 @@ c_pdf14trans_write(const gs_composite_t * pct, byte * data, uint * psize,
break;
case PDF14_PUSH_DEVICE:
put_value(pbuf, pparams->num_spot_colors);
+ put_value(pbuf, pparams->is_pattern);
/* If we happen to be going to a color space like CIELAB then
we are going to do our blending in default RGB and convert
to CIELAB at the end. To do this, we need to store the
@@ -4860,7 +5009,7 @@ c_pdf14trans_write(const gs_composite_t * pct, byte * data, uint * psize,
}
break;
case PDF14_POP_DEVICE:
- code = 0;
+ put_value(pbuf, pparams->is_pattern);
break;
case PDF14_END_TRANS_GROUP:
break; /* No data */
@@ -5030,9 +5179,10 @@ c_pdf14trans_read(gs_composite_t * * ppct, const byte * data,
break;
case PDF14_PUSH_DEVICE:
read_value(data, params.num_spot_colors);
+ read_value(data, params.is_pattern);
break;
case PDF14_POP_DEVICE:
- code += 0; /* A good place for a breakpoint. */
+ read_value(data, params.is_pattern);
break;
case PDF14_END_TRANS_GROUP:
code += 0; /* A good place for a breakpoint. */
@@ -6325,7 +6475,8 @@ pdf14_clist_create_compositor(gx_device * dev, gx_device ** pcdev,
code = pdf14_clist_update_params(pdev, pis, true,
&(pdf14pct->params));
if (pdf14pct->params.Background_components != 0 &&
- pdf14pct->params.Background_components != pdev->color_info.num_components)
+ 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
@@ -6990,11 +7141,11 @@ c_pdf14trans_clist_read_update(gs_composite_t * pcte, gx_device * cdev,
needs to inherit the ICC profile from the clist thread device
not the target device. */
#if !CMM_THREAD_SAFE
+ rc_increment(cl_icc_profile);
gx_monitor_enter(p14_icc_profile->lock);
rc_decrement(p14_icc_profile, "c_pdf14trans_clist_read_update");
gx_monitor_leave(p14_icc_profile->lock);
p14dev->icc_array->device_profile[0] = cl_icc_profile;
- rc_increment(cl_icc_profile);
#endif
/*
* If we are blending using spot colors (i.e. the output device
@@ -7008,7 +7159,7 @@ c_pdf14trans_clist_read_update(gs_composite_t * pcte, gx_device * cdev,
* was buffered into the output device.
*/
pclist_devn_params = dev_proc(cdev, ret_devn_params)(cdev);
- if (pclist_devn_params != NULL) {
+ if (pclist_devn_params != NULL && pclist_devn_params->page_spot_colors != 0) {
int num_comp = p14dev->color_info.num_components;
/*
* The number of components for the PDF14 device is the sum
@@ -7259,18 +7410,20 @@ pdf14_increment_smask_color(gs_imager_state * pis, gx_device * dev)
pdf14_device * pdev = (pdf14_device *) dev;
pdf14_smaskcolor_t *result;
gsicc_smask_t *smask_profiles = pis->icc_manager->smask_profiles;
+ int k;
/* See if we have profiles already in place */
if (pdev->smaskcolor != NULL) {
pdev->smaskcolor->ref_count++;
} else {
/* Allocate and swap out the current profiles. The softmask
- profiles should already b in place */
+ profiles should already be in place */
result = gs_alloc_struct(pdev->memory, pdf14_smaskcolor_t,
&st_pdf14_smaskcolor,
"pdf14_increment_smask_color");
if (result == NULL ) return(-1);
result->profiles = gsicc_new_iccsmask(pdev->memory);
+ if (result->profiles == NULL ) return(-1);
pdev->smaskcolor = result;
/* Theoretically there should not be any reason to change ref counts
on the profiles for a well-formed PDF with clean soft mask groups.
@@ -7283,6 +7436,48 @@ pdf14_increment_smask_color(gs_imager_state * pis, gx_device * dev)
pis->icc_manager->default_rgb = smask_profiles->smask_rgb;
pis->icc_manager->default_cmyk = smask_profiles->smask_cmyk;
pdev->smaskcolor->ref_count = 1;
+ /* We also need to update the profile that is currently in the
+ color spaces of the graphic state. Otherwise this can be
+ referenced, which will result in a mismatch. What we want to do
+ is see if it was the original default and only swap in that case. */
+ if (pis->is_gstate) {
+ gs_state *pgs = (gs_state*) pis;
+ for (k = 0; k < 2; k++) {
+ gs_color_space *pcs = pgs->color[k].color_space;
+ cmm_profile_t *profile = pcs->cmm_icc_profile_data;
+ if (profile != NULL) {
+ switch(profile->data_cs) {
+ case gsGRAY:
+ if (profile->hashcode ==
+ result->profiles->smask_gray->hashcode) {
+ profile = pis->icc_manager->default_gray;
+ }
+ break;
+ case gsRGB:
+ if (profile->hashcode ==
+ result->profiles->smask_rgb->hashcode) {
+ profile = pis->icc_manager->default_rgb;
+ }
+ break;
+ case gsCMYK:
+ if (profile->hashcode ==
+ result->profiles->smask_cmyk->hashcode) {
+ profile = pis->icc_manager->default_cmyk;
+ }
+ break;
+ default:
+
+ break;
+ }
+ if (profile != pcs->cmm_icc_profile_data) {
+ rc_decrement(pcs->cmm_icc_profile_data,
+ "pdf14_increment_smask_color");
+ rc_increment(profile);
+ pcs->cmm_icc_profile_data = profile;
+ }
+ }
+ }
+ }
}
return(0);
}
@@ -7293,11 +7488,56 @@ pdf14_decrement_smask_color(gs_imager_state * pis, gx_device * dev)
pdf14_device * pdev = (pdf14_device *) dev;
pdf14_smaskcolor_t *smaskcolor = pdev->smaskcolor;
gsicc_manager_t *icc_manager = pis->icc_manager;
+ int k;
if (smaskcolor != NULL) {
smaskcolor->ref_count--;
if (smaskcolor->ref_count == 0) {
/* Lets return the profiles and clean up */
+ /* First see if we need to "reset" the profiles that are in
+ the graphic state */
+ if (pis->is_gstate) {
+ gs_state *pgs = (gs_state*) pis;
+ for (k = 0; k < 2; k++) {
+ gs_color_space *pcs = pgs->color[k].color_space;
+ cmm_profile_t *profile = pcs->cmm_icc_profile_data;
+ if (profile != NULL) {
+ switch(profile->data_cs) {
+ case gsGRAY:
+ if (profile->hashcode ==
+ pis->icc_manager->default_gray->hashcode) {
+ profile =
+ smaskcolor->profiles->smask_gray;
+ }
+ break;
+ case gsRGB:
+ if (profile->hashcode ==
+ pis->icc_manager->default_rgb->hashcode) {
+ profile =
+ smaskcolor->profiles->smask_rgb;
+ }
+ break;
+ case gsCMYK:
+ if (profile->hashcode ==
+ pis->icc_manager->default_cmyk->hashcode) {
+ profile =
+ smaskcolor->profiles->smask_cmyk;
+ }
+ break;
+ default:
+
+ break;
+ }
+ if (profile != pcs->cmm_icc_profile_data) {
+ rc_decrement(pcs->cmm_icc_profile_data,
+ "pdf14_decrement_smask_color");
+ rc_increment(profile);
+ pcs->cmm_icc_profile_data = profile;
+ }
+ }
+ }
+ }
+
/* Decrement handled in pdf14_free_smask_color */
icc_manager->default_gray = smaskcolor->profiles->smask_gray;
icc_manager->default_rgb = smaskcolor->profiles->smask_rgb;
diff --git a/gs/base/gdevp14.h b/gs/base/gdevp14.h
index 1cfb2d0ea..048f303e7 100644
--- a/gs/base/gdevp14.h
+++ b/gs/base/gdevp14.h
@@ -272,8 +272,9 @@ pdf14_put_devn_params(gx_device * pdev, gs_devn_params * pdevn_params,
/* Used to passed along information about the buffer created by the
pdf14 device. This is used by the pattern accumulator when the
pattern contains transparency */
-
-int pdf14_get_buffer_information(const gx_device * dev, gx_pattern_trans_t *transbuff);
+int pdf14_get_buffer_information(const gx_device * dev,
+ gx_pattern_trans_t *transbuff, gs_memory_t *mem,
+ bool free_device);
/* Not static due to call from pattern logic */
int pdf14_disable_device(gx_device * dev);
diff --git a/gs/base/gscdevn.c b/gs/base/gscdevn.c
index 7c376b1d5..fa94172eb 100644
--- a/gs/base/gscdevn.c
+++ b/gs/base/gscdevn.c
@@ -546,11 +546,13 @@ gx_install_DeviceN(gs_color_space * pcs, gs_state * pgs)
/* See if we have an ICC profile that we can associate with
this DeviceN color space */
if (pgs->icc_manager->device_n != NULL) {
- /* An nclr profile is in the manager. Grab one
- that matches */
- pcs->cmm_icc_profile_data = gsicc_finddevicen(pcs, pgs->icc_manager);
+ /* An nclr profile is in the manager. Grab one that matches. */
+ cmm_profile_t *profdata = gsicc_finddevicen(pcs, pgs->icc_manager);
+ if (profdata != NULL)
+ rc_increment(profdata);
if (pcs->cmm_icc_profile_data != NULL)
- rc_adjust(pcs->cmm_icc_profile_data, pcs->rc.ref_count, "gs_install_DeviceN");
+ rc_decrement(pcs->cmm_icc_profile_data, "gx_install_DeviceN");
+ pcs->cmm_icc_profile_data = profdata;
}
/* {csrc} was pgs->color_space->params.device_n.use_alt_cspace */
((gs_color_space *)pcs)->params.device_n.use_alt_cspace =
@@ -564,7 +566,8 @@ gx_install_DeviceN(gs_color_space * pcs, gs_state * pgs)
/* Need to install the nclr cspace */
code = gs_cspace_build_ICC(&nclr_pcs, NULL, pgs->memory);
nclr_pcs->cmm_icc_profile_data = pcs->cmm_icc_profile_data;
- rc_increment_cs(nclr_pcs);
+ rc_increment(pcs->cmm_icc_profile_data);
+ rc_increment_cs(nclr_pcs); // Suspicious - RJW
rc_decrement_cs(pcs->base_space, "gx_install_DeviceN");
pcs->base_space = nclr_pcs;
}
diff --git a/gs/base/gscscie.c b/gs/base/gscscie.c
index 80dbd59f0..2bb9b3de1 100644
--- a/gs/base/gscscie.c
+++ b/gs/base/gscscie.c
@@ -148,40 +148,48 @@ static void
gx_final_CIEDEFG(const gs_color_space * pcs)
{
if (pcs->icc_equivalent != NULL) {
- rc_decrement(pcs->icc_equivalent->cmm_icc_profile_data,"gx_final_CIEDEFG");
- rc_adjust_const(pcs->icc_equivalent,-1,"gx_final_CIEDEFG");
+ rc_decrement_only(pcs->icc_equivalent, "gx_final_CIEDEFG");
}
- rc_adjust_const(pcs->params.defg, -1, "gx_adjust_cspace_CIEDEFG");
+ if (pcs->cmm_icc_profile_data != NULL) {
+ rc_decrement_only(pcs->cmm_icc_profile_data, "gx_final_CIEDEFG");
+ }
+ rc_decrement_only(pcs->params.defg, "gx_final_CIEDEFG");
}
static void
gx_final_CIEDEF(const gs_color_space * pcs)
{
if (pcs->icc_equivalent != NULL) {
- rc_decrement(pcs->icc_equivalent->cmm_icc_profile_data,"gx_final_CIEDEF");
- rc_adjust_const(pcs->icc_equivalent,-1,"gx_final_CIEDEF");
+ rc_decrement_only(pcs->icc_equivalent,"gx_final_CIEDEF");
+ }
+ if (pcs->cmm_icc_profile_data != NULL) {
+ rc_decrement_only(pcs->cmm_icc_profile_data, "gx_final_CIEDEF");
}
- rc_adjust_const(pcs->params.def, -1, "gx_adjust_cspace_CIEDEF");
+ rc_decrement_only(pcs->params.def, "gx_final_CIEDEF");
}
static void
gx_final_CIEABC(const gs_color_space * pcs)
{
if (pcs->icc_equivalent != NULL) {
- rc_decrement(pcs->icc_equivalent->cmm_icc_profile_data,"gx_final_CIEABC");
- rc_adjust_const(pcs->icc_equivalent,-1,"gx_final_CIEABC");
+ rc_decrement_only(pcs->icc_equivalent,"gx_final_CIEABC");
}
- rc_adjust_const(pcs->params.abc, -1, "gx_adjust_cspace_CIEABC");
+ if (pcs->cmm_icc_profile_data != NULL) {
+ rc_decrement_only(pcs->cmm_icc_profile_data, "gx_final_CIEABC");
+ }
+ rc_decrement_only(pcs->params.abc, "gx_final_CIEABC");
}
static void
gx_final_CIEA(const gs_color_space * pcs)
{
if (pcs->icc_equivalent != NULL) {
- rc_decrement(pcs->icc_equivalent->cmm_icc_profile_data,"gx_final_CIEA");
- rc_adjust_const(pcs->icc_equivalent,-1,"gx_final_CIEA");
+ rc_decrement_only(pcs->icc_equivalent,"gx_final_CIEA");
+ }
+ if (pcs->cmm_icc_profile_data != NULL) {
+ rc_decrement_only(pcs->cmm_icc_profile_data, "gx_final_CIEA");
}
- rc_adjust_const(pcs->params.a, -1, "gx_adjust_cspace_CIEA");
+ rc_decrement_only(pcs->params.a, "gx_adjust_cspace_CIEA");
}
/* ---------------- Procedures ---------------- */
diff --git a/gs/base/gscspace.c b/gs/base/gscspace.c
index 937386466..61a93639c 100644
--- a/gs/base/gscspace.c
+++ b/gs/base/gscspace.c
@@ -222,16 +222,18 @@ gs_color_space_restrict_color(gs_client_color *pcc, const gs_color_space *pcs)
static int
gx_install_DeviceGray(gs_color_space * pcs, gs_state * pgs)
{
- if (pcs->cmm_icc_profile_data == NULL) {
- if (pgs->icc_manager->default_gray == NULL) {
- /* User params have not yet been set for the icc manager
- go ahead and init */
- gsicc_init_iccmanager(pgs);
- }
- pcs->cmm_icc_profile_data = pgs->icc_manager->default_gray;
- pcs->type = &gs_color_space_type_ICC;
- rc_adjust(pgs->icc_manager->default_gray, pcs->rc.ref_count, "gx_install_DeviceGray");
- }
+ /* If we already have profile data installed, nothing to do here. */
+ if (pcs->cmm_icc_profile_data != NULL)
+ return 0;
+
+ /* If we haven't initialised the iccmanager, do it now. */
+ if (pgs->icc_manager->default_gray == NULL)
+ gsicc_init_iccmanager(pgs);
+
+ /* pcs takes a reference to the default_gray profile data */
+ pcs->cmm_icc_profile_data = pgs->icc_manager->default_gray;
+ rc_increment(pgs->icc_manager->default_gray);
+ pcs->type = &gs_color_space_type_ICC;
return 0;
}
@@ -268,19 +270,11 @@ gs_cspace_base_space(const gs_color_space * pcspace)
void rc_increment_cs(gs_color_space *pcs)
{
rc_increment(pcs);
- if (pcs) {
- if (pcs->cmm_icc_profile_data != NULL) {
- rc_increment(pcs->cmm_icc_profile_data);
- }
- }
}
void rc_decrement_cs(gs_color_space *pcs, const char *cname) {
if (pcs) {
- if (pcs->cmm_icc_profile_data != NULL) {
- rc_decrement(pcs->cmm_icc_profile_data, cname);
- }
rc_decrement(pcs, cname);
}
}
@@ -288,9 +282,6 @@ void rc_decrement_cs(gs_color_space *pcs, const char *cname) {
void rc_decrement_only_cs(gs_color_space *pcs, const char *cname)
{
if (pcs) {
- if (pcs->cmm_icc_profile_data != NULL) {
- rc_decrement(pcs->cmm_icc_profile_data, cname);
- }
rc_decrement_only(pcs, cname);
}
}
@@ -300,9 +291,6 @@ void cs_adjust_counts_icc(gs_state *pgs, int delta)
gs_color_space *pcs = gs_currentcolorspace_inline(pgs);
if (pcs) {
- if (pcs->cmm_icc_profile_data != NULL) {
- rc_adjust(pcs->cmm_icc_profile_data, delta, "cs_adjust_counts_icc");
- }
cs_adjust_counts(pgs, delta);
}
}
@@ -320,16 +308,18 @@ gx_no_install_cspace(gs_color_space * pcs, gs_state * pgs)
static int
gx_install_DeviceRGB(gs_color_space * pcs, gs_state * pgs)
{
- if (pcs->cmm_icc_profile_data == NULL) {
- if (pgs->icc_manager->default_rgb == NULL) {
- /* User params have not yet been set for the icc manager
- go ahead and init */
- gsicc_init_iccmanager(pgs);
- }
- pcs->cmm_icc_profile_data = pgs->icc_manager->default_rgb;
- pcs->type = &gs_color_space_type_ICC;
- rc_adjust(pgs->icc_manager->default_rgb, pcs->rc.ref_count, "gx_install_DeviceRGB");
- }
+ /* If we already have profile_data, nothing to do here. */
+ if (pcs->cmm_icc_profile_data != NULL)
+ return 0;
+
+ /* If the icc manager hasn't been set up yet, then set it up. */
+ if (pgs->icc_manager->default_rgb == NULL)
+ gsicc_init_iccmanager(pgs);
+
+ /* pcs takes a reference to default_rgb */
+ pcs->cmm_icc_profile_data = pgs->icc_manager->default_rgb;
+ rc_increment(pcs->cmm_icc_profile_data);
+ pcs->type = &gs_color_space_type_ICC;
return 0;
}
@@ -337,16 +327,18 @@ gx_install_DeviceRGB(gs_color_space * pcs, gs_state * pgs)
static int
gx_install_DeviceCMYK(gs_color_space * pcs, gs_state * pgs)
{
- if (pcs->cmm_icc_profile_data == NULL) {
- if (pgs->icc_manager->default_cmyk == NULL) {
- /* User params have not yet been set for the icc manager
- go ahead and init */
- gsicc_init_iccmanager(pgs);
- }
- pcs->cmm_icc_profile_data = pgs->icc_manager->default_cmyk;
- pcs->type = &gs_color_space_type_ICC;
- rc_adjust(pgs->icc_manager->default_cmyk, pcs->rc.ref_count, "gx_install_DeviceCMYK");
- }
+ /* If we already have profile data, nothing to do here. */
+ if (pcs->cmm_icc_profile_data != NULL)
+ return 0;
+
+ /* If the icc manager hasn't been set up yet, then set it up. */
+ if (pgs->icc_manager->default_cmyk == NULL)
+ gsicc_init_iccmanager(pgs);
+
+ /* pcs takes a reference to default_cmyk */
+ pcs->cmm_icc_profile_data = pgs->icc_manager->default_cmyk;
+ rc_increment(pcs->cmm_icc_profile_data);
+ pcs->type = &gs_color_space_type_ICC;
return 0;
}
diff --git a/gs/base/gsicc.c b/gs/base/gsicc.c
index 27d336dc5..b61257100 100644
--- a/gs/base/gsicc.c
+++ b/gs/base/gsicc.c
@@ -364,13 +364,13 @@ gx_remap_ICC(const gs_client_color * pcc, const gs_color_space * pcs,
if_debug0('c',"[c]ICC remap [ ");
for (k = 0; k < num_src_comps; k++) {
if_debug1('c', "%d ",psrc[k]);
-}
+ }
if_debug0('c',"] --> [ ");
for (k = 0; k < num_des_comps; k++) {
if_debug1('c', "%d ",psrc_temp[k]);
-}
+ }
if_debug0('c',"]\n");
-}
+ }
#endif
/* Release the link */
gsicc_release_link(icc_link);
@@ -450,11 +450,10 @@ gx_concretize_ICC(
static void
gx_final_ICC(const gs_color_space * pcs)
{
- /* if (pcs->cmm_icc_profile_data != NULL) {
+ if (pcs->cmm_icc_profile_data != NULL) {
rc_decrement_only(pcs->cmm_icc_profile_data, "gx_final_ICC");
- } */
- /* rc_decrement_only(pcs->params.icc.picc_info, "gx_final_ICC"); */
}
+}
/*
* Install an ICCBased color space.
@@ -466,8 +465,8 @@ static int
gx_install_ICC(gs_color_space * pcs, gs_state * pgs)
{
/* update the stub information used by the joint caches */
- return 0;
- }
+ return 0;
+}
/*
* Constructor for ICCBased color space. As with the other color space
diff --git a/gs/base/gsicc_manage.c b/gs/base/gsicc_manage.c
index 4778e2bfe..1e345df9c 100644
--- a/gs/base/gsicc_manage.c
+++ b/gs/base/gsicc_manage.c
@@ -908,29 +908,26 @@ int
gsicc_set_gscs_profile(gs_color_space *pcs, cmm_profile_t *icc_profile,
gs_memory_t * mem)
{
- if (pcs != NULL) {
+ if (pcs == NULL)
+ return (-1);
#if ICC_DUMP
- if (icc_profile->buffer) {
- dump_icc_buffer(icc_profile->buffer_size, "set_gscs",
- icc_profile->buffer);
- global_icc_index++;
- }
+ if (icc_profile->buffer) {
+ dump_icc_buffer(icc_profile->buffer_size, "set_gscs",
+ icc_profile->buffer);
+ global_icc_index++;
+ }
#endif
- if (pcs->cmm_icc_profile_data != NULL) {
- /* There is already a profile set there */
- /* free it and then set to the new one. */
- /* should we check the hash code and retain if the same
- or place this job on the caller? */
- rc_free_icc_profile(mem, (void*) pcs->cmm_icc_profile_data,
- "gsicc_set_gscs_profile");
- pcs->cmm_icc_profile_data = icc_profile;
- return(0);
- } else {
- pcs->cmm_icc_profile_data = icc_profile;
- return(0);
- }
+
+ rc_increment(icc_profile);
+ if (pcs->cmm_icc_profile_data != NULL) {
+ /* There is already a profile set there */
+ /* free it and then set to the new one. */
+ /* should we check the hash code and retain if the same
+ or place this job on the caller? */
+ rc_decrement(pcs->cmm_icc_profile_data, "gsicc_set_gscs_profile");
}
- return(-1);
+ pcs->cmm_icc_profile_data = icc_profile;
+ return(0);
}
cmm_profile_t *
@@ -1363,14 +1360,14 @@ gsicc_get_profile_handle_buffer(unsigned char *buffer, int profile_size)
rc_increment(icc_manager->default_cmyk);
return(gs_colorspace->cmm_icc_profile_data);
/* Need to convert to an ICC form */
- break;
+ break;
case gs_color_space_index_CIEDEF:
/* For now just use default RGB to avoid segfault. MJV to fix */
gs_colorspace->cmm_icc_profile_data = icc_manager->default_rgb;
rc_increment(icc_manager->default_rgb);
return(gs_colorspace->cmm_icc_profile_data);
/* Need to convert to an ICC form */
- break;
+ break;
case gs_color_space_index_CIEABC:
gs_colorspace->cmm_icc_profile_data =
gsicc_profile_new(NULL, icc_manager->memory, NULL, 0);
diff --git a/gs/base/gsptype1.c b/gs/base/gsptype1.c
index 12b9e224f..cc9da5aec 100644
--- a/gs/base/gsptype1.c
+++ b/gs/base/gsptype1.c
@@ -517,6 +517,17 @@ gx_pattern1_get_transptr(const gx_device_color *pdevc)
return pdevc->colors.pattern.p_tile->ttrans;
}
+/* Check for if the clist in the pattern has transparency */
+int
+gx_pattern1_clist_has_trans(const gx_device_color *pdevc)
+{
+ if (pdevc->colors.pattern.p_tile->cdev != NULL) {
+ return pdevc->colors.pattern.p_tile->cdev->common.page_uses_transparency;
+ } else {
+ return 0;
+ }
+}
+
/* Check device color for Pattern Type 1. */
bool
gx_dc_is_pattern1_color_clist_based(const gx_device_color *pdevc)
@@ -867,6 +878,8 @@ gs_makepixmappattern(
* If this is not a masked pattern and if the white pixel index
* is outside of the representable range, we don't need to go to
* the trouble of accumulating a mask that will just be all 1s.
+ * Also, patterns that use transparency don't need a mask since
+ * the alpha plane of the transparency buffers will be used.
*/
gs_pattern1_instance_t *pinst =
(gs_pattern1_instance_t *)pcc->pattern;
@@ -1467,22 +1480,16 @@ gx_dc_pattern_trans_write_raster(gx_color_tile *ptile, uint offset, byte *data,
/* check if we have written it all */
if (offset1 <= size) {
-
/* Get the most that we can write */
-
int u = min(size, left);
/* copy that amount */
-
ptr = ptile->ttrans->transbytes;
-
memcpy(dp, ptr + (offset1 - size_h), u);
left -= u;
dp += u;
offset1 += u;
-
}
-
return 0;
}
@@ -1530,6 +1537,7 @@ gx_dc_pattern_write(
if (ptile->cdev == NULL)
return gx_dc_pattern_write_raster(ptile, offset, data, psize);
+ /* Here is where we write pattern-clist data */
size_b = clist_data_size(ptile->cdev, 0);
if (size_b < 0)
return_error(gs_error_unregistered);
@@ -1555,6 +1563,7 @@ gx_dc_pattern_write(
buf.tiling_type = ptile->tiling_type;
buf.is_simple = ptile->is_simple;
buf.has_overlap = ptile->has_overlap;
+ buf.uses_transparency = ptile->cdev->common.page_uses_transparency;
if (sizeof(buf) > left) {
/* For a while we require the client to provide enough buffer size. */
return_error(gs_error_unregistered); /* Must not happen. */
@@ -1669,17 +1678,13 @@ gx_dc_pattern_read_trans_buff(gx_color_tile *ptile, uint offset,
int data_size;
data_size = trans_pat->planestride * trans_pat->n_chan;
-
/* Allocate the bytes */
-
if (trans_pat->transbytes == NULL){
-
trans_pat->transbytes = gs_alloc_bytes(mem, data_size, "gx_dc_pattern_read_raster");
+ trans_pat->mem = mem;
if (trans_pat->transbytes == NULL)
return_error(gs_error_VMerror);
-
}
-
/* Read transparency buffer */
if (offset1 <= sizeof(gx_dc_serialized_tile_t) + sizeof(tile_trans_clist_info_t) + data_size ) {
@@ -1693,7 +1698,6 @@ gx_dc_pattern_read_trans_buff(gx_color_tile *ptile, uint offset,
offset1 += u;
dp += u;
}
-
return size - left;
}
@@ -1716,6 +1720,7 @@ gx_dc_pattern_read(
gx_color_tile *ptile;
int code, l;
tile_trans_clist_info_t trans_info;
+ int cache_space_needed;
if (offset == 0) {
pdevc->mask.id = gx_no_bitmap_id;
@@ -1746,10 +1751,31 @@ gx_dc_pattern_read(
left -= sizeof(buf);
offset1 += sizeof(buf);
+ if (buf.uses_transparency && !buf.is_clist){
+
+ if (sizeof(buf) + sizeof(tile_trans_clist_info_t) > size) {
+ return_error(gs_error_unregistered); /* Must not happen. */
+ }
+
+ memcpy(&trans_info, dp, sizeof(trans_info));
+ dp += sizeof(trans_info);
+ left -= sizeof(trans_info);
+ offset1 += sizeof(trans_info);
+
+ /* limit our upper bound to avoid int overflow */
+ cache_space_needed = trans_info.planestride > (0x7fffffff / 6) ? 0x7fff0000 :
+ trans_info.planestride * trans_info.n_chan;
+ } else {
+ /* the following works for raster or clist patterns */
+ cache_space_needed = buf.size_b + buf.size_c;
+ }
+ gx_pattern_cache_ensure_space((gs_imager_state *)pis, cache_space_needed);
+
code = gx_pattern_cache_get_entry((gs_imager_state *)pis, /* Break 'const'. */
buf.id, &ptile);
if (code < 0)
return code;
+ gx_pattern_cache_update_used((gs_imager_state *)pis, cache_space_needed);
pdevc->type = &gx_dc_pattern;
pdevc->colors.pattern.p_tile = ptile;
ptile->id = buf.id;
@@ -1769,15 +1795,7 @@ gx_dc_pattern_read(
/* Make a new ttrans object */
ptile->ttrans = new_pattern_trans_buff(mem);
-
- if (sizeof(buf) + sizeof(tile_trans_clist_info_t) > size) {
- return_error(gs_error_unregistered); /* Must not happen. */
- }
-
- memcpy(&trans_info, dp, sizeof(trans_info));
- dp += sizeof(trans_info);
- left -= sizeof(trans_info);
- offset1 += sizeof(trans_info);
+ /* trans_info was loaded above */
ptile->ttrans->height = trans_info.height;
ptile->ttrans->n_chan = trans_info.n_chan;
@@ -1797,14 +1815,15 @@ gx_dc_pattern_read(
return code + sizeof(buf)+sizeof(trans_info);
} else {
- code = gx_dc_pattern_read_raster(ptile, &buf, offset1, dp, left, mem);
- if (code < 0)
- return code;
- return code + sizeof(buf);
- }
+ code = gx_dc_pattern_read_raster(ptile, &buf, offset1, dp, left, mem);
+ if (code < 0)
+ return code;
+ return code + sizeof(buf);
+ }
}
+ /* Here is where we read back from the clist */
size_b = buf.size_b;
size_c = buf.size_c;
ptile->tbits.size.x = size_b; /* HACK: Use unrelated field for saving size_b between calls. */
@@ -1821,11 +1840,14 @@ gx_dc_pattern_read(
inst.size.x = buf.size.x;
inst.size.y = buf.size.y;
inst.saved = &state;
- inst.is_clist = buf.is_clist; /* tell gx_pattern_accum_alloc to use clist */
+ inst.is_clist = buf.is_clist; /* tell gx_pattern_accum_alloc to use clist */
ptile->cdev = (gx_device_clist *)gx_pattern_accum_alloc(mem, mem,
&inst, "gx_dc_pattern_read");
if (ptile->cdev == NULL)
return_error(gs_error_VMerror);
+ ptile->cdev->common.band_params.page_uses_transparency =
+ buf.uses_transparency;
+ ptile->cdev->common.page_uses_transparency = buf.uses_transparency;
code = dev_proc(&ptile->cdev->writer, open_device)((gx_device *)&ptile->cdev->writer);
if (code < 0)
return code;
diff --git a/gs/base/gsptype1.h b/gs/base/gsptype1.h
index fa985bc93..32cf7bd24 100644
--- a/gs/base/gsptype1.h
+++ b/gs/base/gsptype1.h
@@ -93,6 +93,8 @@ bool gx_dc_is_pattern1_color(const gx_device_color *pdevc);
/* Get transparency pointer */
void * gx_pattern1_get_transptr(const gx_device_color *pdevc);
+/* pattern is clist with transparency */
+int gx_pattern1_clist_has_trans(const gx_device_color *pdevc);
/* For changing the device color procs when we have a transparency situation */
diff --git a/gs/base/gstrans.c b/gs/base/gstrans.c
index 586b399e3..4d51d00e0 100644
--- a/gs/base/gstrans.c
+++ b/gs/base/gstrans.c
@@ -770,7 +770,7 @@ get_num_pdf14_spot_colors(gs_state * pgs)
}
int
-gs_push_pdf14trans_device(gs_state * pgs)
+gs_push_pdf14trans_device(gs_state * pgs, bool is_pattern)
{
gs_pdf14trans_params_t params = { 0 };
cmm_profile_t *icc_profile;
@@ -790,6 +790,7 @@ gs_push_pdf14trans_device(gs_state * pgs)
* and convert spot colors into process colors.
*/
params.num_spot_colors = get_num_pdf14_spot_colors(pgs);
+ params.is_pattern = is_pattern;
/* If we happen to be in a situation where we are going out to a device
whose profile is CIELAB then we will need to make sure that we
do our blending in RGB and convert to CIELAB when we do the put_image
@@ -802,10 +803,11 @@ gs_push_pdf14trans_device(gs_state * pgs)
}
int
-gs_pop_pdf14trans_device(gs_state * pgs)
+gs_pop_pdf14trans_device(gs_state * pgs, bool is_pattern)
{
gs_pdf14trans_params_t params = { 0 };
+ params.is_pattern = is_pattern;
params.pdf14_op = PDF14_POP_DEVICE; /* Other parameters not used */
return gs_state_update_pdf14trans(pgs, &params);
}
diff --git a/gs/base/gstrans.h b/gs/base/gstrans.h
index 85e83bc33..9b9037495 100644
--- a/gs/base/gstrans.h
+++ b/gs/base/gstrans.h
@@ -105,8 +105,8 @@ struct gs_pdf14trans_params_s {
bool mask_is_image;
gs_matrix ctm;
bool replacing;
- bool overprint;
- bool overprint_mode;
+ bool overprint;
+ bool overprint_mode;
bool idle; /* For clist reader.*/
uint mask_id; /* For clist reader.*/
int group_color_numcomps;
@@ -115,7 +115,7 @@ struct gs_pdf14trans_params_s {
cmm_profile_t *iccprofile; /* The profile */
bool crop_blend_params; /* This is used when the blend params are updated
during a transparency group push */
-
+ bool is_pattern; /* Needed to detect device push and pop for clist pattern */
};
#ifndef gs_pdf14trans_params_DEFINED
@@ -155,9 +155,9 @@ gs_transparency_state_type_t
* We have to abbreviate the procedure name because procedure names are
* only unique to 23 characters on VMS.
*/
-int gs_push_pdf14trans_device(gs_state * pgs);
+int gs_push_pdf14trans_device(gs_state * pgs, bool is_pattern);
-int gs_pop_pdf14trans_device(gs_state * pgs);
+int gs_pop_pdf14trans_device(gs_state * pgs, bool is_pattern);
void gs_trans_group_params_init(gs_transparency_group_params_t *ptgp);
diff --git a/gs/base/gxclip.c b/gs/base/gxclip.c
index e4e64bd42..16ccd9578 100644
--- a/gs/base/gxclip.c
+++ b/gs/base/gxclip.c
@@ -82,7 +82,7 @@ static const gx_device_clip gs_clip_device =
gx_default_begin_typed_image,
clip_get_bits_rectangle,
gx_forward_map_color_rgb_alpha,
- gx_no_create_compositor,
+ gx_forward_create_compositor,
gx_forward_get_hardware_params,
gx_default_text_begin,
gx_default_finish_copydevice,
diff --git a/gs/base/gxclrast.c b/gs/base/gxclrast.c
index bd1fb41e7..591eb8996 100644
--- a/gs/base/gxclrast.c
+++ b/gs/base/gxclrast.c
@@ -2767,7 +2767,17 @@ static int apply_create_compositor(gx_device_clist_reader *cdev, gs_imager_state
*/
code = dev_proc(tdev, create_compositor)(tdev, &tdev, pcomp, pis, mem, (gx_device*) cdev);
if (code >= 0 && tdev != *ptarget) {
- *ptarget = tdev;
+ /* If we created a new compositor here, then that new compositor should
+ * become the device to which we send all future drawing requests. If
+ * the above create_compositor call found an existing compositor
+ * already in the chain of devices (such as might happen when we are
+ * playing back a clist based pattern, and the top device is a clip
+ * device that forwards to a pdf14 device), then we'll just reuse
+ * that one. We do not want to send new drawing operations to the
+ * compositor, as that will sidestep the clipping. We therefore check
+ * the reference count to see if this is a new device or not. */
+ if (tdev->rc.ref_count == 1)
+ *ptarget = tdev;
}
if (code < 0)
return code;
diff --git a/gs/base/gxdevice.h b/gs/base/gxdevice.h
index 16b1eb6c7..3002955a1 100644
--- a/gs/base/gxdevice.h
+++ b/gs/base/gxdevice.h
@@ -361,6 +361,7 @@ dev_proc_fill_linear_color_triangle(gx_forward_fill_linear_color_triangle);
dev_proc_update_spot_equivalent_colors(gx_forward_update_spot_equivalent_colors);
dev_proc_ret_devn_params(gx_forward_ret_devn_params);
dev_proc_fillpage(gx_forward_fillpage);
+dev_proc_create_compositor(gx_forward_create_compositor);
dev_proc_get_profile(gx_forward_get_profile);
/* ---------------- Implementation utilities ---------------- */
diff --git a/gs/base/gxfillsl.h b/gs/base/gxfillsl.h
index 02f35394d..c96350386 100644
--- a/gs/base/gxfillsl.h
+++ b/gs/base/gxfillsl.h
@@ -217,7 +217,7 @@ TEMPLATE_spot_into_scanlines (line_list *ll, fixed band_mask)
} else
y_min = y;
- /* Process horisontal segments */
+ /* Process horizontal segments */
for (alp = ll->h_list0; alp != NULL; alp = alp->next) {
fixed x0 = min(alp->start.x, alp->end.x);
diff --git a/gs/base/gxipixel.c b/gs/base/gxipixel.c
index 95e335ecb..7606a1c20 100644
--- a/gs/base/gxipixel.c
+++ b/gs/base/gxipixel.c
@@ -370,7 +370,7 @@ gx_image_enum_begin(gx_device * dev, const gs_imager_state * pis,
if (pcs->cmm_icc_profile_data != NULL) {
device_color = false;
} else {
- device_color = (*pcst->concrete_space) (pcs, pis) == pcs;
+ device_color = (*pcst->concrete_space) (pcs, pis) == pcs;
}
image_init_colors(penum, bps, spp, format, decode, pis, dev,
diff --git a/gs/base/gxp1fill.c b/gs/base/gxp1fill.c
index d9f3ab203..fd69c3f1c 100644
--- a/gs/base/gxp1fill.c
+++ b/gs/base/gxp1fill.c
@@ -564,28 +564,36 @@ tile_by_steps_trans(tile_fill_trans_state_t * ptfs, int x0, int y0, int w0, int
return 0;
}
-/* This does the case of tiling with simple tiles. Since it is not commented anywhere note
- that simple means that the tile size is the same as the step matrix size and the cross
- terms in the step matrix are 0. Hence a simple case of tile replication. This needs to be optimized. */
+/* This does the case of tiling with simple tiles. Since it is not commented
+ * anywhere note that simple means that the tile size is the same as the step
+ * matrix size and the cross terms in the step matrix are 0. Hence a simple
+ * case of tile replication. This needs to be optimized. */
+/* Our source tile runs (conceptually) from (0,0) to
+ * (ptile->ttrans->width, ptile->ttrans->height). In practise, only a limited
+ * section of this (ptile->rect) may actually be used. */
void
-tile_rect_trans_simple(int xmin, int ymin, int xmax, int ymax, int px, int py, const gx_color_tile *ptile,
- gx_pattern_trans_t *fill_trans_buffer)
+tile_rect_trans_simple(int xmin, int ymin, int xmax, int ymax,
+ int px, int py, const gx_color_tile *ptile,
+ gx_pattern_trans_t *fill_trans_buffer)
{
- int kk, jj, ii, h, w, buff_y_offset, buff_x_offset;
+ int kk, jj, ii, h, w;
+ int buff_out_y_offset, buff_out_x_offset;
unsigned char *ptr_out, *ptr_in, *buff_out, *buff_in, *ptr_out_temp;
unsigned char *row_ptr;
int in_row_offset;
- int tile_width = ptile->ttrans->width;
- int tile_height = ptile->ttrans->height;
int dx, dy;
int left_rem_end, left_width, num_full_tiles, right_tile_width;
+ int left_copy_rem_end, left_copy_width, left_copy_offset, left_copy_start;
+ int mid_copy_width, right_copy_width;
+ int tile_width = ptile->ttrans->width;
+ int tile_height = ptile->ttrans->height;
- buff_y_offset = ymin - fill_trans_buffer->rect.p.y;
- buff_x_offset = xmin - fill_trans_buffer->rect.p.x;
+ buff_out_y_offset = ymin - fill_trans_buffer->rect.p.y;
+ buff_out_x_offset = xmin - fill_trans_buffer->rect.p.x;
buff_out = fill_trans_buffer->transbytes +
- buff_y_offset * fill_trans_buffer->rowstride +
- buff_x_offset;
+ buff_out_y_offset * fill_trans_buffer->rowstride +
+ buff_out_x_offset;
buff_in = ptile->ttrans->transbytes;
@@ -594,126 +602,144 @@ tile_rect_trans_simple(int xmin, int ymin, int xmax, int ymax, int px, int py, c
if (h <= 0 || w <= 0) return;
+ /* Calc dx, dy within the entire (conceptual) input tile. */
dx = (xmin + px) % tile_width;
dy = (ymin + py) % tile_height;
/* To speed this up, the inner loop on the width is implemented with
- mem copys where we have a left remainder, full tiles and a right remainder.
- Depending upon the rect that we are filling we may have only one of these
- three portions, or two or all three. We compute the parts now outside the loops. */
+ * memcpys where we have a left remainder, full tiles and a right
+ * remainder. Depending upon the rect that we are filling we may have
+ * only one of these three portions, or two or all three. We compute
+ * the parts now outside the loops. */
/* Left remainder part */
-
left_rem_end = min(dx+w,tile_width);
left_width = left_rem_end - dx;
+ left_copy_start = max(dx,ptile->ttrans->rect.p.x);
+ left_copy_rem_end = min(dx+w,ptile->ttrans->rect.q.x);
+ left_copy_width = left_copy_rem_end - left_copy_start;
+ if (left_copy_width < 0)
+ left_copy_width = 0;
+ left_copy_offset = left_copy_start-ptile->ttrans->rect.p.x;
/* Now the middle part */
-
num_full_tiles = (int)fastfloor((float) (w - left_width)/ (float) tile_width);
+ mid_copy_width = ptile->ttrans->rect.q.x - ptile->ttrans->rect.p.x;
/* Now the right part */
-
right_tile_width = w - num_full_tiles*tile_width - left_width;
+ right_copy_width = right_tile_width - ptile->ttrans->rect.p.x;
+ if (right_copy_width > ptile->ttrans->rect.q.x)
+ right_copy_width = ptile->ttrans->rect.q.x;
+ right_copy_width -= ptile->ttrans->rect.p.x;
+ if (right_copy_width < 0)
+ right_copy_width = 0;
- for (kk = 0; kk < fill_trans_buffer->n_chan; kk++){
+ for (kk = 0; kk < fill_trans_buffer->n_chan; kk++) {
ptr_out = buff_out + kk * fill_trans_buffer->planestride;
- ptr_in = buff_in + kk * ptile->ttrans->planestride;
+ ptr_in = buff_in + kk * ptile->ttrans->planestride;
- for (jj = 0; jj < h; jj++){
+ for (jj = 0; jj < h; jj++, ptr_out += fill_trans_buffer->rowstride) {
- in_row_offset = (jj + dy) % ptile->ttrans->height;
+ in_row_offset = ((jj + dy) % ptile->ttrans->height);
+ if (in_row_offset >= ptile->ttrans->rect.q.y)
+ continue;
+ in_row_offset -= ptile->ttrans->rect.p.y;
+ if (in_row_offset < 0)
+ continue;
row_ptr = ptr_in + in_row_offset * ptile->ttrans->rowstride;
/* This is the case when we have no blending. */
-
ptr_out_temp = ptr_out;
/* Left part */
-
- memcpy( ptr_out_temp, row_ptr + dx, left_width);
+ memcpy( ptr_out_temp, row_ptr + left_copy_offset, left_copy_width);
ptr_out_temp += left_width;
/* Now the full tiles */
for ( ii = 0; ii < num_full_tiles; ii++){
-
- memcpy( ptr_out_temp, row_ptr, tile_width);
+ memcpy( ptr_out_temp, row_ptr, mid_copy_width);
ptr_out_temp += tile_width;
-
}
/* Now the remainder */
-
- memcpy( ptr_out_temp, row_ptr, right_tile_width);
-
- ptr_out += fill_trans_buffer->rowstride;
-
+ memcpy( ptr_out_temp, row_ptr, right_copy_width);
}
-
}
/* If the group we are filling has a shape plane fill that now */
- /* Note: Since this was a virgin group push we can just blast it with 255 */
-
+ /* Note: Since this was a virgin group push we can just blast it with
+ * 255 */
if (fill_trans_buffer->has_shape) {
-
ptr_out = buff_out + fill_trans_buffer->n_chan * fill_trans_buffer->planestride;
-
- for (jj = 0; jj < h; jj++){
-
+ for (jj = 0; jj < h; jj++,ptr_out += fill_trans_buffer->rowstride) {
memset(ptr_out, 255, w);
- ptr_out += fill_trans_buffer->rowstride;
-
}
-
}
-
}
-/* This does the case of tiling with non simple tiles. In this case, the tiles may overlap and
- so we really need to do blending within the existing buffer. This needs some serious optimization. */
+/* This does the case of tiling with non simple tiles. In this case, the
+ * tiles may overlap and so we really need to do blending within the existing
+ * buffer. This needs some serious optimization. */
void
-tile_rect_trans_blend(int xmin, int ymin, int xmax, int ymax, int px, int py, const gx_color_tile *ptile,
- gx_pattern_trans_t *fill_trans_buffer)
+tile_rect_trans_blend(int xmin, int ymin, int xmax, int ymax,
+ int px, int py, const gx_color_tile *ptile,
+ gx_pattern_trans_t *fill_trans_buffer)
{
- int kk, jj, ii, h, w, buff_y_offset, buff_x_offset;
+ int kk, jj, ii, h, w;
+ int buff_out_y_offset, buff_out_x_offset;
unsigned char *buff_out, *buff_in;
unsigned char *buff_ptr, *row_ptr_in, *row_ptr_out;
unsigned char *tile_ptr;
int in_row_offset;
- int tile_width = ptile->ttrans->width;
- int tile_height = ptile->ttrans->height;
int dx, dy;
byte src[PDF14_MAX_PLANES];
byte dst[PDF14_MAX_PLANES];
- int num_chan = ptile->ttrans->n_chan; /* Includes alpha */
+ int tile_width = ptile->ttrans->width;
+ int tile_height = ptile->ttrans->height;
+ int num_chan = ptile->ttrans->n_chan; /* Includes alpha */
- buff_y_offset = ymin - fill_trans_buffer->rect.p.y;
- buff_x_offset = xmin - fill_trans_buffer->rect.p.x;
+ buff_out_y_offset = ymin - fill_trans_buffer->rect.p.y;
+ buff_out_x_offset = xmin - fill_trans_buffer->rect.p.x;
buff_out = fill_trans_buffer->transbytes +
- buff_y_offset * fill_trans_buffer->rowstride +
- buff_x_offset;
+ buff_out_y_offset * fill_trans_buffer->rowstride +
+ buff_out_x_offset;
buff_in = ptile->ttrans->transbytes;
h = ymax - ymin;
w = xmax - xmin;
+ if (h <= 0 || w <= 0) return;
+
+ /* Calc dx, dy within the entire (conceptual) input tile. */
dx = (xmin + px) % tile_width;
dy = (ymin + py) % tile_height;
for (jj = 0; jj < h; jj++){
in_row_offset = (jj + dy) % ptile->ttrans->height;
+ if (in_row_offset >= ptile->ttrans->rect.q.y)
+ continue;
+ in_row_offset -= ptile->ttrans->rect.p.y;
+ if (in_row_offset < 0)
+ continue;
row_ptr_in = buff_in + in_row_offset * ptile->ttrans->rowstride;
row_ptr_out = buff_out + jj * fill_trans_buffer->rowstride;
for (ii = 0; ii < w; ii++) {
-
- tile_ptr = row_ptr_in + (dx + ii) % ptile->ttrans->width;
+ int x_in_offset = (dx + ii) % ptile->ttrans->width;
+
+ if (x_in_offset >= ptile->ttrans->rect.q.x)
+ continue;
+ x_in_offset -= ptile->ttrans->rect.p.x;
+ if (x_in_offset < 0)
+ continue;
+ tile_ptr = row_ptr_in + x_in_offset;
buff_ptr = row_ptr_out + ii;
/* We need to blend here. The blending mode from the current
@@ -721,55 +747,43 @@ tile_rect_trans_blend(int xmin, int ymin, int xmax, int ymax, int px, int py, co
*/
/* The color values. This needs to be optimized */
-
- for (kk = 0; kk < num_chan; kk++){
-
+ for (kk = 0; kk < num_chan; kk++) {
dst[kk] = *(buff_ptr + kk * fill_trans_buffer->planestride);
src[kk] = *(tile_ptr + kk * ptile->ttrans->planestride);
-
}
/* Blend */
-
- art_pdf_composite_pixel_alpha_8(dst, src, ptile->ttrans->n_chan-1,
- ptile->ttrans->blending_mode, ptile->ttrans->blending_procs);
+ art_pdf_composite_pixel_alpha_8(dst, src,
+ ptile->ttrans->n_chan-1,
+ ptile->ttrans->blending_mode,
+ ptile->ttrans->blending_procs);
/* Store the color values */
-
- for (kk = 0; kk < num_chan; kk++){
-
+ for (kk = 0; kk < num_chan; kk++) {
*(buff_ptr + kk * fill_trans_buffer->planestride) = dst[kk];
-
}
-
}
-
}
/* If the group we are filling has a shape plane fill that now */
- /* Note: Since this was a virgin group push we can just blast it with 255 */
-
+ /* Note: Since this was a virgin group push we can just blast it with
+ * 255 */
if (fill_trans_buffer->has_shape) {
-
buff_ptr = buff_out + fill_trans_buffer->n_chan * fill_trans_buffer->planestride;
- for (jj = 0; jj < h; jj++){
-
+ for (jj = 0; jj < h; jj++) {
memset(buff_ptr, 255, w);
buff_ptr += fill_trans_buffer->rowstride;
-
}
-
}
-
}
/* This version does a rect fill with the transparency object */
int
gx_dc_pat_trans_fill_rectangle(const gx_device_color * pdevc, int x, int y,
- int w, int h, gx_device * dev,
- gs_logical_operation_t lop,
- const gx_rop_source_t * source)
+ int w, int h, gx_device * dev,
+ gs_logical_operation_t lop,
+ const gx_rop_source_t * source)
{
gx_color_tile *ptile = pdevc->colors.pattern.p_tile;
int code;
@@ -786,7 +800,8 @@ gx_dc_pat_trans_fill_rectangle(const gx_device_color * pdevc, int x, int y,
phase.y = pdevc->phase.y;
code = gx_trans_pattern_fill_rect(x, y, x+w, y+h, ptile,
- ptile->ttrans->fill_trans_buffer, phase);
+ ptile->ttrans->fill_trans_buffer, phase,
+ dev, pdevc);
return code;
}
@@ -795,12 +810,15 @@ gx_dc_pat_trans_fill_rectangle(const gx_device_color * pdevc, int x, int y,
buffer that includes transparency */
int
-gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax, gx_color_tile *ptile,
- gx_pattern_trans_t *fill_trans_buffer,
- gs_int_point phase)
+gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax,
+ gx_color_tile *ptile,
+ gx_pattern_trans_t *fill_trans_buffer,
+ gs_int_point phase, gx_device *dev,
+ const gx_device_color * pdevc)
{
- tile_fill_trans_state_t state;
+ tile_fill_trans_state_t state_trans;
+ tile_fill_state_t state_clist_trans;
int code;
if (ptile == 0) /* null pattern */
@@ -814,8 +832,9 @@ gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax, gx_color_tile
ymin = 0;
}
- state.phase.x = phase.x;
- state.phase.y = phase.y;
+ /* Initialize the fill state */
+ state_trans.phase.x = phase.x;
+ state_trans.phase.y = phase.y;
if (ptile->is_simple && ptile->cdev == NULL) {
/* A simple case. Tile is not clist and simple. */
@@ -834,16 +853,36 @@ gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax, gx_color_tile
This portion transforms the bounding box by the step matrix
and does partial rect fills with tiles that fall into this
transformed bbox */
- code = tile_by_steps_trans(&state, xmin, ymin, xmax-xmin, ymax-ymin,
- fill_trans_buffer, ptile);
+ code = tile_by_steps_trans(&state_trans, xmin, ymin, xmax-xmin,
+ ymax-ymin, fill_trans_buffer, ptile);
} else {
- /* clist for the tile. Currently this is not implemented
- for the case when the tile has transparency. This is
- on the to do list. Right now, all tiles with transparency
- are rendered into the pattern cache or into the clist
- */
- return_error(gs_error_unregistered);
+ /* clist for the trans tile. This uses the pdf14 device as a target
+ and should blend directly into the buffer. Note that the
+ pattern can not have a push pdf14 device or a pop pdf14 device
+ compositor action. Those are removed during the compositor
+ clist writing operation where we check for the case of a pattern
+ with a transparency */
+ gx_device_clist *cdev = ptile->cdev;
+ gx_device_clist_reader *crdev = (gx_device_clist_reader *)cdev;
+ gx_strip_bitmap tbits;
+
+ code = tile_fill_init(&state_clist_trans, pdevc, dev, false);
+
+ state_clist_trans.phase.x = phase.x;
+ state_clist_trans.phase.y = phase.y;
+ crdev->yplane.depth = 0;
+ crdev->yplane.shift = 0;
+ crdev->yplane.index = -1;
+ crdev->pages = NULL;
+ crdev->num_pages = 1;
+ state_clist_trans.orig_dev = dev;
+ state_clist_trans.pdevc = pdevc;
+ tbits = ptile->tbits;
+ tbits.size.x = crdev->width;
+ tbits.size.y = crdev->height;
+ code = tile_by_steps(&state_clist_trans, xmin, ymin, xmax,
+ ymax, ptile, &tbits, tile_pattern_clist);
}
}
-return(0);
+ return(0);
}
diff --git a/gs/base/gxpcmap.c b/gs/base/gxpcmap.c
index aae8c65dc..6d97997d1 100644
--- a/gs/base/gxpcmap.c
+++ b/gs/base/gxpcmap.c
@@ -18,11 +18,11 @@
#include "gx.h"
#include "gserrors.h"
#include "gsstruct.h"
-#include "gsutil.h" /* for gs_next_ids */
+#include "gsutil.h" /* for gs_next_ids */
#include "gxfixed.h"
#include "gxmatrix.h"
#include "gspath2.h"
-#include "gxcspace.h" /* for gscolor2.h */
+#include "gxcspace.h" /* for gscolor2.h */
#include "gxcolor2.h"
#include "gxdcolor.h"
#include "gxdevice.h"
@@ -150,8 +150,8 @@ static const gx_device_pattern_accum gs_pattern_accum_device =
NULL,
NULL
},
- 0, /* target */
- 0, 0, 0, 0 /* bitmap_memory, bits, mask, instance */
+ 0, /* target */
+ 0, 0, 0, 0 /* bitmap_memory, bits, mask, instance */
};
static int
@@ -187,6 +187,29 @@ static dev_proc_destroy_buf_device(dummy_destroy_buf_device)
{
}
+/* Attempt to determine the size of a pattern (the approximate amount that will */
+/* be needed in the pattern cache). If we end up using the clist, this is only */
+/* a guess -- we use the tile size which will _probably_ be too large. */
+static int
+gx_pattern_size_estimate(gs_pattern1_instance_t *pinst, int has_tags)
+{
+ gx_device *tdev = pinst->saved->device;
+ int depth = (pinst->template.PaintType == 2 ? 1 : tdev->color_info.depth);
+ int64_t raster;
+ int64_t size;
+
+ if (pinst->template.uses_transparency) {
+ raster = (pinst->size.x * ((depth/8) + 1 + has_tags));
+ size = raster > max_int / pinst->size.y ? (max_int & ~0xFFFF) : raster * pinst->size.y;
+ } else {
+ raster = (pinst->size.x * depth + 7) / 8;
+ size = raster * pinst->size.y;
+ }
+ if (size > (int64_t)max_int)
+ size = (int64_t)max_int;
+ return (int)size;
+}
+
#ifndef MaxPatternBitmap_DEFAULT
# define MaxPatternBitmap_DEFAULT (8*1024*1024) /* reasonable on most modern hosts */
#endif
@@ -197,14 +220,12 @@ gx_pattern_accum_alloc(gs_memory_t * mem, gs_memory_t * storage_memory,
gs_pattern1_instance_t *pinst, client_name_t cname)
{
gx_device *tdev = pinst->saved->device;
- int depth = (pinst->template.PaintType == 2 ? 1 : tdev->color_info.depth);
- int raster = (pinst->size.x * depth + 7) / 8;
- int64_t size = (int64_t)raster * pinst->size.y;
+ int has_tags = (mem->gs_lib_ctx->BITTAG != GS_DEVICE_DOESNT_SUPPORT_TAGS);
+ int size = gx_pattern_size_estimate(pinst, has_tags);
gx_device_forward *fdev;
int force_no_clist = 0;
int max_pattern_bitmap = tdev->MaxPatternBitmap == 0 ? MaxPatternBitmap_DEFAULT :
tdev->MaxPatternBitmap;
-
/*
* If the target device can accumulate a pattern stream and the language
* client supports high level patterns (ps and pdf only) we don't need a
@@ -222,16 +243,11 @@ gx_pattern_accum_alloc(gs_memory_t * mem, gs_memory_t * storage_memory,
if (pinst->saved->have_pattern_streams == 0 && (*dev_proc(pinst->saved->device,
dev_spec_op))((gx_device *)pinst->saved->device,
gxdso_pattern_can_accum, pinst, 0) == 1)
- force_no_clist = 1;
- /* Do not allow pattern to be a clist if it uses transparency. We
- will want to fix this at some point */
-
- if (force_no_clist || (size < max_pattern_bitmap && !pinst->is_clist) || pinst->template.PaintType != 1 ||
- pinst->template.uses_transparency ) {
-
+ force_no_clist = 1; /* Set only for first time through */
+ if (force_no_clist || (size < max_pattern_bitmap && !pinst->is_clist)
+ || pinst->template.PaintType != 1 ) {
gx_device_pattern_accum *adev = gs_alloc_struct(mem, gx_device_pattern_accum,
&st_device_pattern_accum, cname);
-
if (adev == 0)
return 0;
#ifdef DEBUG
@@ -318,8 +334,14 @@ gx_pattern_accum_alloc(gs_memory_t * mem, gs_memory_t * storage_memory,
clist_init_io_procs(cdev, true);
cwdev->data = data;
cwdev->data_size = data_size;
- cwdev->buf_procs = buf_procs ;
- cwdev->band_params.page_uses_transparency = false;
+ cwdev->buf_procs = buf_procs;
+ if ( pinst->template.uses_transparency) {
+ cwdev->band_params.page_uses_transparency = true;
+ cwdev->page_uses_transparency = true;
+ } else {
+ cwdev->band_params.page_uses_transparency = false;
+ cwdev->page_uses_transparency = false;
+ }
cwdev->band_params.BandWidth = pinst->size.x;
cwdev->band_params.BandHeight = pinst->size.x;
cwdev->band_params.BandBufferSpace = 0;
@@ -327,7 +349,6 @@ gx_pattern_accum_alloc(gs_memory_t * mem, gs_memory_t * storage_memory,
cwdev->bandlist_memory = storage_memory->non_gc_memory;
cwdev->free_up_bandlist_memory = dummy_free_up_bandlist_memory;
cwdev->disable_mask = 0;
- cwdev->page_uses_transparency = false;
cwdev->pinst = pinst;
set_dev_proc(cwdev, get_clipping_box, gx_default_get_clipping_box);
set_dev_proc(cwdev, get_profile, gx_forward_get_profile);
@@ -377,26 +398,20 @@ pattern_accum_open(gx_device * dev)
PDSET(padev);
padev->color_info = target->color_info;
-
/* If we have transparency, then fix the color info
now so that the mem device allocates the proper
buffer space for the pattern template. We can
do this since the transparency code all */
-
- if(pinst->template.uses_transparency){
-
+ if (pinst->template.uses_transparency) {
/* Allocate structure that we will use for the trans pattern */
padev->transbuff = gs_alloc_struct(mem,gx_pattern_trans_t,&st_pattern_trans,"pattern_accum_open(trans)");
padev->transbuff->transbytes = NULL;
+ padev->transbuff->mem = NULL;
padev->transbuff->pdev14 = NULL;
padev->transbuff->fill_trans_buffer = NULL;
-
} else {
-
padev->transbuff = NULL;
-
}
-
if (pinst->uses_mask) {
mask = gs_alloc_struct( mem,
gx_device_memory,
@@ -417,25 +432,20 @@ pattern_accum_open(gx_device * dev)
}
if (code >= 0) {
-
- if (pinst->template.uses_transparency){
-
+ if (pinst->template.uses_transparency) {
/* In this case, we will grab the buffer created
by the graphic state's device (which is pdf14) and
we will be tiling that into a transparency group buffer
to blend with the pattern accumulator's target. Since
all the transparency stuff is planar format, it is
best just to keep the data in that form */
-
gx_device_set_target((gx_device_forward *)padev, target);
-
} else {
-
switch (pinst->template.PaintType) {
- case 2: /* uncolored */
+ case 2: /* uncolored */
gx_device_set_target((gx_device_forward *)padev, target);
break;
- case 1: /* colored */
+ case 1: /* colored */
bits = gs_alloc_struct(mem, gx_device_memory,
&st_device_memory,
"pattern_accum_open(bits)");
@@ -476,13 +486,13 @@ pattern_accum_open(gx_device * dev)
gx_pattern_trans_t*
new_pattern_trans_buff(gs_memory_t *mem)
{
-
gx_pattern_trans_t *result;
/* Allocate structure that we will use for the trans pattern */
result = gs_alloc_struct(mem, gx_pattern_trans_t, &st_pattern_trans, "new_pattern_trans_buff");
result->transbytes = NULL;
result->pdev14 = NULL;
+ result->mem = NULL;
result->fill_trans_buffer = NULL;
return(result);
@@ -697,6 +707,7 @@ static void
gx_pattern_cache_free_entry(gx_pattern_cache * pcache, gx_color_tile * ctile)
{
gx_device *temp_device;
+ int size_b, size_c;
if ((ctile->id != gx_no_bitmap_id) && !ctile->is_dummy) {
gs_memory_t *mem = pcache->memory;
@@ -715,7 +726,7 @@ gx_pattern_cache_free_entry(gx_pattern_cache * pcache, gx_color_tile * ctile)
gdev_mem_bitmap_size(pmdev, &used);
gs_free_object(mem, ctile->tmask.data,
"free_pattern_cache_entry(mask data)");
- ctile->tmask.data = 0; /* for GC */
+ ctile->tmask.data = 0; /* for GC */
}
if (ctile->tbits.data != 0) {
ulong tbits_used = 0;
@@ -727,9 +738,17 @@ gx_pattern_cache_free_entry(gx_pattern_cache * pcache, gx_color_tile * ctile)
used += tbits_used;
gs_free_object(mem, ctile->tbits.data,
"free_pattern_cache_entry(bits data)");
- ctile->tbits.data = 0; /* for GC */
+ ctile->tbits.data = 0; /* for GC */
}
if (ctile->cdev != NULL) {
+ size_b = clist_data_size(ctile->cdev, 0);
+ if (size_b < 0)
+ return; /* gs_error_unregistered) */
+ size_c = clist_data_size(ctile->cdev, 1);
+ if (size_c < 0)
+ return; /* gs_error_unregistered) */
+ used = size_b + size_c;
+ ctile->cdev->common.do_not_open_or_close_bandfiles = false; /* make sure memfile gets freed/closed */
dev_proc(&ctile->cdev->common, close_device)((gx_device *)&ctile->cdev->common);
/* Free up the icc based stuff in the clist device. I am puzzled
why the other objects are not released */
@@ -737,7 +756,8 @@ gx_pattern_cache_free_entry(gx_pattern_cache * pcache, gx_color_tile * ctile)
ctile->cdev->common.memory);
rc_decrement(ctile->cdev->common.icc_cache_cl,
"gx_pattern_cache_free_entry");
- gs_free_object(ctile->cdev->common.memory, ctile->cdev, "free_pattern_cache_entry(pattern-clist)");
+ temp_device = (gx_device *)ctile->cdev;
+ gx_device_retain(temp_device, false);
ctile->cdev = NULL;
}
@@ -745,15 +765,17 @@ gx_pattern_cache_free_entry(gx_pattern_cache * pcache, gx_color_tile * ctile)
if ( ctile->ttrans->pdev14 == NULL) {
/* This can happen if we came from the clist */
- gs_free_object(mem,ctile->ttrans->transbytes,
+ gs_free_object(ctile->ttrans->mem ,ctile->ttrans->transbytes,
"free_pattern_cache_entry(transbytes)");
gs_free_object(mem,ctile->ttrans->fill_trans_buffer,
"free_pattern_cache_entry(fill_trans_buffer)");
ctile->ttrans->transbytes = NULL;
+ ctile->ttrans->fill_trans_buffer = NULL;
} else {
dev_proc(ctile->ttrans->pdev14, close_device)((gx_device *)ctile->ttrans->pdev14);
temp_device = ctile->ttrans->pdev14;
gx_device_retain(temp_device, false);
+ rc_decrement(temp_device,"gx_pattern_cache_free_entry");
ctile->ttrans->pdev14 = NULL;
ctile->ttrans->transbytes = NULL; /* should be ok due to pdf14_close */
ctile->ttrans->fill_trans_buffer = NULL; /* This is always freed */
@@ -767,12 +789,48 @@ gx_pattern_cache_free_entry(gx_pattern_cache * pcache, gx_color_tile * ctile)
}
pcache->tiles_used--;
+ if (pcache->bits_used < used) /* FIXME: tile 'used' doesn't match cache */
+ pcache->bits_used = 0; /* FIXME: tile 'used' doesn't match cache */
+ else /* FIXME: tile 'used' doesn't match cache */
pcache->bits_used -= used;
ctile->id = gx_no_bitmap_id;
gx_device_retain((gx_device *)pmdev, false);
}
}
+/* Given the size of a new pattern tile, free entries from the cache until */
+/* enough space is available (or nothing left to free). */
+/* This will allow 1 oversized entry */
+void
+gx_pattern_cache_ensure_space(gs_imager_state * pis, int needed)
+{
+ int code = ensure_pattern_cache(pis);
+ gx_pattern_cache *pcache;
+
+ if (code < 0)
+ return; /* no cache -- just exit */
+
+ pcache = pis->pattern_cache;
+
+ /* If too large then start freeing entries */
+ /* By starting at 'next', we attempt to first free the oldest entries */
+ while (pcache->bits_used + needed > pcache->max_bits &&
+ pcache->bits_used != 0) {
+ pcache->next = (pcache->next + 1) % pcache->num_tiles;
+ gx_pattern_cache_free_entry(pcache, &pcache->tiles[pcache->next]);
+ }
+}
+
+/* Export updating the pattern_cache bits_used and tiles_used for clist reading */
+void
+gx_pattern_cache_update_used(gs_imager_state *pis, ulong used)
+{
+ gx_pattern_cache *pcache = pis->pattern_cache;
+
+ pcache->bits_used += used;
+ pcache->tiles_used++;
+}
+
/*
* Add a Pattern cache entry. This is exported for the interpreter.
* Note that this does not free any of the data in the accumulator
@@ -794,6 +852,7 @@ gx_pattern_cache_add_entry(gs_imager_state * pis,
gx_device_memory *mmask = NULL;
gx_device_memory *mbits = NULL;
gx_pattern_trans_t *trans = NULL;
+ int size_b, size_c;
if (code < 0)
return code;
@@ -848,22 +907,18 @@ gx_pattern_cache_add_entry(gs_imager_state * pis,
if (code < 0)
return code;
pinst = cdev->writer.pinst;
- /* HACK: we would like to copy the pattern clist stream into the
- tile cache memory and properly account its size,
- but we have no time for this development now.
- Therefore the stream is stored outside the cache. */
- used = 0;
+ size_b = clist_data_size(cdev, 0);
+ if (size_b < 0)
+ return_error(gs_error_unregistered);
+ size_c = clist_data_size(cdev, 1);
+ if (size_c < 0)
+ return_error(gs_error_unregistered);
+ /* The memfile size is the size, not the size determined by the depth*width*height */
+ used = size_b + size_c;
}
id = pinst->id;
ctile = &pcache->tiles[id % pcache->num_tiles];
- gx_pattern_cache_free_entry(pcache, ctile);
- /* If too large then start freeing entries */
- while (pcache->bits_used + used > pcache->max_bits &&
- pcache->bits_used != 0 /* allow 1 oversized entry (?) */
- ) {
- pcache->next = (pcache->next + 1) % pcache->num_tiles;
- gx_pattern_cache_free_entry(pcache, &pcache->tiles[pcache->next]);
- }
+ gx_pattern_cache_free_entry(pcache, ctile); /* ensure that this cache slot is empty */
ctile->id = id;
ctile->depth = fdev->color_info.depth;
ctile->uid = pinst->template.uid;
@@ -876,12 +931,12 @@ gx_pattern_cache_add_entry(gs_imager_state * pis,
if (fdev->procs.open_device != pattern_clist_open_device) {
if (mbits != 0) {
make_bitmap(&ctile->tbits, mbits, gs_next_ids(pis->memory, 1));
- mbits->bitmap_memory = 0; /* don't free the bits */
+ mbits->bitmap_memory = 0; /* don't free the bits */
} else
ctile->tbits.data = 0;
if (mmask != 0) {
make_bitmap(&ctile->tmask, mmask, id);
- mmask->bitmap_memory = 0; /* don't free the bits */
+ mmask->bitmap_memory = 0; /* don't free the bits */
} else
ctile->tmask.data = 0;
if (trans != 0) {
@@ -889,7 +944,6 @@ gx_pattern_cache_add_entry(gs_imager_state * pis,
}
ctile->cdev = NULL;
- pcache->bits_used += used;
} else {
gx_device_clist *cdev = (gx_device_clist *)fdev;
gx_device_clist_writer *cwdev = (gx_device_clist_writer *)fdev;
@@ -913,7 +967,8 @@ gx_pattern_cache_add_entry(gs_imager_state * pis,
/* Prevent freeing files on pattern_paint_cleanup : */
cwdev->do_not_open_or_close_bandfiles = true;
}
- pcache->tiles_used++;
+ gx_pattern_cache_update_used(pis, used);
+
*pctile = ctile;
return 0;
}
@@ -1047,7 +1102,7 @@ gx_pattern_cache_winnow(gx_pattern_cache * pcache,
{
uint i;
- if (pcache == 0) /* no cache created yet */
+ if (pcache == 0) /* no cache created yet */
return;
for (i = 0; i < pcache->num_tiles; ++i) {
gx_color_tile *ctile = &pcache->tiles[i];
@@ -1102,14 +1157,18 @@ gx_pattern_load(gx_device_color * pdc, const gs_imager_state * pis,
gs_state *saved;
gx_color_tile *ctile;
gs_memory_t *mem = pis->memory;
+ int has_tags = (mem->gs_lib_ctx->BITTAG != GS_DEVICE_DOESNT_SUPPORT_TAGS);
int code;
+ if (pis->pattern_cache == NULL)
+ if ((code = ensure_pattern_cache((gs_imager_state *) pis))< 0) /* break const for call */
+ return code;
+
if (gx_pattern_cache_lookup(pdc, pis, dev, select))
return 0;
- /* We REALLY don't like the following cast.... */
- code = ensure_pattern_cache((gs_imager_state *) pis);
- if (code < 0)
- return code;
+
+ /* Get enough space in the cache for this pattern (estimated if it is a clist) */
+ gx_pattern_cache_ensure_space(pis, gx_pattern_size_estimate(pinst, has_tags));
/*
* Note that adev is an internal device, so it will be freed when the
* last reference to it from a graphics state is deleted.
@@ -1130,10 +1189,10 @@ gx_pattern_load(gx_device_color * pdc, const gs_imager_state * pis,
saved->pattern_cache = pis->pattern_cache;
gs_setdevice_no_init(saved, (gx_device *)adev);
if (pinst->template.uses_transparency) {
- /* This should not occur from PS or PDF, but is provided for other clients (XPS) */
if_debug0('v', "gx_pattern_load: pushing the pdf14 compositor device into this graphics state\n");
- if ((code = gs_push_pdf14trans_device(saved)) < 0)
+ if ((code = gs_push_pdf14trans_device(saved, true)) < 0)
return code;
+ saved->device->is_open = true;
} else {
/* For colored patterns we clear the pattern device's
background. This is necessary for the anti aliasing code
@@ -1149,14 +1208,26 @@ gx_pattern_load(gx_device_color * pdc, const gs_imager_state * pis,
code = (*pinst->template.PaintProc)(&pdc->ccolor, saved);
if (code < 0) {
- dev_proc(adev, close_device)((gx_device *)adev);
- /* Freeing the state will free the device and the pdf14 compositor (if any). */
+ gx_device_retain(saved->device, false); /* device no longer retained */
+ if (pinst->template.uses_transparency) {
+ dev_proc(saved->device, close_device)((gx_device *)saved->device);
+ dev_proc(adev, close_device)((gx_device *)adev);
+ if (pinst->is_clist == 0)
+ gs_free_object(((gx_device_pattern_accum *)adev)->bitmap_memory,
+ ((gx_device_pattern_accum *)adev)->transbuff,
+ "gx_pattern_load");
+ // rc_decrement_only(adev, "gx_pattern_load"); /* may free the device */
+ // gs_free_object(mem, adev, "gx_pattern_load");
+ } else {
+ dev_proc(adev, close_device)((gx_device *)adev);
+ }
+ /* Freeing the state should now free the device which may be the pdf14 compositor. */
gs_state_free(saved);
return code;
}
if (pinst->template.uses_transparency) {
if_debug0('v', "gx_pattern_load: popping the pdf14 compositor device from this graphics state\n");
- if ((code = gs_pop_pdf14trans_device(saved)) < 0)
+ if ((code = gs_pop_pdf14trans_device(saved, true)) < 0)
return code;
}
/* We REALLY don't like the following cast.... */
@@ -1199,7 +1270,7 @@ fail:
}
/* Remap a PatternType 1 color. */
-cs_proc_remap_color(gx_remap_Pattern); /* check the prototype */
+cs_proc_remap_color(gx_remap_Pattern); /* check the prototype */
int
gs_pattern1_remap_color(const gs_client_color * pc, const gs_color_space * pcs,
gx_device_color * pdc, const gs_imager_state * pis,
@@ -1216,7 +1287,7 @@ gs_pattern1_remap_color(const gs_client_color * pc, const gs_color_space * pcs,
color_set_null_pattern(pdc);
return 0;
}
- if (pinst->template.PaintType == 2) { /* uncolored */
+ if (pinst->template.PaintType == 2) { /* uncolored */
code = (pcs->base_space->type->remap_color)
(pc, pcs->base_space, pdc, pis, dev, select);
if (code < 0)
diff --git a/gs/base/gxpcolor.h b/gs/base/gxpcolor.h
index ffc97ce1d..cb6ed3c47 100644
--- a/gs/base/gxpcolor.h
+++ b/gs/base/gxpcolor.h
@@ -159,13 +159,14 @@ struct gx_pattern_trans_s {
const gx_device *pdev14;
byte *transbytes;
+ gs_memory_t *mem;
gx_pattern_trans_t *fill_trans_buffer; /* buffer to fill */
gs_int_rect rect;
int rowstride;
int planestride;
int n_chan; /* number of pixel planes including alpha */
bool has_shape; /* extra plane inserted */
- int width;
+ int width; /* Complete plane width/height; rect may be a subset of this */
int height;
const pdf14_nonseparable_blending_procs_t *blending_procs;
bool is_additive;
@@ -284,6 +285,16 @@ gx_device_forward * gx_pattern_accum_alloc(gs_memory_t * mem,
gs_memory_t * stoarge_memory,
gs_pattern1_instance_t *pinst, client_name_t cname);
+/* Given the size of a new pattern tile, free entries from the cache until */
+/* enough space is available (or nothing left to free). */
+/* This will allow 1 oversized entry */
+void gx_pattern_cache_ensure_space(gs_imager_state * pis, int needed);
+
+void gx_pattern_cache_update_used(gs_imager_state *pis, ulong used);
+
+/* Update cache tile space */
+void gx_pattern_cache_update_space(gs_imager_state * pis, int64_t used);
+
/* Add an accumulated pattern to the cache. */
/* Note that this does not free any of the data in the accumulator */
/* device, but it may zero out the bitmap_memory pointers to prevent */
@@ -315,7 +326,8 @@ dev_proc_open_device(pattern_clist_open_device);
int gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax,
gx_color_tile *ptile,
gx_pattern_trans_t *fill_trans_buffer,
- gs_int_point phase);
+ gs_int_point phase, gx_device *dev,
+ const gx_device_color * pdevc);
gx_pattern_trans_t* new_pattern_trans_buff(gs_memory_t *mem);
diff --git a/gs/base/gxshade.c b/gs/base/gxshade.c
index e0471abe7..76f07a022 100644
--- a/gs/base/gxshade.c
+++ b/gs/base/gxshade.c
@@ -389,7 +389,7 @@ top:
/* Grab the icc link transform that we need now */
if (pcs->cmm_icc_profile_data != NULL) {
pfs->icclink = gsicc_get_link(pis, pis->trans_device, pcs, NULL,
- &rendering_params, pis->memory, false);
+ &rendering_params, pis->memory, false);
} else {
if (pcs->icc_equivalent != NULL ) {
/* We have a PS equivalent ICC profile. We may need to go
diff --git a/gs/ghostscript.vcproj b/gs/ghostscript.vcproj
index a00a612ad..e69b1e642 100644
--- a/gs/ghostscript.vcproj
+++ b/gs/ghostscript.vcproj
@@ -4931,6 +4931,10 @@
>
</File>
<File
+ RelativePath=".\base\gxdevsop.h"
+ >
+ </File>
+ <File
RelativePath="base\gxdht.h"
>
</File>
diff --git a/gs/psi/zicc.c b/gs/psi/zicc.c
index 8a713cf8f..a3158214d 100644
--- a/gs/psi/zicc.c
+++ b/gs/psi/zicc.c
@@ -90,7 +90,7 @@ int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff)
picc_profile = gsicc_get_profile_handle_file(icc_std_profile_names[k],
strlen(icc_std_profile_names[k]), gs_state_memory(igs));
break;
- }
+ }
}
} else {
picc_profile = gsicc_profile_new(s, gs_state_memory(igs), NULL, 0);
@@ -179,17 +179,20 @@ int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff)
for (i = 0; i < ncomps; i++) {
picc_profile->Range.ranges[i].rmin = range_buff[2 * i];
picc_profile->Range.ranges[i].rmax = range_buff[2 * i + 1];
- }
}
+ }
/* Set the color space. We are done. No joint cache here... */
code = gs_setcolorspace(igs, pcs);
+ /* The context has taken a reference to the colorspace. We no longer need
+ * ours, so drop it. */
+ rc_decrement_only(pcs, "seticc");
/* In this case, we already have a ref count of 2 on the icc profile
one for when it was created and one for when it was set. We really
only want one here so adjust */
rc_decrement(picc_profile,"seticc");
/* Remove the ICC dict from the stack */
pop(1);
- return code;
+ return code;
}
/*
diff --git a/gs/psi/zpcolor.c b/gs/psi/zpcolor.c
index d6ec6e49f..514a7d808 100644
--- a/gs/psi/zpcolor.c
+++ b/gs/psi/zpcolor.c
@@ -241,7 +241,7 @@ pattern_paint_prepare(i_ctx_t *i_ctx_p)
gs_setdevice_no_init(pgs, (gx_device *)pdev);
if (pinst->template.uses_transparency) {
if_debug0('v', " pushing the pdf14 compositor device into this graphics state\n");
- if ((code = gs_push_pdf14trans_device(pgs)) < 0)
+ if ((code = gs_push_pdf14trans_device(pgs, true)) < 0)
return code;
} else { /* not transparent */
if (pinst->template.PaintType == 1)
@@ -304,12 +304,22 @@ pattern_paint_finish(i_ctx_t *i_ctx_p)
if (pinst->template.uses_transparency) {
gs_state *pgs = igs;
int code;
- /* Get PDF14 buffer information */
- code = pdf14_get_buffer_information(pgs->device,padev->transbuff);
- /* PDF14 device (and buffer) is destroyed when pattern cache
- entry is removed */
- if (code < 0)
- return code;
+
+ if (pinst->is_clist) {
+ /* Send the compositor command to close the PDF14 device */
+ code = (gs_pop_pdf14trans_device(pgs, true) < 0);
+ if (code < 0)
+ return code;
+ } else {
+ /* Not a clist, get PDF14 buffer information */
+ code = pdf14_get_buffer_information(pgs->device,
+ padev->transbuff, pgs->memory,
+ true);
+ /* PDF14 device (and buffer) is destroyed when pattern cache
+ entry is removed */
+ if (code < 0)
+ return code;
+ }
}
code = gx_pattern_cache_add_entry((gs_imager_state *)igs, pdev, &ctile);
if (code < 0)
diff --git a/gs/psi/ztrans.c b/gs/psi/ztrans.c
index 7f9f414ec..2d28c1e06 100644
--- a/gs/psi/ztrans.c
+++ b/gs/psi/ztrans.c
@@ -374,6 +374,7 @@ zimage3x(i_ctx_t *i_ctx_p)
check_type(*op, t_dictionary);
check_dict_read(*op);
+ memset(&image, 0, sizeof(gs_image3x_t));
gs_image3x_t_init(&image, NULL);
if (dict_find_string(op, "DataDict", &pDataDict) <= 0)
return_error(e_rangecheck);
@@ -451,7 +452,7 @@ zpushpdf14devicefilter(i_ctx_t *i_ctx_p)
os_ptr op = osp;
check_type(*op, t_integer);
- code = gs_push_pdf14trans_device(igs);
+ code = gs_push_pdf14trans_device(igs, false);
if (code < 0)
return code;
pop(1);
@@ -463,7 +464,7 @@ zpushpdf14devicefilter(i_ctx_t *i_ctx_p)
static int
zpoppdf14devicefilter(i_ctx_t *i_ctx_p)
{
- return gs_pop_pdf14trans_device(igs);
+ return gs_pop_pdf14trans_device(igs, false);
}
/* This is used to communicate to the transparency compositor
diff --git a/gs/toolbin/leaks.tcl b/gs/toolbin/leaks.tcl
index f378b3f62..b4592546c 100755
--- a/gs/toolbin/leaks.tcl
+++ b/gs/toolbin/leaks.tcl
@@ -74,6 +74,7 @@ proc add0-1 {il addr} [info body add0+0]
proc read_trace {{fname %stdin}} {
global A lines next
set n $next
+ set i 0
if {$fname == "%stdin"} {
set in stdin
} else {
@@ -82,10 +83,11 @@ proc read_trace {{fname %stdin}} {
# Skip to the first "allocated" line. See below for why we bother
# checking for EOF.
while {[gets $in l] >= 0} {
+ incr i
if [regexp "memory allocated" $l] break
incr n
}
- if {$n == 0} {
+ if {$i == 0} {
puts stderr "Empty input file!"
if {$fname != "%stdin"} {close $in}
exit
diff --git a/svg/svgdoc.c b/svg/svgdoc.c
index fc058e74a..5f3286fad 100644
--- a/svg/svgdoc.c
+++ b/svg/svgdoc.c
@@ -326,7 +326,7 @@ svg_parse_document(svg_context_t *ctx, svg_item_t *root)
if (use_transparency)
{
- code = gs_push_pdf14trans_device(ctx->pgs);
+ code = gs_push_pdf14trans_device(ctx->pgs, false);
if (code < 0)
return gs_rethrow(code, "cannot install transparency device");
}
@@ -342,7 +342,7 @@ svg_parse_document(svg_context_t *ctx, svg_item_t *root)
if (use_transparency)
{
- code = gs_pop_pdf14trans_device(ctx->pgs);
+ code = gs_pop_pdf14trans_device(ctx->pgs, false);
if (code < 0)
return gs_rethrow(code, "cannot uninstall transparency device");
}
diff --git a/xps/xpspage.c b/xps/xpspage.c
index 59a562f4b..4896ac311 100644
--- a/xps/xpspage.c
+++ b/xps/xpspage.c
@@ -208,7 +208,7 @@ xps_parse_fixed_page(xps_context_t *ctx, xps_part_t *part)
if (ctx->use_transparency && has_transparency)
{
- code = gs_push_pdf14trans_device(ctx->pgs);
+ code = gs_push_pdf14trans_device(ctx->pgs, false);
if (code < 0)
{
gs_grestore(ctx->pgs);
@@ -233,7 +233,7 @@ xps_parse_fixed_page(xps_context_t *ctx, xps_part_t *part)
code = xps_parse_resource_dictionary(ctx, &dict, base_uri, xps_down(node));
if (code)
{
- gs_pop_pdf14trans_device(ctx->pgs);
+ gs_pop_pdf14trans_device(ctx->pgs, false);
gs_grestore(ctx->pgs);
return gs_rethrow(code, "cannot load FixedPage.Resources");
}
@@ -241,7 +241,7 @@ xps_parse_fixed_page(xps_context_t *ctx, xps_part_t *part)
code = xps_parse_element(ctx, base_uri, dict, node);
if (code)
{
- gs_pop_pdf14trans_device(ctx->pgs);
+ gs_pop_pdf14trans_device(ctx->pgs, false);
gs_grestore(ctx->pgs);
return gs_rethrow(code, "cannot parse child of FixedPage");
}
@@ -249,7 +249,7 @@ xps_parse_fixed_page(xps_context_t *ctx, xps_part_t *part)
if (ctx->use_transparency && has_transparency)
{
- code = gs_pop_pdf14trans_device(ctx->pgs);
+ code = gs_pop_pdf14trans_device(ctx->pgs, false);
if (code < 0)
{
gs_grestore(ctx->pgs);