summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2018-09-17 14:06:12 +0100
committerChris Liddell <chris.liddell@artifex.com>2018-09-18 09:26:36 +0100
commit7c3e7eee829cc3d2582e4aa7ae1fd495ca72cef1 (patch)
treec7c1843b13f742a7599fe1e708749b67fe8874a3
parent8bc783cb586231da2916f423bf5793e194092679 (diff)
downloadghostpdl-7c3e7eee829cc3d2582e4aa7ae1fd495ca72cef1.tar.gz
Implement .currentoutputdevice operator
The currentdevice operator returns the device currently installed in the graphics state. This can be the output/page device, but also could be a forwarding device (bbox device), compositor (pdf14) or subclass device (erasepage optimisation, First/Last page etc). In certain circumstances (for example during a setpagedevice) we want to be sure we're retrieving the *actual* output/page device. The new .currentoutputdevice operator uses the spec_op device method to traverse any chain of devices and retrieve the final device in the chain, which should always be the output/page device.
-rw-r--r--Resource/Init/gs_init.ps2
-rw-r--r--Resource/Init/gs_setpd.ps8
-rw-r--r--base/gdevdflt.c5
-rw-r--r--base/gxdevsop.h4
-rw-r--r--psi/zdevice.c30
5 files changed, 47 insertions, 2 deletions
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 56b518a78..d5b5584dd 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -2211,7 +2211,7 @@ SAFER { .setsafeglobal } if
/.shfill /.argindex /.bytestring /.namestring /.stringbreak /.stringmatch /.globalvmarray /.globalvmdict /.globalvmpackedarray /.globalvmstring
/.localvmarray /.localvmdict /.localvmpackedarray /.localvmstring /.systemvmarray /.systemvmdict /.systemvmpackedarray /.systemvmstring /.systemvmfile /.systemvmlibfile
/.systemvmSFD /.settrapparams /.currentsystemparams /.currentuserparams /.getsystemparam /.getuserparam /.setsystemparams /.setuserparams
- /.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath
+ /.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath /.currentoutputdevice
% Used by a free user in the Library of Congress. Apparently this is used to
% draw a partial page, which is then filled in by the results of a barcode
diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps
index 8fa7c51df..aa79b3f0b 100644
--- a/Resource/Init/gs_setpd.ps
+++ b/Resource/Init/gs_setpd.ps
@@ -877,7 +877,13 @@ SETPDDEBUG { (Selecting.) = pstack flush } if
% Stack: mark <orig> <request> <merged> <failed>
SETPDDEBUG { (Constructing.) = pstack flush } if
- currentdevice .devicename 2 index /OutputDevice get eq
+ % Non-obvious: we need to check the name of the output device, to tell
+ % whether we're going to have to replace the entire device chain (which
+ % may be only one device, or may be multiple devices.
+ % If we're not replacing the entire change, we have to use the device in
+ % the graphics state, so the configuration of the entire device chain is
+ % correctly set.
+ .currentoutputdevice .devicename 2 index /OutputDevice get eq
{ currentdevice }
{ 1 index /OutputDevice get finddevice }
ifelse
diff --git a/base/gdevdflt.c b/base/gdevdflt.c
index 3cb9fbd0a..b5bd82b0a 100644
--- a/base/gdevdflt.c
+++ b/base/gdevdflt.c
@@ -1044,6 +1044,11 @@ gx_default_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size)
dev_param_req_t *request = (dev_param_req_t *)data;
return gx_default_get_param(pdev, request->Param, request->list);
}
+ case gxdso_current_output_device:
+ {
+ *(gx_device **)data = pdev;
+ return 0;
+ }
}
return_error(gs_error_undefined);
}
diff --git a/base/gxdevsop.h b/base/gxdevsop.h
index cd3b63296..27e3e842f 100644
--- a/base/gxdevsop.h
+++ b/base/gxdevsop.h
@@ -327,6 +327,10 @@ enum {
gxdso_JPEG_passthrough_data,
gxdso_JPEG_passthrough_end,
gxdso_supports_iccpostrender,
+ /* Retrieve the last device in a device chain
+ (either forwarding or subclass devices).
+ */
+ gxdso_current_output_device,
/* Add new gxdso_ keys above this. */
gxdso_pattern__LAST
};
diff --git a/psi/zdevice.c b/psi/zdevice.c
index 8d48b7426..e5f4f1b4b 100644
--- a/psi/zdevice.c
+++ b/psi/zdevice.c
@@ -57,6 +57,7 @@ zcopydevice2(i_ctx_t *i_ctx_p)
}
/* - currentdevice <device> */
+/* Returns the current device in the graphics state */
int
zcurrentdevice(i_ctx_t *i_ctx_p)
{
@@ -71,6 +72,34 @@ zcurrentdevice(i_ctx_t *i_ctx_p)
return 0;
}
+/* - .currentoutputdevice <device> */
+/* Returns the *output* device - which will often
+ be the same as above, but not always: if a compositor
+ or other forwarding device, or subclassing device is
+ in force, that will be referenced by the graphics state
+ rather than the output device.
+ This is equivalent of currentdevice device, but returns
+ the *device* object, rather than the dictionary describing
+ the device and device state.
+ */
+static int
+zcurrentoutputdevice(i_ctx_t *i_ctx_p)
+{
+ os_ptr op = osp;
+ gx_device *odev = NULL, *dev = gs_currentdevice(igs);
+ gs_ref_memory_t *mem = (gs_ref_memory_t *) dev->memory;
+ int code = dev_proc(dev, dev_spec_op)(dev,
+ gxdso_current_output_device, (void *)&odev, 0);
+ if (code < 0)
+ return code;
+
+ push(1);
+ make_tav(op, t_device,
+ (mem == 0 ? avm_foreign : imemory_space(mem)) | a_all,
+ pdevice, odev);
+ return 0;
+}
+
/* <device> .devicename <string> */
static int
zdevicename(i_ctx_t *i_ctx_p)
@@ -614,6 +643,7 @@ const op_def zdevice_op_defs[] =
{
{"1.copydevice2", zcopydevice2},
{"0currentdevice", zcurrentdevice},
+ {"0.currentoutputdevice", zcurrentoutputdevice},
{"1.devicename", zdevicename},
{"0.doneshowpage", zdoneshowpage},
{"0flushpage", zflushpage},