You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

741 lines
24 KiB

1 month ago
  1. % Copyright (C) 2002-2023 Artifex, Inc. All rights reserved.
  2. %
  3. % This software is provided AS-IS with no warranty, either express or
  4. % implied.
  5. %
  6. % This software is distributed under license and may not be copied,
  7. % modified or distributed except as expressly authorized under the terms
  8. % of the license contained in the file LICENSE in this distribution.
  9. %
  10. % For more information about licensing, please refer to
  11. % http://www.ghostscript.com/licensing/. For information on
  12. % commercial licensing, go to http://www.artifex.com/licensing/ or
  13. % contact Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  14. % CA 94129, USA.
  15. % image, colorimage, and imagemask implementation
  16. %
  17. % The design of the overprint facility in Ghostscript requires that color
  18. % specifications include the color space from which they were expressed,
  19. % even after conversion to the device color model. Directly including this
  20. % information in color specifications is usually not efficient, and is
  21. % difficult to integrate into the existing code structure. The alternative
  22. % approach taken is to extend a state mechanism through the device
  23. % interface, and make the current color space, or more specifically,
  24. % certain information about the current color space, a property of this
  25. % state.
  26. %
  27. % For such a mechanism to work, it is necessary to identify all changes
  28. % to the current color space. This is accomplished in the graphic library
  29. % by funneling all changes to the current color space through the
  30. % gs_setcolorspace procedure. At the PostScript interpreter level, this
  31. % result is achieved by forcing color space changes through the
  32. % setcolorspace operator.
  33. %
  34. % Aside from explicit use of setcolorspace, PostScript provides a few
  35. % implicit methods of changing the current color space. The setgray,
  36. % setrgbcolor, and setcmykcolor operators implicitly set the color space
  37. % while explicitly setting the current color. Similarly, the colorimage
  38. % operator and the traditional form of the image operator (5 operands)
  39. % both temporarily modify the current color space while an image is
  40. % being processed. The current file is concerned with the implementation
  41. % of these two operators. In addition, the traditional form of the
  42. % imagemask operator (5 operands), while it does not affect the current
  43. % color space, is closely related to the image operator and thus is
  44. % implemented in this file as well.
  45. %
  46. % In this implementation, all sampled objects are passed through one of
  47. % the internal operators .image1, .imagemask1, .image2,
  48. % .image3, or .image4, each of which handles a specific ImageType value.
  49. %
  50. % The procedures in this file are responsible for constructing
  51. % image dictionaries from a set of stack entries. This is, in principle,
  52. % a trivial exercise. In practice it appears to be far more complex,
  53. % primarily due to the need to reconstruct the original state in the
  54. % event of an error. This is a particular problem for operators such as
  55. % image, which include data source objects that may, directly or
  56. % indirectly, be procedures. When these procedures are executed, the
  57. % image operator's operands must have been cleared from the operand
  58. % stack. Hence, the operand stack cannot be used to store state
  59. % information. Similarly, the dictionary stack also cannot be used to
  60. % store state information, as the data source procedures may depend on
  61. % a particular dictionary being on the top of this stack.
  62. %
  63. % Adobe's PostScript implementations determine the extent to which the
  64. % interpreter state is restored in the event of an error by the point at
  65. % which the error is detected. Errors in the image/colorimage/imagemask
  66. % operators that are detected before the data source procedures are
  67. % executed restore the state in effect before the image was processed.
  68. % Those that are detected as part of running the data source procedures
  69. % only attempt to restore the state to that in effect at the start of
  70. % the operator that failed (or at the conclusion of the data source
  71. % procedure, if this procedure failed to push a string).
  72. %
  73. % The implementation given here follows the Adobe convention. The
  74. % mechanism used is as follows:
  75. %
  76. % 1. Check that the stack has a sufficient number of operands, and
  77. % that enough of them have the proper type to allow construction
  78. % of the image dictionary. Any errors at this point are handled
  79. % in the conventional manner.
  80. %
  81. % 2. Build the image dictionary, in the process clearing the image/
  82. % colorimage/imagemask operands from the stack. No errors can
  83. % occur during this process.
  84. %
  85. % (Special precautions could be taken during this step to handle
  86. % a limitcheck or VMError during the building of the image
  87. % dictionary, but this essentially never occurs in practice and, if
  88. % it did, is very unlikely to leave a useable state. Hence, we don't
  89. % bother with this possibility.)
  90. %
  91. % 3. The .image operator is executed in a stopped context. If it
  92. % returns abnormally, a check is made to see if the uppermost
  93. % operand on the stack is a color image dictionary. If so, the
  94. % original stack is created anew using this dictionary. (Because
  95. % the image operand works via colorimage, some additional special
  96. % handling is required in this case.)
  97. %
  98. %
  99. % Create a dictionary of operators for specific image and image mask types.
  100. % Each of these will always handle ImageType 1. Additional types are added
  101. % as they are supported in specific interpreter levels or versions.
  102. %
  103. % These dictionaries are in systemdict for historical reasons.
  104. %
  105. .currentglobal //true .setglobal
  106. systemdict begin
  107. /.imagetypes
  108. 5 dict
  109. dup 1 /.image1 load put
  110. def
  111. /.imagemasktypes
  112. 5 dict
  113. dup 1 /.imagemask1 load put
  114. def
  115. %
  116. % Some useful local data structures:
  117. %
  118. % img_csary maps the number of components in an image to the implied
  119. % color space.
  120. %
  121. % img_decary is a prototype Decode array; subintervals of this array
  122. % may be used for fewer than 4 color components.
  123. %
  124. % img_params_ary is a list of the parameters to be built in the image
  125. % dictionary for a colorimage invocation. ImageType is given a
  126. % fixed value; the other parameters are in stack order (IMG_NComps
  127. % is the number of components).
  128. %
  129. % img_mask_params_ary is the equivalent of img_params_ary for imagemask
  130. % invocations. Polarity is a proxy for Decode, and is replaced
  131. % by the Decode key in the image dictionary.
  132. %
  133. % img_mask_check_ary is the set of parameters that must be present in
  134. % an image dictionary generated by an imagemask invocation. This
  135. % differs from img_mask_params_ary in that Decode replaces Polarity.
  136. %
  137. /img_csary [ //null /DeviceGray //null /DeviceRGB /DeviceCMYK ] def
  138. /img_decary [ 0 1 0 1 0 1 0 1 ] def
  139. /img_params_ary
  140. [
  141. /ImageType /IMG_NComps /MultipleDataSources /DataSource
  142. /ImageMatrix /BitsPerComponent /Height /Width /Decode
  143. ]
  144. def
  145. /img_check_ary //img_params_ary def
  146. /img_unbuild_ary
  147. //img_params_ary 1 1 index length 2 sub getinterval
  148. def
  149. /img_mask_params_ary
  150. [ /ImageType /DataSource /ImageMatrix /Polarity /Height /Width ]
  151. def
  152. /img_mask_check_ary
  153. [
  154. /ImageType /BitsPerComponent
  155. /DataSource /ImageMatrix /Decode /Height /Width
  156. ]
  157. def
  158. /img_mask_unbuild_ary
  159. //img_mask_check_ary 2 1 index length 2 sub getinterval
  160. def
  161. %
  162. % <?any?> <array> img_check_keys <?any?> <bool>
  163. %
  164. % Verify that:
  165. % that there are at least two entries on the stack, and
  166. % the second (lower) entry is a dictionary, and
  167. % that dictionary contains all of the keys in the array
  168. %
  169. % If any one of these conditions does not hold, pop the array and push
  170. % false; otherwise pop the array and push true. This utility is used by
  171. % the colorimage and imagematrix procedures to determine if .image left
  172. % the image dictionary on the stack after an abnormal return.
  173. %
  174. /img_check_keys
  175. {
  176. count 2 ge
  177. {
  178. 1 index type /dicttype eq
  179. {
  180. //true exch
  181. {
  182. 2 index exch known and
  183. dup not
  184. { exit }
  185. if
  186. }
  187. forall
  188. }
  189. { pop //false }
  190. ifelse
  191. }
  192. { pop //false }
  193. ifelse
  194. }
  195. .forcebind def
  196. %
  197. % Procedures to convert a set of stack entries to a dictionary. There is
  198. % a procedure associated with each key, though most keys use the same
  199. % procedure. The dictionary to be built is at the top of the dictionary
  200. % stack. Stack handling for the procedures is:
  201. %
  202. % <?val0?> ... <?val(n - 1)?> <key> proc -
  203. %
  204. % Parameters are handle in inverse-stack order, so inter-parameter
  205. % dependencies that on the stack can generally be used here.
  206. %
  207. /img_params_dict
  208. mark
  209. /ImageType { 1 def } .bind
  210. /IMG_NComps { exch def } .bind % number of components
  211. /MultipleDataSources 1 index
  212. /Width 1 index
  213. /Height 1 index
  214. /ImageMatrix 1 index
  215. /BitsPerComponent 1 index
  216. /DataSource 1 index
  217. % Polarity is a proxy for Decode; it never appears in a dictionary
  218. /Polarity
  219. {
  220. pop
  221. { { 1 0 } }
  222. { { 0 1 } }
  223. ifelse
  224. /Decode exch cvlit def
  225. }
  226. .bind
  227. % the definition of Decode is based on the number of components
  228. /Decode { //img_decary 0 IMG_NComps 2 mul getinterval def } .bind
  229. .dicttomark
  230. def
  231. %
  232. % <oper_0> ... <oper_n> <array> img_build_dict <dict>
  233. %
  234. % Build a dictionary. This will always be done in local VM. The array is
  235. % a list of the keys to be associated with operands on the stack, in
  236. % inverse stack order (topmost element first). The caller should verify
  237. % that the dictionary can be built successfully (except for a possible
  238. % VMerror) before calling this routine.
  239. %
  240. /img_build_dict
  241. {
  242. % build the dictionary in local VM; all for 2 extra entries
  243. .currentglobal //false .setglobal
  244. 1 index length 2 add dict
  245. exch .setglobal
  246. begin
  247. % process all keys in the array
  248. { //img_params_dict 1 index get exec }
  249. forall
  250. % if BitsPerComponent is not yet defined, define it to be 1
  251. currentdict /BitsPerComponent known not
  252. { /BitsPerComponent 1 def }
  253. if
  254. currentdict end
  255. }
  256. .forcebind def
  257. %
  258. % <dict> <array> img_unbuild_dict <oper_0> ... <oper_n>
  259. %
  260. % "Unbuild" a dictionary: spread the contents the dictionary back onto the
  261. % stack, in the inverse of the order indicated in the array (inverse is
  262. % used as this order is more convenient for img_build_dict, which is
  263. % expected to be invoked far more frequently).
  264. %
  265. /img_unbuild_dict
  266. {
  267. exch begin
  268. dup length 1 sub -1 0
  269. { 1 index exch get load exch }
  270. for
  271. pop
  272. end
  273. }
  274. .forcebind def
  275. %
  276. % Check the image types that can be used as data sources
  277. % <any> foo <bool>
  278. %
  279. /good_image_types mark
  280. /filetype { pop //true } .bind
  281. /stringtype 1 index
  282. /arraytype //xcheck
  283. /packedarraytype //xcheck
  284. .dicttomark readonly def
  285. %
  286. % <width> <height> <bits/component> <matrix> <dsrc0> ...
  287. % <multi> <ncomp>
  288. % img_build_image_dict
  289. % <dict>
  290. %
  291. % Build the dictionary corresponding to a colorimage operand stack. This
  292. % routine will check just enough of the stack to verify that the
  293. % dictionary can be built, and will generate the appropriate error if this
  294. % is not the case.
  295. %
  296. % At the first level, errors in this procedure are reported as colorimage
  297. % errors. The error actually reported will usually be determined by the
  298. % pseudo-operator which invokes this routine.
  299. %
  300. /img_build_image_dict
  301. {
  302. % Verify that at least 7 operands are available, and that the top two
  303. % operands have the expected types
  304. count 7 lt
  305. { /.colorimage cvx /stackunderflow signalerror }
  306. if
  307. 2 copy
  308. type /integertype ne exch
  309. type /booleantype ne or
  310. { /.colorimage cvx /typecheck signalerror }
  311. if
  312. % verify that the number of components is 1, 3, or 4
  313. dup 1 lt 1 index 2 eq or 1 index 4 gt or
  314. { /.colorimage cvx /rangecheck signalerror }
  315. if
  316. % Verify that the required number of operands are present if multiple
  317. % data sources are being used. If this test is successful, convert
  318. % the data sources to an array (in local VM).
  319. 1 index
  320. {
  321. dup dup count 8 sub gt
  322. {
  323. % Adobe interpreters appear to test the arguments sequentially
  324. % starting from the top of the stack and report the 1st error found.
  325. % To satisfy CET test 12-02.PS we emulate this logic.
  326. //true exch -1 1
  327. { 2 add index
  328. //good_image_types 1 index type .knownget
  329. { exec and
  330. }
  331. { pop pop //false
  332. }
  333. ifelse
  334. }
  335. for
  336. { /stackunderflow
  337. }
  338. { /typecheck
  339. }
  340. ifelse
  341. /.colorimage cvx exch signalerror
  342. }
  343. if
  344. % build the DataSource array in local VM
  345. dup .currentglobal //false .setglobal exch array exch .setglobal
  346. % stack: <w> <h> <bps> <mtx> <d0> ... <multi> <n> <n'> <array>
  347. 4 1 roll 3 add 2 roll astore 3 1 roll
  348. }
  349. if
  350. % the image dictionary can be built; do so
  351. % stack: <w> <h> <bps> <mtx> <dsrc|dsrc_array> <multi> <n>
  352. //img_params_ary //img_build_dict exec
  353. }
  354. .forcebind def
  355. currentdict /good_image_types .undef
  356. %
  357. % <?dict?>
  358. % img_unbuild_image_dict
  359. % <width> <height> <bits/component> <matrix> <dsrc0> ...
  360. % <multi> <ncomp>
  361. %
  362. % If the top entry of the stack is a dictionary that has the keys required
  363. % by a colorimage dictionary, unpack that dictionary onto the stack.
  364. % Otherwise just leave things as they are.
  365. %
  366. /img_unbuild_image_dict
  367. {
  368. //img_check_ary //img_check_keys exec
  369. {
  370. //img_unbuild_ary //img_unbuild_dict exec
  371. 1 index type /booleantype eq
  372. {
  373. 1 index
  374. { 3 -1 roll aload length 2 add -2 roll }
  375. if
  376. }
  377. if
  378. }
  379. if
  380. }
  381. .forcebind def
  382. %
  383. % <width> <height> <polarity> <matrix> <dsrc>
  384. % img_unbuild_imagemask_dict
  385. % <dict>
  386. %
  387. % Build the dictionary corresponding to an imagemask stack. This routine
  388. % will verify that the appropriate number of operands are on the stack,
  389. % and that polarity is a boolean. This is all that is necessary to build
  390. % the dictionary.
  391. %
  392. /img_build_imagemask_dict
  393. {
  394. % check for proper number of operands
  395. count 5 lt
  396. { /imagemask .systemvar /stackunderflow signalerror }
  397. if
  398. % verify that polarity is a boolean
  399. 2 index type /booleantype ne
  400. { /imagemask .systemvar /typecheck signalerror }
  401. if
  402. % the imagemask dictionary can be built; do so
  403. //img_mask_params_ary //img_build_dict exec
  404. }
  405. .forcebind def
  406. %
  407. % <?dict?>
  408. % img_unbuild_imagemask_dict
  409. % <width> <height> <polarity> <matrix> <dsrc>
  410. %
  411. % If the top entry of the stack is a dictionary that has the keys rquired
  412. % by an imagemask dictionary, unpack that dictionary onto the stack.
  413. % Otherwise just leave things as they are.
  414. %
  415. /img_unbuild_imagemask_dict
  416. {
  417. //img_mask_check_ary //img_check_keys exec
  418. {
  419. //img_mask_unbuild_ary //img_unbuild_dict exec
  420. 3 -1 roll
  421. dup type dup /arraytype eq exch /packedarraytype eq or
  422. 1 index rcheck and
  423. { 0 get 1 eq }
  424. if
  425. 3 1 roll
  426. }
  427. if
  428. }
  429. .forcebind def
  430. %
  431. % <width> <height> <bits/component> <matrix> <dsrc_0> ...
  432. % <multi> <ncomp>
  433. % .colorimage
  434. % -
  435. %
  436. % Convert the image/colorimage operator from their traditional form to
  437. % the dictionary form.
  438. %
  439. % Error handling for these operators is a bit complex, due to the stack
  440. % handling required of operators that potentially invoke procedures.
  441. % This problem is discussed in the comment above. The facts relevant to
  442. % this particular implementation are:
  443. %
  444. % 1. The .image1 operator is executed in a stopped
  445. % context, so that we can undo the gsave context in the event of
  446. % an error.
  447. %
  448. % 2. In the event of an error, the stack is examined to see if the
  449. % dictionary passed to .image1 is still present.
  450. % If so, this dictionary is "unpacked" onto the stack to re-
  451. % create the original stack.
  452. %
  453. % 3. The use of pseudo-operators in this case may yield incorrect
  454. % results for late-detected errors, as the stack depth will be
  455. % restored (even though the stack is not). This is, however, no
  456. % worse than the prior (level >= 2) code, so it should cause no
  457. % new problems.
  458. %
  459. /.colorimage
  460. {
  461. % build the image dictionary
  462. //img_build_image_dict exec
  463. % execute .image1 in a stopped context
  464. {
  465. gsave
  466. % The CET test file 12-02.ps creates colorimages with a width and
  467. % height of 0. Ignore these since that is what the CET expects.
  468. dup dup /Height get 0 eq exch /Width get 0 eq or
  469. { pop } % Ignore colorimage. Pop dict
  470. {
  471. 0 .setoverprintmode % disable overprint mode for images
  472. //img_csary 1 index /IMG_NComps get get setcolorspace
  473. .image1
  474. }
  475. ifelse
  476. }
  477. stopped
  478. grestore
  479. {
  480. //img_unbuild_image_dict exec
  481. /.colorimage cvx $error /errorname get
  482. signalerror
  483. }
  484. if
  485. }
  486. .forcebind def
  487. %
  488. % <width> <height> <bits/component> <matrix> <dsrc_0> ...
  489. % <multi> <ncomp>
  490. % colorimage
  491. % -
  492. %
  493. % Build the colorimage pseudo-operator only if setcolorscreen is visible.
  494. %
  495. systemdict /setcolorscreen .knownget
  496. {
  497. type /operatortype eq
  498. {
  499. /colorimage
  500. {
  501. //.colorimage
  502. stopped
  503. { /colorimage .systemvar $error /errorname get signalerror }
  504. if
  505. }
  506. .forcebind systemdict begin odef end
  507. }
  508. if
  509. }
  510. if
  511. %
  512. % width height bits_per_component matrix data_src image -
  513. %
  514. % <dict> image -
  515. %
  516. % Some special handling is required for ImageType 2 (Display PostScript
  517. % pixmap images) so as to set the appropriate color space as the current
  518. % color space.
  519. %
  520. /image
  521. {
  522. dup type /dicttype eq .languagelevel 2 ge and
  523. {
  524. dup /ImageType get dup 2 eq
  525. {
  526. % verify the ImageType 2 is supported
  527. //.imagetypes exch known
  528. {
  529. %
  530. % Set either DevicePixel or DeviceRGB as the current
  531. % color space. DevicePixel is used if the image data is
  532. % to be copied directly, with only a geometric
  533. % transformation (PixelCopy true). The use of DeviceRGB
  534. % in the alternate case is not, in general, correct, and
  535. % reflects a current implementation limitation. Ideally,
  536. % an intermediate color space should be used only if
  537. % the source and destination color models vary; otherwise
  538. % the native color space corresponding to the color model
  539. % should be used.
  540. %
  541. % The mechanism to determine depth for the DevicePixel
  542. % color space when BitsPerPixel is not available is
  543. % somewhat of a hack.
  544. %
  545. gsave
  546. 0 .setoverprintmode % disable overprintmode for images
  547. dup /PixelCopy .knownget dup
  548. { pop }
  549. if
  550. {
  551. [
  552. /DevicePixel
  553. currentpagedevice dup /BitsPerPixel .knownget
  554. { exch pop }
  555. {
  556. /GrayValues .knownget not
  557. { 2 } % try a guess
  558. if
  559. ln 2 ln div round cvi
  560. }
  561. ifelse
  562. ]
  563. }
  564. { /DeviceRGB }
  565. ifelse
  566. setcolorspace
  567. //.imagetypes 2 get
  568. stopped
  569. grestore
  570. { /image .systemvar $error /errorname get signalerror }
  571. if
  572. }
  573. { /image .systemvar /rangecheck signalerror
  574. }
  575. ifelse
  576. }
  577. {
  578. dup //.imagetypes exch .knownget
  579. {
  580. exch pop gsave
  581. 0 .setoverprintmode % disable overprintmode for images
  582. stopped
  583. grestore
  584. { /image .systemvar $error /errorname get signalerror }
  585. if
  586. }
  587. {
  588. /image .systemvar exch type /integertype eq
  589. { /rangecheck } { /typecheck }
  590. ifelse signalerror
  591. }
  592. ifelse
  593. }
  594. ifelse
  595. }
  596. {
  597. //false 1
  598. //.colorimage
  599. stopped
  600. { /image .systemvar $error /errorname get signalerror }
  601. if
  602. }
  603. ifelse
  604. }
  605. .forcebind odef
  606. % An auxiliary function for checking whether an imagemask to be interpolated.
  607. /.is_low_resolution % <image dict> .is_low_resolution <bool>
  608. { % Checking whether image pixel maps to more than 2 device pixels.
  609. % The threshold 2 is arbitrary.
  610. 1 exch 0 exch
  611. 0 exch 1 exch
  612. /ImageMatrix get dup
  613. 2 {
  614. 4 1 roll
  615. idtransform dtransform dup mul exch dup mul add sqrt
  616. } repeat
  617. .max
  618. 2 gt % arbitrary
  619. } .forcebind def
  620. %
  621. % width height polarity matrix datasrc imagemask -
  622. %
  623. % See the comment preceding the definition of .colorimage for information
  624. % as to the handling of error conditions.
  625. %
  626. /imagemask
  627. {
  628. dup type /dicttype eq .languagelevel 2 ge and
  629. { dup /ImageType get
  630. //.imagemasktypes exch .knownget
  631. { 1 index //.is_low_resolution exec
  632. 2 index /ImageType get 1 eq and
  633. 2 index /BitsPerComponent get 1 eq and
  634. 2 index /Interpolate .knownget not { //false } if and
  635. //filterdict /ImscaleDecode known and
  636. %%
  637. %% Don't apply ImScaleDecode to interpolate imagemasks if
  638. %% the current device is a high level device.
  639. %%
  640. /HighLevelDevice /GetDeviceParam .special_op {
  641. exch pop not
  642. }{
  643. //true
  644. }ifelse
  645. and
  646. {
  647. % Apply interpolated imagemask scaling filter
  648. exch .currentglobal exch dup .gcheck .setglobal
  649. dup length dict .copydict
  650. dup dup /DataSource get
  651. dup type /stringtype eq {
  652. 1 array astore cvx % image.* operators read strings repeatesly
  653. } if
  654. mark /Width 3 index /Width get /Height 5 index /Height get .dicttomark
  655. /ImscaleDecode filter /DataSource exch put
  656. dup dup /Width get 4 mul /Width exch put
  657. dup dup /Height get 4 mul /Height exch put
  658. dup dup /ImageMatrix get
  659. { 4 0 0 4 0 0 } matrix concatmatrix /ImageMatrix exch put
  660. 3 1 roll .setglobal
  661. } if
  662. exec
  663. }
  664. { % CET 12-08b.ps wants /typecheck
  665. /imagemask .systemvar /typecheck signalerror
  666. }
  667. ifelse
  668. }
  669. {
  670. //img_build_imagemask_dict exec
  671. { .imagemask1 }
  672. stopped
  673. {
  674. //img_unbuild_imagemask_dict exec
  675. /imagemask .systemvar $error /errorname get signalerror
  676. }
  677. if
  678. }
  679. ifelse
  680. }
  681. .forcebind odef
  682. % undefine a bunch of local definitions
  683. [
  684. /.colorimage
  685. /img_params_dict
  686. /img_unbuild_dict
  687. /img_unbuild_image_dict
  688. /img_unbuild_imagemask_dict
  689. /img_build_dict
  690. /img_build_image_dict
  691. /img_build_imagemask_dict
  692. /img_check_keys
  693. /img_mask_check_ary
  694. /img_params_ary
  695. /img_mask_unbuild_ary
  696. /img_mask_params_ary
  697. /img_csary
  698. /img_decary
  699. /img_check_ary
  700. /img_unbuild_ary
  701. /.is_low_resolution
  702. ] currentdict .undefinternalnames
  703. end % systemdict
  704. .setglobal % restore VM mode