Sophie

Sophie

distrib > Mageia > 6 > armv7hl > media > core-updates-src > by-pkgid > bc219369320b6b5781eed48254462cef > files > 16

ghostscript-9.25-1.2.mga6.src.rpm

From 7c3e7eee829cc3d2582e4aa7ae1fd495ca72cef1 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Mon, 17 Sep 2018 14:06:12 +0100
Subject: [PATCH] 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.
---
 Resource/Init/gs_init.ps  |  2 +-
 Resource/Init/gs_setpd.ps |  8 +++++++-
 base/gdevdflt.c           |  5 +++++
 base/gxdevsop.h           |  4 ++++
 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 56b518a..d5b5584 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 8fa7c51..aa79b3f 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 3cb9fbd..b5bd82b 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 cd3b632..27e3e84 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 8d48b74..e5f4f1b 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},
-- 
2.9.1