summaryrefslogtreecommitdiff
path: root/base/gxgstate.h
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2021-08-17 12:39:25 +0100
committerRobin Watts <Robin.Watts@artifex.com>2021-09-06 10:44:43 +0100
commitf2bb042229e8a27a2c78f7f4ec883e3d313192e5 (patch)
tree8fa9d0f7fed35543365eb4be40f926793f934ff0 /base/gxgstate.h
parent28bb0fa34b35181d5905d4f6d32fdcded2df5b04 (diff)
downloadghostpdl-f2bb042229e8a27a2c78f7f4ec883e3d313192e5.tar.gz
Nup device: Attempt to fix operation with Postscript/EPS.
Currently, the Nup device doesn't work properly with Postscript due to the handling of the 'default' matrix (tied up with the Install/BeginPage/EndPage aspects of Postscript device handling). Put simply, once the 'initial' matrix is read, it becomes the 'default' matrix in the graphics state. It sticks there until explicitly overwritten. This means that any changes we might make to the 'initial' matrix (as returned by get_initial_matrix) are largely ignored. PDF and other languages sidestep this problem by invalidating the default and rereading it on each page. PDF does this by reinstalling the device to allow for media size changes. Doing this is tricky with Postscript, as frequently this 'invalidation' of the default is then undone by restores done to the graphics state. Furthermore, we don't actually want to completely invalidate the default each time, as the Install/BeginPage/EndPage procedures give a way for Postscript programs to modify the default, which will then be confused when it is reset. Our solution to this is to store the 'initial' value that was in effect when the 'default' was set with it in the graphics state. When we start new pages, we can then call a 'gs_updatematrices' function to check for changes to the initial value, and to update the default and ctm as appropriate. If the initial matrix has changed, we do nothing. Thus all existing files run without Nup will be utterly unchanged. Otherwise, we calculate the 'modification' that was required to make the default from the old initial value, and reapply that modification to the new initial value to make a new default. Similarly, we update ctm. The only problem is then to get this called at the start of every page. For postscript, we insert calls to this into the BeginPage EndPage handling (in a way that ensures it will always get called even if those are overridden). For EPS, BeginPage/EndPage are not called, so we need to insert a call at the start of .runEPS. The only problem with this is that updating the matrices does not change the clipbox. This is problematic to do. Accordingly, we just reinitialise the clipbox. For when this is called from BeginPage/EndPage this is clearly harmless. When this is called from runEPS, it's less harmless, as it potentially breaks a corner case where we do: gs -sNupControl=2x1 in1.ps in2.eps where in1.ps sets a clipping box to be used on in2.eps. Again this only affects the case where NupControl is in uses, so we will live with this.
Diffstat (limited to 'base/gxgstate.h')
-rw-r--r--base/gxgstate.h3
1 files changed, 3 insertions, 0 deletions
diff --git a/base/gxgstate.h b/base/gxgstate.h
index 593412f8f..b1ce6a088 100644
--- a/base/gxgstate.h
+++ b/base/gxgstate.h
@@ -285,6 +285,9 @@ struct gs_gstate_s {
gs_matrix ctm_default;
bool ctm_default_set; /* if true, use ctm_default; */
/* if false, ask device */
+ gs_matrix ctm_initial; /* The value of the device initial matrix at the time the default was set. */
+ bool ctm_initial_set; /* if true, modification set. If not, assume identity. */
+
/* Paths: */
gx_path *path;