[gs-cvs] rev 8484 - trunk/gs/src
leonardo at ghostscript.com
leonardo at ghostscript.com
Wed Jan 16 14:55:45 PST 2008
Author: leonardo
Date: 2008-01-16 14:55:42 -0800 (Wed, 16 Jan 2008)
New Revision: 8484
Modified:
trunk/gs/src/gdevdflt.c
trunk/gs/src/gdevp14.c
trunk/gs/src/gdevp14.h
trunk/gs/src/gsalphac.c
trunk/gs/src/gsovrc.c
trunk/gs/src/gsovrc.h
trunk/gs/src/gstparam.h
trunk/gs/src/gstrans.c
trunk/gs/src/gstrans.h
trunk/gs/src/gxclrast.c
trunk/gs/src/gxcomp.h
trunk/gs/src/lib.mak
trunk/gs/src/zdict.c
Log:
Fix (clist interpreter) : Skip idle compositors, step 5.
DETAILS :
This really skips compositors which don't paint anything.
Compositor parameter list structures are extended with a new boolean field 'idle'.
These fields pass information whether something was painted to a compositor.
We choosen this way for passing this info because
(1) we can't change the device inteface with new function arguments, and
(2) we need to pass it through the device chain
(for example, when a clipper is installed onth the overprint device).
This patch only affects the transparency and the overprint.
Other compositors (gsalphac.c, gxropc.c) behave as before.
They may need further improvements.
This patch does not fix the bug 689492.
That fix may be done either before or after this one,
but in any case the patches need to adopt each to another.
The new compositor virtual method is_closing
checks whether a current compositor command
closes an older command, and finds the opening command.
Now we provide untrivial implementations for transparency and overprint compositors.
Would like to define an enum for return values of is_closing.
The old device method create_compositor now passes the 'idle' parameter via
gs_composite_s structure. By default it is false and the behaviour
is same as before. But the clist interpreter is modified
to provide true value when a compositor doesn't paint anything.
To compute this flag the compositor queue now works with its full power.
Note we changed the queue representation with a bilikned list.
This patch entroduces the concept of 'friendly operations'
for compositor operations. These are those operations, which
may interchange with compositor installation/deinstallation.
One example is halftone operations, which always affect
the device below the compositor device, i.e. the target device
of the compositor device. The new compositor virtual method
is_friendly is implemented in an intrivial way for the
transparency compositor especially to exchange with halftone
operations while queueing clist operations.
This especially helps to delay the pdf14 device installation
so that it may completely annihilate with its deinstallation
if nothing is painted through the compositor in a band.
Overprint and transparency compositor implementations
are changed with checking the idle flag.
If it is set, they don't perform neither color blending, nor
raster buffer allocation. Note the pdf14 device maintains the buffer stack
as before, but the allocation of buffers may be skipped.
It saves significant time from cleaning up raster buffers when they are idle.
This patch may need further improvements for the case when
different compositor types are mixed in one queue.
We could not fully test it due to absence of practical tests.
Another useful improvement would be to convert
"0 .inittransparencymask 1 .inittransparencymask dict .setblendparams"
into a single command. It would simplify the compositor queue logic.
Also we think that the name .inittransparencymask doesn't reflect the function purpose.
Will improve someday.
We're not sure whether this patch correctly works with idle masks.
We could not debug it due to no practical cases.
Possibly idle mask will need an additional effort to skip
the group painting to the band.
Also disabled cmd_put_halftone in c_pdf14trans_clist_write_update -
see comment in code.
Monor change : Inserted a visual trace support for transparency buffers.
EXPECTED DIFFERENCES :
None.
Modified: trunk/gs/src/gdevdflt.c
===================================================================
--- trunk/gs/src/gdevdflt.c 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/gdevdflt.c 2008-01-16 22:55:42 UTC (rev 8484)
@@ -845,8 +845,7 @@
return 0;
}
-/*
- * Default handler for adjusting a compositor's CTM. */
+/* Default handler for adjusting a compositor's CTM. */
int
gx_default_composite_adjust_ctm(gs_composite_t *pcte, int x0, int y0, gs_imager_state *pis)
{
@@ -854,6 +853,24 @@
}
/*
+ * Default check for closing compositor.
+ */
+int
+gx_default_composite_is_closing(const gs_composite_t *this, const gs_composite_t **pcte, gx_device *dev)
+{
+ return false;
+}
+
+/*
+ * Default check whether a next operation is friendly to the compositor.
+ */
+bool
+gx_default_composite_is_friendly(const gs_composite_t *this, byte cmd0, byte cmd1)
+{
+ return false;
+}
+
+/*
* Default handler for updating the clist device when reading a compositing
* device.
*/
Modified: trunk/gs/src/gdevp14.c
===================================================================
--- trunk/gs/src/gdevp14.c 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/gdevp14.c 2008-01-16 22:55:42 UTC (rev 8484)
@@ -41,6 +41,7 @@
#include "gxcldev.h"
#include "gxclpath.h"
#include "gxdcconv.h"
+#include "vdtrace.h"
/*
* We chose the blending color space based upon the process color model of the
@@ -507,7 +508,7 @@
* Return value: Newly allocated buffer, or NULL on failure.
**/
static pdf14_buf *
-pdf14_buf_new(gs_int_rect *rect, bool has_alpha_g, bool has_shape,
+pdf14_buf_new(gs_int_rect *rect, bool has_alpha_g, bool has_shape, bool idle,
int n_chan,
gs_memory_t *memory)
{
@@ -536,8 +537,9 @@
result->rowstride = rowstride;
result->transfer_fn = NULL;
result->maskbuf = NULL;
+ result->idle = idle;
- if (height <= 0) {
+ if (height <= 0 && !idle) {
/* Empty clipping - will skip all drawings. */
result->planestride = 0;
result->data = 0;
@@ -582,7 +584,7 @@
if (result == NULL)
return result;
- buf = pdf14_buf_new(rect, false, false, n_chan, memory);
+ buf = pdf14_buf_new(rect, false, false, false, n_chan, memory);
if (buf == NULL) {
gs_free_object(memory, result, "pdf14_ctx_new");
return NULL;
@@ -638,13 +640,14 @@
pdf14_push_transparency_group(pdf14_ctx *ctx, gs_int_rect *rect,
bool isolated, bool knockout,
byte alpha, byte shape,
- gs_blend_mode_t blend_mode)
+ gs_blend_mode_t blend_mode, bool idle)
{
pdf14_buf *tos = ctx->stack;
pdf14_buf *buf, *backdrop;
bool has_shape;
if_debug0('v', "[v]pdf14_push_transparency_group\n");
+
/* todo: fix this hack, which makes all knockout groups isolated.
For the vast majority of files, there won't be any visible
effects, but it still isn't correct. The pixel compositing code
@@ -655,7 +658,7 @@
has_shape = tos->has_shape || tos->knockout;
- buf = pdf14_buf_new(rect, !isolated, has_shape, ctx->n_chan, ctx->memory);
+ buf = pdf14_buf_new(rect, !isolated, has_shape, idle, ctx->n_chan, ctx->memory);
if_debug3('v', "[v]push buf: %d x %d, %d channels\n", buf->rect.p.x, buf->rect.p.y, buf->n_chan);
if (buf == NULL)
return_error(gs_error_VMerror);
@@ -675,6 +678,8 @@
if (buf->data == NULL)
return 0;
+ if (idle)
+ return 0;
backdrop = pdf14_find_backdrop_buf(ctx);
if (backdrop == NULL) {
@@ -729,6 +734,8 @@
ctx->maskbuf = maskbuf; /* Restore the mask saved by pdf14_push_transparency_group. */
tos->maskbuf = NULL; /* Clean the pointer sinse the mask ownership is now passed to ctx. */
+ if (tos->idle)
+ goto exit;
if (x0 < x1 && y0 < y1) {
int n_chan = ctx->n_chan;
int num_comp = n_chan - 1;
@@ -825,6 +832,7 @@
mask = mask_tr_fn[mask];
tmp = pix_alpha * mask + 0x80;
pix_alpha = (tmp + (tmp >> 8)) >> 8;
+ vd_pixel(int2fixed(x), int2fixed(y), mask);
}
if (nos_knockout) {
@@ -865,6 +873,11 @@
nos_ptr[x + i * nos_planestride] = 255 - nos_pixel[i];
nos_ptr[x + num_comp * nos_planestride] = nos_pixel[num_comp];
}
+ if (maskbuf == NULL) {
+ vd_pixel(int2fixed(x), int2fixed(y), n_chan == 1 ?
+ (nos_pixel[0] << 16) + (nos_pixel[0] << 8) + nos_pixel[0] :
+ (nos_pixel[0] << 16) + (nos_pixel[1] << 8) + nos_pixel[2]);
+ }
if (nos_alpha_g_ptr != NULL)
++nos_alpha_g_ptr;
}
@@ -877,8 +890,9 @@
}
}
+exit:
ctx->stack = nos;
- if_debug0('v', "[v]pop buf\n");
+ if_debug1('v', "[v]pop buf, idle=%d\n", tos->idle);
pdf14_buf_free(tos, ctx->memory);
if (maskbuf != NULL) {
pdf14_buf_free(maskbuf, ctx->memory);
@@ -895,12 +909,12 @@
*/
static int
pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect, byte bg_alpha,
- byte *transfer_fn)
+ byte *transfer_fn, bool idle)
{
pdf14_buf *buf;
if_debug0('v', "[v]pdf14_push_transparency_mask\n");
- buf = pdf14_buf_new(rect, false, false, ctx->n_chan, ctx->memory);
+ buf = pdf14_buf_new(rect, false, false, idle, ctx->n_chan, ctx->memory);
if (buf == NULL)
return_error(gs_error_VMerror);
@@ -925,7 +939,7 @@
{
pdf14_buf *tos = ctx->stack;
- if_debug0('v', "[v]pdf14_pop_transparency_mask\n");
+ if_debug1('v', "[v]pdf14_pop_transparency_mask, idle=%d\n", tos->idle);
ctx->stack = tos->saved;
ctx->maskbuf = tos;
return 0;
@@ -1963,9 +1977,11 @@
const gs_pdf14trans_t * pdf14pct, gs_memory_t * mem )
{
pdf14_device *p14dev = (pdf14_device *)pdev;
+ gs_pdf14trans_params_t params = pdf14pct->params;
int code = 0;
- switch (pdf14pct->params.pdf14_op) {
+ params.idle = pdf14pct->idle;
+ switch (params.pdf14_op) {
default: /* Should not occur. */
break;
case PDF14_PUSH_DEVICE:
@@ -1990,19 +2006,19 @@
pdf14_close(pdev);
break;
case PDF14_BEGIN_TRANS_GROUP:
- code = gx_begin_transparency_group(pis, pdev, &pdf14pct->params);
+ code = gx_begin_transparency_group(pis, pdev, ¶ms);
break;
case PDF14_END_TRANS_GROUP:
code = gx_end_transparency_group(pis, pdev);
break;
case PDF14_INIT_TRANS_MASK:
- code = gx_init_transparency_mask(pis, &pdf14pct->params);
+ code = gx_init_transparency_mask(pis, ¶ms);
break;
case PDF14_BEGIN_TRANS_MASK:
- code = gx_begin_transparency_mask(pis, pdev, &pdf14pct->params);
+ code = gx_begin_transparency_mask(pis, pdev, ¶ms);
break;
case PDF14_END_TRANS_MASK:
- code = gx_end_transparency_mask(pis, pdev, &pdf14pct->params);
+ code = gx_end_transparency_mask(pis, pdev, ¶ms);
break;
case PDF14_SET_BLEND_PARAMS:
pdf14_set_params(pis, pdev, &pdf14pct->params);
@@ -2210,7 +2226,7 @@
ptgp->Isolated, ptgp->Knockout,
(byte)floor (255 * alpha + 0.5),
(byte)floor (255 * pis->shape.alpha + 0.5),
- pis->blend_mode);
+ pis->blend_mode, ptgp->idle);
return code;
}
@@ -2223,7 +2239,13 @@
int code;
if_debug0('v', "[v]pdf14_end_transparency_group\n");
+ vd_get_dc('c');
+ vd_set_shift(0, 0);
+ vd_set_scale(0.01);
+ vd_set_origin(0, 0);
+ vd_erase(RGB(192, 192, 192));
code = pdf14_pop_transparency_group(pdev->ctx, pdev->blend_procs);
+ vd_release_dc;
return code;
}
@@ -2245,7 +2267,7 @@
if_debug1('v', "pdf14_begin_transparency_mask, bg_alpha = %d\n", bg_alpha);
memcpy(transfer_fn, ptmp->transfer_fn, size_of(ptmp->transfer_fn));
return pdf14_push_transparency_mask(pdev->ctx, &pdev->ctx->rect, bg_alpha,
- transfer_fn);
+ transfer_fn, ptmp->idle);
}
static int
@@ -2857,11 +2879,11 @@
return gs_error_rangecheck;
}
- /* If we are writing more than the maximum ever expected,
- * return a rangecheck error.
- */
- if ( need > MAX_CLIST_COMPOSITOR_SIZE )
- return_error(gs_error_rangecheck);
+ /* If we are writing more than the maximum ever expected,
+ * return a rangecheck error.
+ */
+ if ( need > MAX_CLIST_COMPOSITOR_SIZE )
+ return_error(gs_error_rangecheck);
/* Copy our serialzed data into the output buffer */
memcpy(data, buf, need - mask_size);
@@ -2908,6 +2930,8 @@
read_value(data, params.num_spot_colors);
break;
case PDF14_POP_DEVICE:
+ code += 0; /* A good place for a breakpoint. */
+ break;
case PDF14_END_TRANS_GROUP:
break; /* No data */
case PDF14_BEGIN_TRANS_GROUP:
@@ -3037,11 +3061,130 @@
return code;
}
+/*
+ * Find an opening compositor op.
+ */
+static int
+find_opening_op(int opening_op, const gs_composite_t **ppcte)
+{
+ /* Assuming a right *BEGIN* - *END* operation balance. */
+ const gs_composite_t *pcte = *ppcte;
+
+ for (;;) {
+ if (pcte->type->comp_id == GX_COMPOSITOR_PDF14_TRANS) {
+ gs_pdf14trans_t *pct = (gs_pdf14trans_t *)pcte;
+ int op = pct->params.pdf14_op;
+
+ *ppcte = pcte;
+ if (op == opening_op)
+ return 1;
+ if (op != PDF14_INIT_TRANS_MASK && op != PDF14_SET_BLEND_PARAMS)
+ return 0;
+ } else
+ return 0;
+ pcte = pcte->prev;
+ if (pcte == NULL)
+ return 2; /* Not in queue. */
+ }
+}
+
+/*
+ * Find an opening compositor op.
+ */
+static int
+find_same_op(const gs_composite_t *this, int my_op, const gs_composite_t **ppcte)
+{
+ const gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)this;
+ const gs_composite_t *pct = *ppcte;
+
+ for (;;) {
+ if (pct->type->comp_id == GX_COMPOSITOR_PDF14_TRANS) {
+ gs_pdf14trans_t *pct_pdf14 = (gs_pdf14trans_t *)pct;
+
+ *ppcte = pct;
+ if (pct_pdf14->params.pdf14_op != my_op)
+ return 0;
+ if (pct_pdf14->params.csel == pct0->params.csel)
+ return 4;
+ } else
+ return 0;
+ pct = pct->prev;
+ if (pct == NULL)
+ return 0; /* Not in queue. */
+ }
+}
+
+/*
+ * Check for closing compositor.
+ */
+static int
+c_pdf14trans_is_closing(const gs_composite_t * this, const gs_composite_t ** ppcte, gx_device *dev)
+{
+ gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)this;
+ gs_pdf14trans_t *pct1 = (gs_pdf14trans_t *)*ppcte;
+ int op0 = pct0->params.pdf14_op;
+
+ switch (op0) {
+ default: return_error(gs_error_unregistered); /* Must not happen. */
+ case PDF14_PUSH_DEVICE:
+ return 0;
+ case PDF14_POP_DEVICE:
+ if (*ppcte == NULL)
+ return 0;
+ else {
+ int code = find_opening_op(PDF14_PUSH_DEVICE, ppcte);
+
+ if (code == 1)
+ return 5;
+ return code;
+ }
+ case PDF14_BEGIN_TRANS_GROUP:
+ return 0;
+ case PDF14_END_TRANS_GROUP:
+ if (*ppcte == NULL)
+ return 2;
+ return find_opening_op(PDF14_BEGIN_TRANS_GROUP, ppcte);
+ case PDF14_INIT_TRANS_MASK:
+ if (*ppcte == NULL)
+ return 0;
+ return find_same_op(this, PDF14_INIT_TRANS_MASK, ppcte);
+ case PDF14_BEGIN_TRANS_MASK:
+ return 0;
+ case PDF14_END_TRANS_MASK:
+ if (*ppcte == NULL)
+ return 2;
+ return find_opening_op(PDF14_BEGIN_TRANS_MASK, ppcte);
+ case PDF14_SET_BLEND_PARAMS:
+ return 0;
+ }
+}
+
+/*
+ * Check whether a next operation is friendly to the compositor.
+ */
+static bool
+c_pdf14trans_is_friendly(const gs_composite_t * this, byte cmd0, byte cmd1)
+{
+ gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)this;
+ int op0 = pct0->params.pdf14_op;
+
+ if (op0 == PDF14_PUSH_DEVICE) {
+ if (cmd0 == cmd_opv_extend && (cmd1 == cmd_opv_ext_put_halftone ||
+ cmd1 == cmd_opv_ext_put_ht_seg))
+ return true;
+ if (cmd0 == cmd_opv_set_misc && (cmd1 >> 6) == (cmd_set_misc_map >> 6))
+ return true;
+ }
+ return false;
+}
+
static composite_create_default_compositor_proc(c_pdf14trans_create_default_compositor);
static composite_equal_proc(c_pdf14trans_equal);
static composite_write_proc(c_pdf14trans_write);
static composite_read_proc(c_pdf14trans_read);
static composite_adjust_ctm_proc(c_pdf14trans_adjust_ctm);
+static composite_is_closing_proc(c_pdf14trans_is_closing);
+static composite_is_àêøóòâäí_proc(c_pdf14trans_is_àêøóòâäí);
static composite_clist_write_update(c_pdf14trans_clist_write_update);
static composite_clist_read_update(c_pdf14trans_clist_read_update);
@@ -3062,6 +3205,8 @@
c_pdf14trans_write, /* procs.write */
c_pdf14trans_read, /* procs.read */
c_pdf14trans_adjust_ctm, /* procs.adjust_ctm */
+ c_pdf14trans_is_closing, /* procs.is_closing */
+ c_pdf14trans_is_friendly, /* procs.is_friendly */
/* Create a PDF 1.4 clist write device */
c_pdf14trans_clist_write_update, /* procs.composite_clist_write_update */
c_pdf14trans_clist_read_update /* procs.composite_clist_reade_update */
@@ -3076,6 +3221,8 @@
c_pdf14trans_write, /* procs.write */
c_pdf14trans_read, /* procs.read */
c_pdf14trans_adjust_ctm, /* procs.adjust_ctm */
+ c_pdf14trans_is_closing, /* procs.is_closing */
+ c_pdf14trans_is_friendly, /* procs.is_friendly */
/* The PDF 1.4 clist writer already exists, Do not create it. */
gx_default_composite_clist_write_update, /* procs.composite_clist_write_update */
c_pdf14trans_clist_read_update /* procs.composite_clist_reade_update */
@@ -3110,6 +3257,7 @@
pct->type = &gs_composite_pdf14trans_type;
pct->id = gs_next_ids(mem, 1);
pct->params = *pparams;
+ pct->idle = false;
*ppct = (gs_composite_t *)pct;
return 0;
}
@@ -4235,6 +4383,7 @@
gx_set_cmap_procs(pis, dev);
return code;
case PDF14_POP_DEVICE:
+# if 0 /* Disabled because pdf14_clist_create_compositor does so. */
/*
* Ensure that the tranfer functions, etc. are current before we
* dump our transparency image to the output device.
@@ -4242,6 +4391,9 @@
if (pis->dev_ht)
code = cmd_put_halftone((gx_device_clist_writer *)
(((pdf14_clist_device *)dev)->target), pis->dev_ht);
+# else
+ code = 0;
+# endif
break;
default:
break; /* do nothing for remaining ops */
Modified: trunk/gs/src/gdevp14.h
===================================================================
--- trunk/gs/src/gdevp14.h 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/gdevp14.h 2008-01-16 22:55:42 UTC (rev 8484)
@@ -55,6 +55,7 @@
byte *transfer_fn;
gs_int_rect bbox;
pdf14_buf *maskbuf; /* Save pdf14_ctx_s::maksbuf. */
+ bool idle;
};
struct pdf14_ctx_s {
Modified: trunk/gs/src/gsalphac.c
===================================================================
--- trunk/gs/src/gsalphac.c 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/gsalphac.c 2008-01-16 22:55:42 UTC (rev 8484)
@@ -101,6 +101,8 @@
c_alpha_write,
c_alpha_read,
gx_default_composite_adjust_ctm,
+ gx_default_composite_is_closing,
+ gx_default_composite_is_friendly,
gx_default_composite_clist_write_update,
gx_default_composite_clist_read_update
}
@@ -127,6 +129,7 @@
pcte->type = &gs_composite_alpha_type;
pcte->id = gs_next_ids(mem, 1);
pcte->params = *params;
+ pcte->idle = false;
*ppcte = (gs_composite_t *) pcte;
return 0;
}
Modified: trunk/gs/src/gsovrc.c
===================================================================
--- trunk/gs/src/gsovrc.c 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/gsovrc.c 2008-01-16 22:55:42 UTC (rev 8484)
@@ -184,6 +184,7 @@
if_debug1('v', "[v]c_overprint_read(%d)\n", flags);
params.retain_any_comps = (flags & OVERPRINT_ANY_COMPS) != 0;
params.retain_spot_comps = (flags & OVERPRINT_SPOT_COMPS) != 0;
+ params.idle = 0;
/* check if the drawn_comps array is present */
if (params.retain_any_comps && !params.retain_spot_comps) {
@@ -198,11 +199,22 @@
return code < 0 ? code : nbytes;
}
+/*
+ * Check for closing compositor.
+ */
+static int
+c_overprint_is_closing(const gs_composite_t *this, const gs_composite_t **ppcte, gx_device *dev)
+{
+ if (*ppcte != NULL && (*ppcte)->type->comp_id != GX_COMPOSITOR_OVERPRINT)
+ return 0;
+ return 3;
+}
static composite_create_default_compositor_proc(c_overprint_create_default_compositor);
static composite_create_default_compositor_proc(c_overprint_create_default_compositor);
static composite_equal_proc(c_overprint_equal);
static composite_write_proc(c_overprint_write);
+static composite_is_closing_proc(c_overprint_is_closing);
static composite_read_proc(c_overprint_read);
static composite_adjust_ctm_proc(c_overprint_adjust_ctm);
@@ -215,6 +227,8 @@
c_overprint_write, /* procs.write */
c_overprint_read, /* procs.read */
gx_default_composite_adjust_ctm,
+ c_overprint_is_closing,
+ gx_default_composite_is_friendly,
gx_default_composite_clist_write_update,/* procs.composite_clist_write_update */
gx_default_composite_clist_read_update /* procs.composite_clist_reade_update */
} /* procs */
@@ -241,6 +255,7 @@
pct->type = &gs_composite_overprint_type;
pct->id = gs_next_ids(mem, 1);
pct->params = *pparams;
+ pct->idle = false;
*ppct = (gs_composite_t *)pct;
return 0;
}
@@ -656,7 +671,7 @@
int ncomps = opdev->color_info.num_components;
/* check if overprint is to be turned off */
- if (!pparams->retain_any_comps) {
+ if (!pparams->retain_any_comps || pparams->idle) {
/* if fill_rectangle forwards, overprint is already off */
if (dev_proc(opdev, fill_rectangle) != gx_forward_fill_rectangle)
memcpy( &opdev->procs,
@@ -825,12 +840,14 @@
if (pct->type != &gs_composite_overprint_type)
return gx_default_create_compositor(dev, pcdev, pct, pis, memory);
else {
+ gs_overprint_params_t params = ((const gs_overprint_t *)pct)->params;
int code;
+ params.idle = pct->idle;
/* device must already exist, so just update the parameters */
code = update_overprint_params(
(overprint_device_t *)dev,
- &((const gs_overprint_t *)pct)->params );
+ ¶ms );
if (code >= 0)
*pcdev = dev;
return code;
@@ -976,12 +993,17 @@
{
const gs_overprint_t * ovrpct = (const gs_overprint_t *)pct;
overprint_device_t * opdev = 0;
+ gs_overprint_params_t params;
/* see if there is anything to do */
if ( !ovrpct->params.retain_any_comps) {
*popdev = tdev;
return 0;
}
+ if (pct->idle) {
+ *popdev = tdev;
+ return 0;
+ }
/* check if the procedure arrays have been initialized */
if (no_overprint_procs.get_xfont_procs == 0) {
@@ -1004,7 +1026,9 @@
gx_device_copy_params((gx_device *)opdev, tdev);
gx_device_set_target((gx_device_forward *)opdev, tdev);
+ params = ovrpct->params;
+ params.idle = ovrpct->idle;
+
/* set up the overprint parameters */
- return update_overprint_params( opdev,
- &((const gs_overprint_t *)pct)->params );
+ return update_overprint_params( opdev, ¶ms);
}
Modified: trunk/gs/src/gsovrc.h
===================================================================
--- trunk/gs/src/gsovrc.h 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/gsovrc.h 2008-01-16 22:55:42 UTC (rev 8484)
@@ -260,6 +260,12 @@
*/
bool retain_spot_comps;
+ /*
+ * Don't we print anything with overprint ?
+ * This info may come from the clist reader.
+ */
+ bool idle;
+
/*
* The list of color model compoents to be retained (i.e.: that are
* not affected by drawing operations). The field is bit-encoded;
Modified: trunk/gs/src/gstparam.h
===================================================================
--- trunk/gs/src/gstparam.h 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/gstparam.h 2008-01-16 22:55:42 UTC (rev 8484)
@@ -83,6 +83,7 @@
bool Isolated;
bool Knockout;
bool image_with_SMask;
+ bool idle;
} gs_transparency_group_params_t;
/* Define the parameter structure for a transparency mask. */
@@ -114,6 +115,7 @@
float Background[GS_CLIENT_COLOR_MAX_COMPONENTS];
float GrayBackground;
bool function_is_identity;
+ bool idle;
byte transfer_fn[MASK_TRANSFER_FUNCTION_SIZE];
} gx_transparency_mask_params_t;
Modified: trunk/gs/src/gstrans.c
===================================================================
--- trunk/gs/src/gstrans.c 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/gstrans.c 2008-01-16 22:55:42 UTC (rev 8484)
@@ -233,6 +233,7 @@
return_error(gs_error_rangecheck);
tgp.Isolated = pparams->Isolated;
tgp.Knockout = pparams->Knockout;
+ tgp.idle = pparams->idle;
pis->opacity.alpha = pparams->opacity.alpha;
pis->shape.alpha = pparams->shape.alpha;
pis->blend_mode = pparams->blend_mode;
@@ -349,6 +350,7 @@
memcpy(tmp.Background, pparams->Background, l);
tmp.GrayBackground = pparams->GrayBackground;
tmp.function_is_identity = pparams->function_is_identity;
+ tmp.idle = pparams->idle;
memcpy(tmp.transfer_fn, pparams->transfer_fn, size_of(tmp.transfer_fn));
if_debug8('v', "[v](0x%lx)gx_begin_transparency_mask [%g %g %g %g]\n\
subtype = %d Background_components = %d %s\n",
Modified: trunk/gs/src/gstrans.h
===================================================================
--- trunk/gs/src/gstrans.h 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/gstrans.h 2008-01-16 22:55:42 UTC (rev 8484)
@@ -91,6 +91,7 @@
gs_transparency_source_t shape;
bool mask_is_image;
gs_matrix ctm;
+ bool idle;
};
#ifndef gs_pdf14trans_params_DEFINED
Modified: trunk/gs/src/gxclrast.c
===================================================================
--- trunk/gs/src/gxclrast.c 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/gxclrast.c 2008-01-16 22:55:42 UTC (rev 8484)
@@ -270,14 +270,17 @@
enqueue_compositor(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last, gs_composite_t *pcomp)
{
if (*ppcomp_last == NULL) {
- pcomp->prev = NULL;
+ pcomp->prev = pcomp->next = NULL;
*ppcomp_last = *ppcomp_first = pcomp;
} else {
+ (*ppcomp_last)->next = pcomp;
pcomp->prev = *ppcomp_last;
+ pcomp->next = NULL;
*ppcomp_last = pcomp;
}
}
+#if 0 /* Appears unused - keep for a while. */
static inline gs_composite_t *
dequeue_last_compositor(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last)
{
@@ -287,29 +290,152 @@
*ppcomp_first = *ppcomp_last = NULL;
else {
*ppcomp_last = (*ppcomp_last)->prev;
+ pcomp->prev = NULL;
+ (*ppcomp_last)->next = NULL;
}
return pcomp;
}
+static inline gs_composite_t *
+dequeue_first_compositor(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last)
+{
+ gs_composite_t *pcomp = *ppcomp_first;
+
+ if (*ppcomp_first == *ppcomp_last)
+ *ppcomp_first = *ppcomp_last = NULL;
+ else {
+ *ppcomp_first = (*ppcomp_first)->next;
+ pcomp->next = NULL;
+ (*ppcomp_last)->prev = NULL;
+ }
+ return pcomp;
+}
+#endif
+
+static inline int
+dequeue_compositor(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last, gs_composite_t *pcomp)
+{
+ if (*ppcomp_last == *ppcomp_first) {
+ if (*ppcomp_last == pcomp) {
+ *ppcomp_last = *ppcomp_first = NULL;
+ return 0;
+ } else
+ return_error(gs_error_unregistered); /* Must not happen. */
+ } else {
+ gs_composite_t *pcomp_next = pcomp->next, *pcomp_prev = pcomp->prev;
+
+ if (*ppcomp_last == pcomp)
+ *ppcomp_last = pcomp->prev;
+ else
+ pcomp_next->prev = pcomp_prev;
+ if (*ppcomp_first == pcomp)
+ *ppcomp_first = pcomp->next;
+ else
+ pcomp_prev->next = pcomp_next;
+ pcomp->next = pcomp->prev = NULL;
+ return 0;
+ }
+}
+
static inline void
-free_compositor(gs_composite_t *pcomp)
+free_compositor(gs_composite_t *pcomp, gs_memory_t *mem)
{
- /* Fixme: todo. */
+ gs_free_object(mem, pcomp, "free_compositor");
}
static inline bool
is_null_compositor_op(const byte *cbp, int *length)
{
- /* Fixme: todo. */
+ if (cbp[0] == cmd_opv_end_run) {
+ *length = 1;
+ return true;
+ }
return false;
}
-is_closing_compositor(gs_composite_t *pcomp0, gs_composite_t *pcomp1)
+static int
+execute_compositor_queue(gx_device_clist_reader *cdev, gx_device **target, gx_device **tdev, gs_imager_state *pis,
+ gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last, gs_composite_t *pcomp_from,
+ int x0, int y0, gs_memory_t *mem, bool idle)
{
- /* Fixme: todo. */
- return false;
+ while (pcomp_from != NULL) {
+ gs_composite_t *pcomp = pcomp_from;
+ int code;
+
+ pcomp_from = pcomp->next;
+ code = dequeue_compositor(ppcomp_first, ppcomp_last, pcomp);
+ if (code < 0)
+ return code;
+ pcomp->idle = idle;
+ code = apply_create_compositor(cdev, pis, mem, pcomp, x0, y0, target); /* Releases the compositor. */
+ if (code < 0)
+ return code;
+ *tdev = *target;
+ }
+ return 0;
}
+static inline void
+drop_compositor_queue(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last,
+ gs_composite_t *pcomp_from, gs_memory_t *mem)
+{
+ gs_composite_t *pcomp;
+
+ do {
+ pcomp = *ppcomp_last;
+ dequeue_compositor(ppcomp_first, ppcomp_last, *ppcomp_last);
+ free_compositor(pcomp, mem);
+ } while (pcomp != pcomp_from);
+}
+
+static int
+read_set_misc_map(byte cb, command_buf_t *pcb, gs_imager_state *pis, gs_memory_t *mem)
+{
+ const byte *cbp = pcb->ptr;
+ frac *mdata;
+ int *pcomp_num;
+ uint count;
+ cmd_map_contents cont =
+ (cmd_map_contents)(cb & 0x30) >> 4;
+ int code;
+
+ code = cmd_select_map(cb & 0xf, cont,
+ pis,
+ &pcomp_num,
+ &mdata, &count, mem);
+
+ if (code < 0)
+ return code;
+ /* Get component number if relevant */
+ if (pcomp_num == NULL)
+ cbp++;
+ else {
+ *pcomp_num = (int) *cbp++;
+ if_debug1('L', " comp_num=%d",
+ *pcomp_num);
+ }
+ if (cont == cmd_map_other) {
+ cbp = cmd_read_data(pcb, (byte *)mdata, count, cbp);
+
+#ifdef DEBUG
+ if (gs_debug_c('L')) {
+ uint i;
+
+ for (i = 0; i < count / sizeof(*mdata); ++i)
+ dprintf1(" 0x%04x", mdata[i]);
+ dputc('\n');
+ }
+ } else {
+ if_debug0('L', " none\n");
+#endif
+ }
+ /* Recompute the effective transfer, */
+ /* in case this was a transfer map. */
+ gx_imager_set_effective_xfer(pis);
+ pcb->ptr = cbp;
+ return 0;
+}
+
int
clist_playback_band(clist_playback_action playback_action,
gx_device_clist_reader *cdev, stream *s,
@@ -551,46 +677,11 @@
if_debug1('L', " data_x=%d\n", data_x);
break;
case cmd_set_misc_map >> 6:
- {
- frac *mdata;
- int *pcomp_num;
- uint count;
- cmd_map_contents cont =
- (cmd_map_contents)(cb & 0x30) >> 4;
-
- code = cmd_select_map(cb & 0xf, cont,
- &imager_state,
- &pcomp_num,
- &mdata, &count, mem);
-
- if (code < 0)
- goto out;
- /* Get component number if relevant */
- if (pcomp_num == NULL)
- cbp++;
- else {
- *pcomp_num = (int) *cbp++;
- if_debug1('L', " comp_num=%d",
- *pcomp_num);
- }
- if (cont == cmd_map_other) {
- cmd_read((byte *)mdata, count, cbp);
-#ifdef DEBUG
- if (gs_debug_c('L')) {
- uint i;
-
- for (i = 0; i < count / sizeof(*mdata); ++i)
- dprintf1(" 0x%04x", mdata[i]);
- dputc('\n');
- }
- } else {
- if_debug0('L', " none\n");
-#endif
- }
- }
- /* Recompute the effective transfer, */
- /* in case this was a transfer map. */
- gx_imager_set_effective_xfer(&imager_state);
+ cbuf.ptr = cbp;
+ code = read_set_misc_map(cb, &cbuf, &imager_state, mem);
+ if (code < 0)
+ goto out;
+ cbp = cbuf.ptr;
break;
case cmd_set_misc_halftone >> 6: {
uint num_comp;
@@ -1323,8 +1414,13 @@
for (;;) {
int len;
+ if (cbp >= cbuf.limit) {
+ code = top_up_cbuf(&cbuf, &cbp);
+ if (code < 0)
+ goto out;
+ }
if (cbp[0] == cmd_opv_extend && cbp[1] == cmd_opv_ext_create_compositor) {
- gs_composite_t *pcomp;
+ gs_composite_t *pcomp, *pcomp_opening;
cbuf.ptr = cbp += 2;
code = read_create_compositor(&cbuf, mem, &pcomp);
@@ -1333,40 +1429,126 @@
cbp = cbuf.ptr;
if (pcomp == NULL)
continue;
- if (pcomp_last != NULL && is_closing_compositor(pcomp_last, pcomp)) {
- /* Annigilate the 2 compositors. */
- free_compositor(pcomp);
- pcomp = dequeue_last_compositor(&pcomp_first, &pcomp_last);
- free_compositor(pcomp);
- } else
+ pcomp_opening = pcomp_last;
+ code = pcomp->type->procs.is_closing(pcomp, &pcomp_opening, tdev);
+ if (code < 0)
+ goto out;
+ else if (code == 0) {
enqueue_compositor(&pcomp_first, &pcomp_last, pcomp);
- } else if (is_null_compositor_op(cbp, &len)) {
- cbuf.ptr = cbp += len;
- } else if (pcomp_first != NULL) {
- gs_composite_t *pcomp = pcomp_last, *pcomp_ahead, *pcomp_back = NULL;
-
- /* Reverse the queue: */
- while (pcomp != NULL) {
- pcomp_ahead = pcomp->prev;
- pcomp->prev = pcomp_back;
- pcomp_back = pcomp;
- pcomp = pcomp_ahead;
- }
- pcomp_back = pcomp_last;
- pcomp_last = pcomp_first;
- pcomp_first = pcomp_back;
- /* Apply and clean the queue: */
- while (pcomp_last != NULL) {
- pcomp = dequeue_last_compositor(&pcomp_first, &pcomp_last);
- code = apply_create_compositor(cdev, &imager_state,
- mem, pcomp, x0, y0, &target); /* Releases the compositor. */
+ } else if (code == 1) {
+ /* Annihilate the last compositors. */
+ enqueue_compositor(&pcomp_first, &pcomp_last, pcomp);
+ code = execute_compositor_queue(cdev, &target, &tdev,
+ &imager_state, &pcomp_first, &pcomp_last, pcomp_opening, x0, y0, mem, true);
if (code < 0)
goto out;
- tdev = target;
+ } else if (code == 2) {
+ /* The opening command was executed. Execute the queue. */
+ enqueue_compositor(&pcomp_first, &pcomp_last, pcomp);
+ code = execute_compositor_queue(cdev, &target, &tdev,
+ &imager_state, &pcomp_first, &pcomp_last, pcomp_first, x0, y0, mem, false);
+ if (code < 0)
+ goto out;
+ } else if (code == 3) {
+ /* Replace last compositors. */
+ code = execute_compositor_queue(cdev, &target, &tdev,
+ &imager_state, &pcomp_first, &pcomp_last, pcomp_opening, x0, y0, mem, true);
+ if (code < 0)
+ goto out;
+ enqueue_compositor(&pcomp_first, &pcomp_last, pcomp);
+ } else if (code == 4) {
+ /* Replace specific compositor. */
+ code = dequeue_compositor(&pcomp_first, &pcomp_last, pcomp_opening);
+ if (code < 0)
+ goto out;
+ enqueue_compositor(&pcomp_first, &pcomp_last, pcomp);
+ free_compositor(pcomp_opening, mem);
+ } else if (code == 5) {
+ enqueue_compositor(&pcomp_first, &pcomp_last, pcomp);
+ drop_compositor_queue(&pcomp_first, &pcomp_last, pcomp_opening, mem);
+ } else {
+ code = gs_note_error(gs_error_unregistered); /* Must not happen. */
+ goto out;
}
+ } else if (is_null_compositor_op(cbp, &len)) {
+ cbuf.ptr = cbp += len;
+ } else if (cbp[0] == cmd_opv_end_page) {
+ /* End page, drop the queue. */
+ code = execute_compositor_queue(cdev, &target, &tdev,
+ &imager_state, &pcomp_first, &pcomp_last, pcomp_first, x0, y0, mem, true);
+ if (code < 0)
+ goto out;
break;
- }
+ } else if (pcomp_last != NULL &&
+ pcomp_last->type->procs.is_friendly(pcomp_last, cbp[0], cbp[1])) {
+ /* Immediately execute friendly commands
+ inside the compositor lookahead loop.
+ Currently there are few friendly commands for the pdf14 compositor only
+ due to the logic defined in c_pdf14trans_is_friendly.
+ This code duplicates some code portions from the main loop,
+ but we have no better idea with no slowdown to the main loop.
+ */
+ uint cb;
+
+ switch (*cbp++) {
+ case cmd_opv_extend:
+ switch (*cbp++) {
+ case cmd_opv_ext_put_halftone:
+ {
+ uint ht_size;
+
+ enc_u_getw(ht_size, cbp);
+ code = read_alloc_ht_buff(&ht_buff, ht_size, mem);
+ if (code < 0)
+ goto out;
+ }
+ break;
+ case cmd_opv_ext_put_ht_seg:
+ cbuf.ptr = cbp;
+ code = read_ht_segment(&ht_buff, &cbuf,
+ &imager_state, tdev,
+ mem);
+ cbp = cbuf.ptr;
+ if (code < 0)
+ goto out;
+ break;
+ default:
+ code = gs_note_error(gs_error_unregistered); /* Must not happen. */
+ goto out;
+ }
+ break;
+ case cmd_opv_set_misc:
+ cb = *cbp++;
+ switch (cb >> 6) {
+ case cmd_set_misc_map >> 6:
+ cbuf.ptr = cbp;
+ code = read_set_misc_map(cb, &cbuf, &imager_state, mem);
+ if (code < 0)
+ goto out;
+ cbp = cbuf.ptr;
+ break;
+ default:
+ code = gs_note_error(gs_error_unregistered); /* Must not happen. */
+ goto out;
+ }
+ break;
+ default:
+ code = gs_note_error(gs_error_unregistered); /* Must not happen. */
+ goto out;
+ }
+ } else {
+ /* A drawing command, execute the queue. */
+ code = execute_compositor_queue(cdev, &target, &tdev,
+ &imager_state, &pcomp_first, &pcomp_last, pcomp_first, x0, y0, mem, false);
+ if (code < 0)
+ goto out;
+ break;
+ }
}
+ if (pcomp_last != NULL) {
+ code = gs_note_error(gs_error_unregistered);
+ goto out;
+ }
break;
case cmd_opv_ext_put_halftone:
{
@@ -1796,13 +1978,8 @@
ht_buff.ht_size = 0;
ht_buff.read_size = 0;
- /* Release the compositor queue. */
- while (pcomp_last != NULL) {
- gs_composite_t *pcomp = dequeue_last_compositor(&pcomp_first, &pcomp_last);
-
- free_compositor(pcomp);
- }
-
+ if (pcomp_last != NULL)
+ drop_compositor_queue(&pcomp_first, &pcomp_last, NULL, mem);
rc_decrement(pcs, "clist_playback_band");
gx_cpath_free(&clip_path, "clist_render_band exit");
gx_path_free(&path, "clist_render_band exit");
Modified: trunk/gs/src/gxcomp.h
===================================================================
--- trunk/gs/src/gxcomp.h 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/gxcomp.h 2008-01-16 22:55:42 UTC (rev 8484)
@@ -105,15 +105,32 @@
composite_read_proc((*read));
/*
- * Convert the string representation of a function back to
- * a structure, allocating the structure. Return the number of
- * bytes read, or < 0 in the event of an error.
+ * Adjust CTM before applying the compositor. Used with banding.
*/
#define composite_adjust_ctm_proc(proc)\
int proc(gs_composite_t *pcte, int x0, int y0, gs_imager_state *pis)
composite_adjust_ctm_proc((*adjust_ctm));
/*
+ * Checks whether a next compositor operation closes this one.
+ * Must set the 2nd argument with a pointer to the opening compositor operation.
+ * Return coides : <0 - error, 0 - not closing,
+ * 1 - closing with annihilation, 2 - execute immediately,
+ * 3 - closing and replacing, 4 - replace one, 5 - drop queue.
+ */
+#define composite_is_closing_proc(proc)\
+ int proc(const gs_composite_t *this, const gs_composite_t **pcte, gx_device *dev)
+ composite_is_closing_proc((*is_closing));
+
+ /*
+ * Checks whether a next operation is friendly to the compositor
+ * so that it may commutate with the compositor operation.
+ */
+#define composite_is_friendly_proc(proc)\
+ bool proc(const gs_composite_t *this, byte cmd0, byte cmd1)
+ composite_is_friendly_proc((*is_friendly));
+
+ /*
* Update the clist write device when a compositor device is created.
*/
#define composite_clist_write_update(proc)\
@@ -142,11 +159,15 @@
*/
composite_clist_write_update(gx_default_composite_clist_write_update);
-/*
- * Default handler for adjusting a compositor's CTM. */
+/* Default handler for adjusting a compositor's CTM. */
composite_adjust_ctm_proc(gx_default_composite_adjust_ctm);
+/* Default check for closing compositor. */
+composite_is_closing_proc(gx_default_composite_is_closing);
+/* Default check for a friendly command to a compositor. */
+composite_is_friendly_proc(gx_default_composite_is_friendly);
+
/*
* Default implementation for adjusting the clist reader when a compositor
* device is added. The default does nothing.
@@ -162,7 +183,8 @@
#define gs_composite_common\
const gs_composite_type_t *type;\
gs_id id; /* see gscompt.h */\
- struct gs_composite_s *prev /* A queue link for clist_playback_band. */
+ bool idle; /* Doesn't paint anything. */\
+ struct gs_composite_s *prev, *next /* Queue links for clist_playback_band. */
struct gs_composite_s {
gs_composite_common;
Modified: trunk/gs/src/lib.mak
===================================================================
--- trunk/gs/src/lib.mak 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/lib.mak 2008-01-16 22:55:42 UTC (rev 8484)
@@ -2563,7 +2563,7 @@
$(gscdefs_h) $(gxdevice_h) $(gsdevice_h) $(gsstruct_h) $(gxistate_h) $(gxdcolor_h)\
$(gxiparam_h) $(gstparam_h) $(gxblend_h) $(gxtext_h) $(gsdfilt_h) $(gsimage_h)\
$(gsrect_h) $(gzstate_h) $(gdevdevn_h) $(gdevp14_h) $(gsovrc_h) $(gxcmap_h) $(gscolor1_h)\
- $(gstrans_h) $(gsutil_h) $(gxcldev_h) $(gxclpath_h) $(gxdcconv_h)
+ $(gstrans_h) $(gsutil_h) $(gxcldev_h) $(gxclpath_h) $(gxdcconv_h) $(vdtrace_h)
$(GLCC) $(GLO_)gdevp14.$(OBJ) $(C_) $(GLSRC)gdevp14.c
translib_=$(GLOBJ)gstrans.$(OBJ) $(GLOBJ)gximag3x.$(OBJ)\
Modified: trunk/gs/src/zdict.c
===================================================================
--- trunk/gs/src/zdict.c 2008-01-16 19:11:19 UTC (rev 8483)
+++ trunk/gs/src/zdict.c 2008-01-16 22:55:42 UTC (rev 8484)
@@ -145,8 +145,10 @@
if (dict_find(dsp, op1, &pvslot) <= 0)
return idict_put(dsp, op1, op);
ra:
- ref_assign_old_inline(&dsp->value.pdict->values, pvslot, op,
- "dict_put(value)");
+ if ((pvslot->tas.type_attrs & (&i_ctx_p->memory)->test_mask) == 0)
+ alloc_save_change(idmemory, &dsp->value.pdict->values, (ref_packed *)pvslot, "dict_put(value)");
+ ref_assign_new_inline(pvslot,op);
+
return 0;
}
int
More information about the gs-cvs
mailing list