summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base/gdevbbox.c6
-rw-r--r--base/gdevdflt.c4
-rw-r--r--base/gdevnfwd.c6
-rw-r--r--base/gdevp14.c54
-rw-r--r--base/gdevsclass.c46
-rw-r--r--base/gsovrc.c6
-rw-r--r--base/gsstate.c2
-rw-r--r--base/gstrans.c3
-rw-r--r--base/gxclimag.c8
-rw-r--r--base/gxclrast.c17
-rw-r--r--doc/Drivers.htm24
11 files changed, 115 insertions, 61 deletions
diff --git a/base/gdevbbox.c b/base/gdevbbox.c
index 33a421dbc..442b3ab00 100644
--- a/base/gdevbbox.c
+++ b/base/gdevbbox.c
@@ -1245,7 +1245,7 @@ bbox_create_compositor(gx_device * dev,
(target, &temp_cdev, pcte, pgs, memory, cindev);
/* If the target did not create a new compositor then we are done. */
- if (code < 0 || target == temp_cdev) {
+ if (code <= 0) {
*pcdev = dev;
return code;
}
@@ -1261,7 +1261,9 @@ bbox_create_compositor(gx_device * dev,
bbcdev->box_procs = box_procs_forward;
bbcdev->box_proc_data = bdev;
*pcdev = (gx_device *) bbcdev;
- return 0;
+ /* We return 1 to indicate that a new compositor was created
+ * that wrapped dev. */
+ return 1;
}
}
diff --git a/base/gdevdflt.c b/base/gdevdflt.c
index 3ad2d474a..310b716c5 100644
--- a/base/gdevdflt.c
+++ b/base/gdevdflt.c
@@ -1692,6 +1692,10 @@ int gx_subclass_create_compositor(gx_device *dev, gx_device **pcdev, const gs_co
p14dev->target = subclass_device;
+ /* We return 0, rather than 1, as we have not created
+ * a new compositor that wraps dev. */
+ if (code == 1)
+ code = 0;
return code;
}
break;
diff --git a/base/gdevnfwd.c b/base/gdevnfwd.c
index b81ff0e13..041b5b91a 100644
--- a/base/gdevnfwd.c
+++ b/base/gdevnfwd.c
@@ -1009,6 +1009,12 @@ gx_forward_create_compositor(gx_device * dev, gx_device ** pcdev,
code = dev_proc(tdev, create_compositor)(tdev, pcdev, pcte, pgs, memory, cdev);
/* the compositor may have changed color_info. Pick up the new value */
dev->color_info = tdev->color_info;
+ if (code == 1) {
+ /* If a new compositor was made that wrapped tdev, then that
+ * compositor should be our target now. */
+ gx_device_set_target((gx_device_forward *)dev, *pcdev);
+ code = 0; /* We have not made a new compositor that wrapped dev. */
+ }
return code;
}
diff --git a/base/gdevp14.c b/base/gdevp14.c
index 803e5029d..1d443b7ff 100644
--- a/base/gdevp14.c
+++ b/base/gdevp14.c
@@ -68,6 +68,7 @@
#else
#define CAL_SLOP 0
#endif
+#include "assert_.h"
#if RAW_DUMP
unsigned int global_index = 0;
@@ -5923,7 +5924,6 @@ pdf14_forward_create_compositor(gx_device * dev, gx_device * * pcdev,
{
pdf14_device *pdev = (pdf14_device *)dev;
gx_device * tdev = pdev->target;
- gx_device * ndev;
int code;
*pcdev = dev;
@@ -5934,11 +5934,14 @@ pdf14_forward_create_compositor(gx_device * dev, gx_device * * pcdev,
return gx_update_pdf14_compositor(dev, pgs, pdf14pct, mem);
return 0;
}
- code = dev_proc(tdev, create_compositor)(tdev, &ndev, pct, pgs, mem, cdev);
- if (code < 0)
- return code;
- gx_device_set_target((gx_device_forward *)pdev, ndev);
- return 0;
+ code = dev_proc(tdev, create_compositor)(tdev, pcdev, pct, pgs, mem, cdev);
+ if (code == 1) {
+ /* We have created a new compositor that wrapped tdev. This means
+ * that our target should be updated to point to that. */
+ gx_device_set_target((gx_device_forward *)pdev, *pcdev);
+ code = 0; /* We have not created a new compositor that wrapped dev. */
+ }
+ return code;
}
/*
@@ -8449,7 +8452,7 @@ gs_pdf14_device_color_mon_set(gx_device *pdev, bool monitoring)
return code;
}
-int
+static int
gs_pdf14_device_push(gs_memory_t *mem, gs_gstate * pgs,
gx_device ** pdev, gx_device * target, const gs_pdf14trans_t * pdf14pct)
{
@@ -9205,7 +9208,6 @@ c_pdf14trans_create_default_compositor(const gs_composite_t * pct,
gs_memory_t * mem)
{
const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
- gx_device * p14dev = NULL;
int code = 0;
/*
@@ -9215,8 +9217,11 @@ c_pdf14trans_create_default_compositor(const gs_composite_t * pct,
*/
switch (pdf14pct->params.pdf14_op) {
case PDF14_PUSH_DEVICE:
- code = gs_pdf14_device_push(mem, pgs, &p14dev, tdev, pdf14pct);
- *pp14dev = p14dev;
+ code = gs_pdf14_device_push(mem, pgs, pp14dev, tdev, pdf14pct);
+ /* Change (non-error) code to 1 to indicate that we created
+ * a device. */
+ if (code >= 0)
+ code = 1;
break;
default:
/* No other compositor actions are allowed if this isn't a pdf14 compositor */
@@ -10280,7 +10285,8 @@ pdf14_clist_create_compositor(gx_device * dev, gx_device ** pcdev,
pctemp.type = &gs_composite_pdf14trans_no_clist_writer_type;
code = dev_proc(pdev->target, create_compositor)
(pdev->target, pcdev, (gs_composite_t *)&pctemp, pgs, mem, cdev);
- *pcdev = dev;
+ /* We should never have created a new device here. */
+ assert(code != 1);
return code;
}
case PDF14_POP_DEVICE:
@@ -10571,8 +10577,11 @@ put_accum_error:
}
return code; /* DON'T perform set_target */
}
- if (*pcdev != pdev->target)
+ if (code == 1) {
+ /* We just wrapped pdev->target, so we need to update that.*/
gx_device_set_target((gx_device_forward *)pdev, *pcdev);
+ code = 0; /* We did not wrap dev. */
+ }
*pcdev = dev;
return code;
}
@@ -10604,10 +10613,12 @@ pdf14_clist_forward_create_compositor(gx_device * dev, gx_device * * pcdev,
return 0;
}
code = dev_proc(tdev, create_compositor)(tdev, &ndev, pct, pgs, mem, cdev);
- if (code < 0)
- return code;
- gx_device_set_target((gx_device_forward *)pdev, ndev);
- return 0;
+ if (code == 1) {
+ /* We just wrapped tdev, so update our target. */
+ gx_device_set_target((gx_device_forward *)pdev, ndev);
+ code = 0; /* We did not wrap dev. */
+ }
+ return code;
}
/*
@@ -10670,7 +10681,7 @@ pdf14_clist_update_params(pdf14_clist_device * pdev, const gs_gstate * pgs,
}
params.changed = changed;
/* Avoid recursion when we have a PDF14_SET_BLEND_PARAMS forced and apply
- now to the target. Otherwise we send of te compositor action
+ now to the target. Otherwise we send the compositor action
to the pdf14 device at this time. This is due to the fact that we
need to often perform this operation when we are already starting to
do a compositor action */
@@ -11364,6 +11375,8 @@ gs_pdf14_clist_device_push(gs_memory_t *mem, gs_gstate *pgs, gx_device **pcdev,
gx_device_clist_writer * const cdev = &((gx_device_clist *)dev)->writer;
code = pdf14_create_clist_device(mem, pgs, pcdev, dev, pdf14pct);
+ if (code < 0)
+ return code;
/*
* Set the color_info of the clist device to match the compositing
* device. We will restore it when the compositor is popped.
@@ -11425,7 +11438,12 @@ c_pdf14trans_clist_write_update(const gs_composite_t * pcte, gx_device * dev,
/* We only handle the push/pop operations */
switch (pdf14pct->params.pdf14_op) {
case PDF14_PUSH_DEVICE:
- return gs_pdf14_clist_device_push(mem, pgs, pcdev, dev, pdf14pct);
+ code = gs_pdf14_clist_device_push(mem, pgs, pcdev, dev, pdf14pct);
+ /* Change (non-error) code to 1 to indicate that we created
+ * a device. */
+ if (code >= 0)
+ code = 1;
+ return code;
case PDF14_POP_DEVICE:
# if 0 /* Disabled because pdf14_clist_create_compositor does so. */
diff --git a/base/gdevsclass.c b/base/gdevsclass.c
index 2984e3451..b9cc089ac 100644
--- a/base/gdevsclass.c
+++ b/base/gdevsclass.c
@@ -488,35 +488,37 @@ int default_subclass_create_compositor(gx_device *dev, gx_device **pcdev, const
if (code < 0)
return code;
- if (*pcdev != 0L && *pcdev != dev->child){
- /* If the child created a new compositor, which it wants to be the new 'device' in the
- * graphics state, it sets it in the returned pcdev variable. When we return from this
- * method, if pcdev is not the same as the device in the graphics state then the interpreter
- * sets pcdev as the new device in the graphics state. But because we passed in the child device
- * to the child method, if it did create a compositor it will be a forwarding device, and it will
- * be forwarding to our child, we need it to point to us instead. So if pcdev is not the same as the
- * child device, we fixup the target in the child device to point to us.
+ /* *pcdev is always returned containing a device capable of doing
+ * compositing. This may mean it is a new device. If this wants
+ * to be the new 'device' in the graphics state, then code will
+ * return as 1. */
+ if (code == 1) {
+ /* So, we want the new compositor device to become the device
+ * in the graphics state. That device needs to point to us
+ * (the subclassing device) as its child, and our child in
+ * turn will remain as before. Currently the compositor
+ * device has our child as its child. We need to change
+ * this.
*/
gx_device_forward *fdev = (gx_device_forward *)*pcdev;
- if (fdev->target == dev->child) {
- if (gs_is_pdf14trans_compositor(pcte) != 0 && strncmp(fdev->dname, "pdf14clist", 10) == 0) {
- pdf14_clist_device *p14dev;
+ if (gs_is_pdf14trans_compositor(pcte) != 0 && strncmp(fdev->dname, "pdf14clist", 10) == 0) {
+ pdf14_clist_device *p14dev;
- p14dev = (pdf14_clist_device *)*pcdev;
+ p14dev = (pdf14_clist_device *)*pcdev;
- dev->color_info = dev->child->color_info;
+ dev->color_info = dev->child->color_info;
- psubclass_data->saved_compositor_method = p14dev->procs.create_compositor;
- psubclass_data->forwarding_dev = fdev;
- p14dev->procs.create_compositor = gx_subclass_create_compositor;
- }
-
- fdev->target = dev;
- rc_decrement_only(dev->child, "first-last page compositor code");
- rc_increment(dev);
+ psubclass_data->saved_compositor_method = p14dev->procs.create_compositor;
+ psubclass_data->forwarding_dev = fdev;
+ p14dev->procs.create_compositor = gx_subclass_create_compositor;
}
- return_error(gs_error_handled);
+
+ fdev->target = dev;
+ rc_decrement_only(dev->child, "subclass compositor code");
+ rc_increment(dev);
+ /* Return 1 so that *pcdev becomes the current device. */
+ return 1;
}
else {
/* See the 2 comments above. Now, if the child did not create a new compositor (eg its a clist)
diff --git a/base/gsovrc.c b/base/gsovrc.c
index 38ad867c0..3ed880223 100644
--- a/base/gsovrc.c
+++ b/base/gsovrc.c
@@ -1473,6 +1473,7 @@ c_overprint_create_default_compositor(
const gs_overprint_t * ovrpct = (const gs_overprint_t *)pct;
overprint_device_t * opdev = 0;
gs_overprint_params_t params;
+ int code;
/* see if there is anything to do */
if ( !ovrpct->params.retain_any_comps) {
@@ -1525,5 +1526,8 @@ c_overprint_create_default_compositor(
opdev->retain_none_stroke = true;
/* set up the overprint parameters */
- return update_overprint_params(opdev, &params);
+ code = update_overprint_params(opdev, &params);
+ if (code < 0)
+ return code;
+ return 1;
}
diff --git a/base/gsstate.c b/base/gsstate.c
index 102df7ca6..1dc076b15 100644
--- a/base/gsstate.c
+++ b/base/gsstate.c
@@ -590,7 +590,7 @@ gs_gstate_update_overprint(gs_gstate * pgs, const gs_overprint_params_t * pparam
pgs->memory,
NULL);
if (code >= 0 || code == gs_error_handled){
- if (ovptdev != dev) {
+ if (code == 1) {
gx_set_device_only(pgs, ovptdev);
/* Get rid of extra reference */
rc_decrement(ovptdev, "gs_gstate_update_overprint(ovptdev)");
diff --git a/base/gstrans.c b/base/gstrans.c
index 08c962eb7..b5cb84d31 100644
--- a/base/gstrans.c
+++ b/base/gstrans.c
@@ -145,9 +145,10 @@ gs_gstate_update_pdf14trans2(gs_gstate * pgs, gs_pdf14trans_params_t * pparams,
* If we created a new PDF 1.4 compositor device then we need to install it
* into the graphics state.
*/
- if (pdf14dev != dev) {
+ if (code == 1) {
gx_set_device_only(pgs, pdf14dev);
gx_device_retain(pdf14dev, retain_on_create);
+ code = 0;
}
/* If we had a color space change and we are in overprint, then we need to
diff --git a/base/gxclimag.c b/base/gxclimag.c
index f110771fd..8fc779d4a 100644
--- a/base/gxclimag.c
+++ b/base/gxclimag.c
@@ -1301,6 +1301,7 @@ clist_create_compositor(gx_device * dev,
int first_band = 0, no_of_bands = cdev->nbands;
int code = pcte->type->procs.write(pcte, 0, &size, cdev);
int temp_cropping_min, temp_cropping_max;
+ int newdev;
CMD_CHECK_LAST_OP_BLOCK_DEFINED(cdev);
@@ -1314,6 +1315,7 @@ clist_create_compositor(gx_device * dev,
pcdev, pgs, mem);
if (code < 0)
return code;
+ newdev = code == 1;
CMD_CHECK_LAST_OP_BLOCK_DEFINED(cdev);
@@ -1379,6 +1381,9 @@ clist_create_compositor(gx_device * dev,
/* serialize the remainder of the compositor */
if ((code = pcte->type->procs.write(pcte, dp + 3, &size_dummy, cdev)) < 0)
((gx_device_clist_writer *)dev)->cnext = dp;
+
+ if (code >= 0 && newdev)
+ code = 1; /* Return 1 to indicate we created a new device. */
return code;
}
if (cropping_op == PUSHCROP) {
@@ -1425,6 +1430,9 @@ clist_create_compositor(gx_device * dev,
return code;
}
+ if (newdev)
+ code = 1; /* Return 1 to indicate we created a new device. */
+
return code;
}
diff --git a/base/gxclrast.c b/base/gxclrast.c
index 9383d1fed..58718f5b2 100644
--- a/base/gxclrast.c
+++ b/base/gxclrast.c
@@ -3096,18 +3096,11 @@ static int apply_create_compositor(gx_device_clist_reader *cdev, gs_gstate *pgs,
* change the target device.
*/
code = dev_proc(tdev, create_compositor)(tdev, &tdev, pcomp, pgs, mem, (gx_device*) cdev);
- if (code >= 0 && tdev != *ptarget) {
- /* 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 == 1) {
+ /* A new compositor was created that wrapped tdev. This should
+ * be our new target. */
+ *ptarget = tdev;
+ code = 0;
}
if (code < 0)
return code;
diff --git a/doc/Drivers.htm b/doc/Drivers.htm
index 00fcd6bef..93fad7b6c 100644
--- a/doc/Drivers.htm
+++ b/doc/Drivers.htm
@@ -1830,20 +1830,36 @@ Devices will normally implement this in one of the following standard ways:</dd>
<ul>
<li>Devices that don't do any imaging and don't forward any imaging
operations (for example, the null device, the hit detection device, and the
-clipping list accumulation device) simply return themselves, which
-effectively ignores the compositing function.</li>
+clipping list accumulation device) simply set *pcdev to themselves, and
+return 0, which effectively ignores the compositing function.</li>
<li>"Leaf" devices that do imaging and have no special optimizations for
compositing (for example, some memory devices) ask the
-<code>gs_composite_t</code> to create a default compositor. </li>
+<code>gs_composite_t</code> to create a default compositor device that
+'wraps' the current device. They put this in <code>*pcdev</code> and
+return 1.</li>
<li>Leaf devices that can implement some kinds of compositing operation
efficiently (for example, monobit memory devices and RasterOp) inspect the
type and values of <code>*pcte</code> to determine whether it specifies
such an operation: if so, they create a specialized compositor, and if not,
-they ask the <code>gs_composite_t</code> to create a default compositor. </li>
+they ask the <code>gs_composite_t</code> to create a default compositor. They
+place this in <code>*pcdev</code> and return 1.</li>
</ul>
+<p>In short, on every non-error return, <code>*pcdev</code> will be set
+either to the leaf device (in the case where no special compositing is
+required), or to the device that does the compositing. If the return
+code is 1, then <code>*pcdev</code> is a new device that was created
+to wrap <code>dev</code> to perform the compositing for it. Callers
+may need to spot this case so as to update which device future
+operations are sent to.</p>
+
+<p>For forwarding devices, for example, if the call returns 1, then
+they should update their target device to be the new device. For the
+graphics library, if the call returns 1, then it should update the
+current device to be the new one.</p>
+
<p>
Other kinds of forwarding devices, which don't fall into any of these
categories, require special treatment. In principle, what they do is ask