summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Resource/Init/gs_setpd.ps20
-rw-r--r--psi/zdevice2.c55
2 files changed, 56 insertions, 19 deletions
diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps
index b75c4312a..8fa7c51df 100644
--- a/Resource/Init/gs_setpd.ps
+++ b/Resource/Init/gs_setpd.ps
@@ -96,7 +96,7 @@ level2dict begin
96 % we must (carefully) reinstall the old parameters in 96 % we must (carefully) reinstall the old parameters in
97 % the same device. 97 % the same device.
98 .currentpagedevice pop //null currentdevice //null 98 .currentpagedevice pop //null currentdevice //null
99 {.trysetparams} .internalstopped 99 { .trysetparams } .internalstopped
100 { 100 {
101 //null 101 //null
102 } if 102 } if
@@ -104,26 +104,32 @@ level2dict begin
104 { pop pop } 104 { pop pop }
105 { 105 {
106 SETPDDEBUG { (Error in .trysetparams!) = pstack flush } if 106 SETPDDEBUG { (Error in .trysetparams!) = pstack flush } if
107 cleartomark pop pop pop 107 {cleartomark pop pop pop} .internalstopped pop
108 % if resetting the entire device state failed, at least put back the 108 % if resetting the entire device state failed, at least put back the
109 % security related key 109 % security related key
110 currentdevice //null //false mark /.LockSafetyParams .currentpagedevice pop 110 currentdevice //null //false mark /.LockSafetyParams
111 /.LockSafetyParams .knownget not {//false} if .putdeviceparamsonly 111 currentpagedevice /.LockSafetyParams .knownget not
112 {systemdict /SAFER .knownget not {//false} } if
113 .putdeviceparamsonly
112 /.installpagedevice cvx /rangecheck signalerror 114 /.installpagedevice cvx /rangecheck signalerror
113 } 115 }
114 ifelse pop pop 116 ifelse pop pop
115 % A careful reading of the Red Book reveals that an erasepage 117 % A careful reading of the Red Book reveals that an erasepage
116 % should occur, but *not* an initgraphics. 118 % should occur, but *not* an initgraphics.
117 erasepage .beginpage 119 erasepage .beginpage
118 } bind def 120 } bind executeonly def
119 121
120/.uninstallpagedevice 122/.uninstallpagedevice
121 { 2 .endpage { .currentnumcopies //false .outputpage } if 123 {
124 {2 .endpage { .currentnumcopies //false .outputpage } if} .internalstopped pop
122 nulldevice 125 nulldevice
123 } bind def 126 } bind def
124 127
125(%grestorepagedevice) cvn 128(%grestorepagedevice) cvn
126 { .uninstallpagedevice grestore .installpagedevice 129 {
130 .uninstallpagedevice
131 grestore
132 .installpagedevice
127 } bind def 133 } bind def
128 134
129(%grestoreallpagedevice) cvn 135(%grestoreallpagedevice) cvn
diff --git a/psi/zdevice2.c b/psi/zdevice2.c
index 0c7080d57..5447c8c84 100644
--- a/psi/zdevice2.c
+++ b/psi/zdevice2.c
@@ -251,8 +251,8 @@ z2currentgstate(i_ctx_t *i_ctx_p)
251/* ------ Wrappers for operators that reset the graphics state. ------ */ 251/* ------ Wrappers for operators that reset the graphics state. ------ */
252 252
253/* Check whether we need to call out to restore the page device. */ 253/* Check whether we need to call out to restore the page device. */
254static bool 254static int
255restore_page_device(const gs_gstate * pgs_old, const gs_gstate * pgs_new) 255restore_page_device(i_ctx_t *i_ctx_p, const gs_gstate * pgs_old, const gs_gstate * pgs_new)
256{ 256{
257 gx_device *dev_old = gs_currentdevice(pgs_old); 257 gx_device *dev_old = gs_currentdevice(pgs_old);
258 gx_device *dev_new; 258 gx_device *dev_new;
@@ -260,9 +260,10 @@ restore_page_device(const gs_gstate * pgs_old, const gs_gstate * pgs_new)
260 gx_device *dev_t2; 260 gx_device *dev_t2;
261 bool samepagedevice = obj_eq(dev_old->memory, &gs_int_gstate(pgs_old)->pagedevice, 261 bool samepagedevice = obj_eq(dev_old->memory, &gs_int_gstate(pgs_old)->pagedevice,
262 &gs_int_gstate(pgs_new)->pagedevice); 262 &gs_int_gstate(pgs_new)->pagedevice);
263 bool LockSafetyParams = dev_old->LockSafetyParams;
263 264
264 if ((dev_t1 = (*dev_proc(dev_old, get_page_device)) (dev_old)) == 0) 265 if ((dev_t1 = (*dev_proc(dev_old, get_page_device)) (dev_old)) == 0)
265 return false; 266 return 0;
266 /* If we are going to putdeviceparams in a callout, we need to */ 267 /* If we are going to putdeviceparams in a callout, we need to */
267 /* unlock temporarily. The device will be re-locked as needed */ 268 /* unlock temporarily. The device will be re-locked as needed */
268 /* by putdeviceparams from the pgs_old->pagedevice dict state. */ 269 /* by putdeviceparams from the pgs_old->pagedevice dict state. */
@@ -271,23 +272,44 @@ restore_page_device(const gs_gstate * pgs_old, const gs_gstate * pgs_new)
271 dev_new = gs_currentdevice(pgs_new); 272 dev_new = gs_currentdevice(pgs_new);
272 if (dev_old != dev_new) { 273 if (dev_old != dev_new) {
273 if ((dev_t2 = (*dev_proc(dev_new, get_page_device)) (dev_new)) == 0) 274 if ((dev_t2 = (*dev_proc(dev_new, get_page_device)) (dev_new)) == 0)
274 return false; 275 samepagedevice = true;
275 if (dev_t1 != dev_t2) 276 else if (dev_t1 != dev_t2)
276 return true; 277 samepagedevice = false;
278 }
279
280 if (LockSafetyParams && !samepagedevice) {
281 os_ptr op = osp;
282 const int max_ops = 512;
283
284 /* The %grestorepagedevice must complete: the biggest danger
285 is operand stack overflow. As we use get/putdeviceparams
286 that means pushing all the device params onto the stack,
287 pdfwrite having by far the largest number of parameters
288 at (currently) 212 key/value pairs - thus needing (currently)
289 424 entries on the op stack. Allowing for working stack
290 space, and safety margin.....
291 */
292 if (max_ops > op - osbot) {
293 if (max_ops >= ref_stack_count(&o_stack))
294 return_error(gs_error_stackoverflow);
295 }
277 } 296 }
278 /* 297 /*
279 * The current implementation of setpagedevice just sets new 298 * The current implementation of setpagedevice just sets new
280 * parameters in the same device object, so we have to check 299 * parameters in the same device object, so we have to check
281 * whether the page device dictionaries are the same. 300 * whether the page device dictionaries are the same.
282 */ 301 */
283 return !samepagedevice; 302 return samepagedevice ? 0 : 1;
284} 303}
285 304
286/* - grestore - */ 305/* - grestore - */
287static int 306static int
288z2grestore(i_ctx_t *i_ctx_p) 307z2grestore(i_ctx_t *i_ctx_p)
289{ 308{
290 if (!restore_page_device(igs, gs_gstate_saved(igs))) 309 int code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs));
310 if (code < 0) return code;
311
312 if (code == 0)
291 return gs_grestore(igs); 313 return gs_grestore(igs);
292 return push_callout(i_ctx_p, "%grestorepagedevice"); 314 return push_callout(i_ctx_p, "%grestorepagedevice");
293} 315}
@@ -297,7 +319,9 @@ static int
297z2grestoreall(i_ctx_t *i_ctx_p) 319z2grestoreall(i_ctx_t *i_ctx_p)
298{ 320{
299 for (;;) { 321 for (;;) {
300 if (!restore_page_device(igs, gs_gstate_saved(igs))) { 322 int code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs));
323 if (code < 0) return code;
324 if (code == 0) {
301 bool done = !gs_gstate_saved(gs_gstate_saved(igs)); 325 bool done = !gs_gstate_saved(gs_gstate_saved(igs));
302 326
303 gs_grestore(igs); 327 gs_grestore(igs);
@@ -328,11 +352,15 @@ z2restore(i_ctx_t *i_ctx_p)
328 if (code < 0) return code; 352 if (code < 0) return code;
329 353
330 while (gs_gstate_saved(gs_gstate_saved(igs))) { 354 while (gs_gstate_saved(gs_gstate_saved(igs))) {
331 if (restore_page_device(igs, gs_gstate_saved(igs))) 355 code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs));
356 if (code < 0) return code;
357 if (code > 0)
332 return push_callout(i_ctx_p, "%restore1pagedevice"); 358 return push_callout(i_ctx_p, "%restore1pagedevice");
333 gs_grestore(igs); 359 gs_grestore(igs);
334 } 360 }
335 if (restore_page_device(igs, gs_gstate_saved(igs))) 361 code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs));
362 if (code < 0) return code;
363 if (code > 0)
336 return push_callout(i_ctx_p, "%restorepagedevice"); 364 return push_callout(i_ctx_p, "%restorepagedevice");
337 365
338 code = dorestore(i_ctx_p, asave); 366 code = dorestore(i_ctx_p, asave);
@@ -355,9 +383,12 @@ static int
355z2setgstate(i_ctx_t *i_ctx_p) 383z2setgstate(i_ctx_t *i_ctx_p)
356{ 384{
357 os_ptr op = osp; 385 os_ptr op = osp;
386 int code;
358 387
359 check_stype(*op, st_igstate_obj); 388 check_stype(*op, st_igstate_obj);
360 if (!restore_page_device(igs, igstate_ptr(op))) 389 code = restore_page_device(i_ctx_p, igs, igstate_ptr(op));
390 if (code < 0) return code;
391 if (code == 0)
361 return zsetgstate(i_ctx_p); 392 return zsetgstate(i_ctx_p);
362 return push_callout(i_ctx_p, "%setgstatepagedevice"); 393 return push_callout(i_ctx_p, "%setgstatepagedevice");
363} 394}