diff options
author | Chris Liddell <chris.liddell@artifex.com> | 2018-09-17 14:06:12 +0100 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2018-09-18 09:26:36 +0100 |
commit | 7c3e7eee829cc3d2582e4aa7ae1fd495ca72cef1 (patch) | |
tree | c7c1843b13f742a7599fe1e708749b67fe8874a3 | |
parent | 8bc783cb586231da2916f423bf5793e194092679 (diff) | |
download | ghostpdl-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.ps | 2 | ||||
-rw-r--r-- | Resource/Init/gs_setpd.ps | 8 | ||||
-rw-r--r-- | base/gdevdflt.c | 5 | ||||
-rw-r--r-- | base/gxdevsop.h | 4 | ||||
-rw-r--r-- | psi/zdevice.c | 30 |
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}, |