gs_cspace.ps 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. % Copyright (C) 2002 Aladdin Enterprises. 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., 101 Lucas Valley Road #110,
  14. % San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  15. % $Id: gs_cspace.ps,v 1.6 2003/06/26 22:42:33 dan Exp $
  16. % basic colorspace mechanism
  17. %
  18. % This new implementation of color spaces extends the color space
  19. % formalism to all PostScript levels. Level specific features and
  20. % operators continue to be accessible only in the appropriate level,
  21. % but the colorspace concept and associated mechanisms are used
  22. % throughout.
  23. %
  24. % The color space mechanism is built around two dictionaries:
  25. %
  26. % .cspace_util
  27. % A dictionary in global VM that is accessible in userdict only
  28. % during initialization. This dictionary is intended for various
  29. % utility procedures that are used in implementing the individual
  30. % color spaces.
  31. %
  32. % colorspacedict
  33. % A dictionary of methods for each color space type. The keys
  34. % in this dictionary are color space type names (e.g.: /DeviceGray,
  35. % /Separation, etc.), and the values are dictionaries of methods.
  36. % The set of methods is the same for each color space type, and
  37. % provides a complete implementation for the corresponding color
  38. % space type. This dictionary is in global VM.
  39. %
  40. % The information specific to a color space type is created in a file
  41. % for that type or group of types (e.g.: gs_csdev.ps, gs_csindx.ps,
  42. % etc.). These files will generally adhere to the template:
  43. %
  44. % .currentglobal true .setglobal
  45. % <level-specific dictionary> begin
  46. % ...
  47. % .cspace_util begin
  48. % colorspacedict
  49. % /<color space type name>
  50. % mark
  51. % /cs_validate
  52. % {
  53. % ...
  54. % }
  55. % bind
  56. % ...
  57. % .dicttomark
  58. % put
  59. % end % .cspace_util
  60. % end ... % level-specific dictionary
  61. % .setglobal
  62. %
  63. % The methods associated with a color space are listed below (along with
  64. % their stack handling), followed by descriptions.
  65. %
  66. % - cs_potential_indexed_base <bool>
  67. %
  68. % - cs_potential_pattern_base <bool>
  69. %
  70. % - cs_potential_alternate <bool>
  71. %
  72. % - cs_potential_icc_alternate <bool>
  73. %
  74. %
  75. % <name | array> cs_get_ncomps <int>
  76. %
  77. % <name | array> cs_get_range <range_array>
  78. %
  79. % <name | array> cs_get_default_color <c1> ... <cn>
  80. %
  81. %
  82. % <c1> ... <cn> <name | array> cs_get_currentgray <gray>
  83. %
  84. % <c1> ... <cn> <name | array> cs_get_currentrgb <red> <green> <blue>
  85. %
  86. % <c1> ... <cn> <name | array> cs_get_currentcmyk
  87. % <cyan> <magenta> <yellow> <black>
  88. %
  89. %
  90. % <name | array> cs_validate <name | array>
  91. %
  92. % <name1 | array1> cs_substitute <name1 | array1> <array2>
  93. %
  94. % <name1 | array1> <array2> cs_prepare <name1 | array1> <array2>
  95. %
  96. % <name | array> cs_install -
  97. %
  98. %
  99. % <c1> ... <cn> <array> cs_verify_color <c1> ... <cn>
  100. %
  101. % <array> cs_complete_color -
  102. %
  103. %
  104. % cs_potential_indexed_base, cs_potential_pattern_base,
  105. % cs_potential_alternate, cs_potential_icc_alternate
  106. % These are booleans rather than procedures. They indicate if the color
  107. % space can be a base space of an Indexed color space (anything except
  108. % Indexed and Pattern), a Pattern color space (anything except Pattern),
  109. % the alternative color space of a Separation or DeviceN color space, or
  110. % the alternative color space of an ICCBased color space. The two
  111. % parameters are distinct only because of a Ghostscript-specific
  112. % implementation problem; in principle, there is nothing special about
  113. % ICCBased color spaces in this regard.
  114. %
  115. % cs_get_ncomps
  116. % Return the number of color components for the color spaces. For Pattern
  117. % color spaces, the value is -1 if there is no base space, or -(n + 1) if
  118. % the base space has n components.
  119. %
  120. % cs_get_range
  121. % Return the input Range array appropriate for this color space. This is
  122. % defined for all color spaces, though it is of interest primarily for
  123. % CIEBased and ICCBased color spaces. For Indexed color spaces this is
  124. % [ 0 hival ], where hival is the maximum support index value. For all
  125. % other non-CIEBased, non-ICCBased color spaces, the range is an array
  126. % of ncomps elements, all of which are [ 0 1 ], where ncomps is the
  127. % number of color space components.
  128. %
  129. % cs_get_default_color
  130. % Generates the default color for the current color space. Under normal
  131. % circumstances this is done internally. It is provided in PostScript
  132. % only to support an optimization that doesn't change the current color
  133. % space more often than necessary.
  134. %
  135. % cs_get_currentgray, cs_get_currentrgb, cs_get_currentcmyk
  136. % These procedures are used to implement the currentgray, currentrgb,
  137. % and currentcmyk operators (which are pseudo-operators in the current
  138. % implementation).
  139. %
  140. % cs_validate
  141. % Validate the operand color space. Because color spaces are extensively
  142. % manipulated in PostScript in this implementation, error handling can
  143. % become burdensome. To make the code somewhat simpler, it is useful to
  144. % be able to validate a color space prior to manipulation, so as to
  145. % ensure that errors are not discovered in awkward places.
  146. %
  147. % cs_substitute
  148. % Substitute a device-independent color space for device specific color
  149. % space. This applies directly to the device-specific color spaces
  150. % (DeviceGray, DeviceRGB, DeviceCMYK), and indirectly when these color
  151. % spaces are used as base/alternative color spaces. The mechanism for
  152. % color substitution is included in all language levels, though it may
  153. % only be accessed for Language Level 3.
  154. %
  155. % The substituted color space is the topmost of the operands pushed.
  156. % this may or may not be the same as the original color space, which
  157. % is immediately below it on the operand stack. If the two differ,
  158. % the substituted space will always be in local VM (and will be
  159. % writable).
  160. %
  161. % Substitution is applied recursively to the base/alternate color
  162. % space of ICCBased, Indexed, Separation, DeviceN, or Pattern
  163. % color spaces. Because Ghostscript currently requires that any
  164. % base or alternative color space be the current color space when
  165. % the enclosing color space is set, this substitution effectively
  166. % occurs twice: once in the original color space, and once when the
  167. % base/alternative color space is made the current color space.
  168. % We retain the first substitution as we would eventually like to
  169. % remove the restriction on making the base/alternative color space
  170. % the current color space.
  171. %
  172. % cs_prepare
  173. % Perform any operations required on the color space for installation.
  174. % This method exists primarily to allow conversion of PostScript
  175. % procedures to functions for CIEBased color spaces. Two operands are
  176. % provided: the original and the substituted color space. If the two
  177. % differ and the latter is writable, required modifications can
  178. % be made "in place". Otherwise, a new instance of the second color
  179. % space must be built.
  180. %
  181. % Currently, cs_prepare is not explicitly recursive. Because
  182. % Ghostscript requires a base/alternate color space to be installed
  183. % as the current color space prior to installing the enclosing color
  184. % space, the cs_prepare method will implicitly be called recursively.
  185. % The reason for not making this explicit is that color space
  186. % preparation may involve a considerable amount of work, which could
  187. % be avoided if, for example, an alternative color space will not
  188. % be used because the enclosing Separation/DeviceN color space is
  189. % supported in native mode by the process color model. We would
  190. % eventually like to remove the need to prepare color spaces that
  191. % will not be used.
  192. %
  193. % cs_install
  194. % This method actually installs the color space in the graphic state.
  195. % Only the substituted/prepared space (which may be the same as the
  196. % original space) is passed as an operand; the original space is handled
  197. % directly by the .setcolorspace operator.
  198. %
  199. % The provision of a separate method for this tasks reflects the
  200. % historical implementation of color spaces in the Ghostscript
  201. % interpreter. This implementation provides a unique operator for each
  202. % color space type.
  203. %
  204. % cs_prepare_color
  205. % Modify a set of color operands as required by a color space. This
  206. % is used primarily to verify the color operands, as this is most
  207. % conveniently done in PostScript.
  208. %
  209. % cs_complete_setcolor
  210. % This method is invoked immediately after a (successful) invocation
  211. % of setcolor. Ii is provided as a separate method for compatibility
  212. % with Adobe implementations. These implementations invoke the lookup
  213. % (Indexed) or tint procedure each time setcolor is invoked (only if
  214. % the alternative color space is used in the case of the tint
  215. % transform). Because Ghostscript may convert these procedures to
  216. % functions (or pre-sample them), the procedures may not always be
  217. % called when expected. There are applications that depend on this
  218. % behavior (e.g.: Adobe PhotoShop 5+), so this method provides a way
  219. % to emulate it.
  220. %
  221. % In principle, a cs_complete_setcolor procedure for an Indexed color
  222. % space whose base space should invoke cs_complete_setcolor on its
  223. % base space. Currently we don't do this, because it has not been
  224. % shown to be necessary. It would be simple to add if it is every
  225. % needed.
  226. %
  227. % All of these methods are procedures.
  228. %
  229. % For each of these methods, there is a procedure in .cspace_util with
  230. % a dot ('.') prefix that will invoke the appropriate procedure for the
  231. % operand array.
  232. %
  233. .currentglobal true .setglobal
  234. userdict /.cspace_util 80 dict put
  235. .cspace_util begin
  236. %
  237. % Colorspacedict is initially in .cspace_util; it is copied to level2dict
  238. % in the Level 2 initialization code to retain compatibility with
  239. % earlier implementations.
  240. %
  241. /colorspacedict 20 dict def
  242. %
  243. % <obj> make_array1 <array>
  244. %
  245. % procedure for conditionally converting a named color space to a
  246. % 1-element array. Since names are always global, the array will be
  247. % as well.
  248. %
  249. /make_array1
  250. {
  251. dup type /nametype eq
  252. { currentglobal true setglobal exch 1 array astore exch setglobal }
  253. if
  254. }
  255. bind def
  256. %
  257. % <name|array> .get_cspace_type name
  258. %
  259. % Provide generic routine for retrieving the color space type.
  260. %
  261. /.get_cspace_type
  262. {
  263. dup type dup /arraytype eq exch /packedarraytype eq or
  264. { 0 get }
  265. if
  266. }
  267. bind def
  268. %
  269. % <name|array> .get_method_dict <dict>
  270. %
  271. % Get the method dictionary for a specific color space. Note that the
  272. % color space is left on the stack.
  273. %
  274. /.get_method_dict
  275. { //colorspacedict exch //.get_cspace_type exec get }
  276. bind def
  277. %
  278. % <name|array> <proc_name> .get_method <name|array> <proc | bool>
  279. %
  280. % Get the named method for the operand color space.
  281. %
  282. /.get_method
  283. { exch //.get_method_dict exec exch get }
  284. bind def
  285. %
  286. % <name_array> .cs_potential_indexed_base <bool>
  287. % <name_array> .cs_potential_pattern_base <bool>
  288. % <name_array> .cs_potential_alternate <bool>
  289. % <name_array> .cs_potential_icc_alternate <bool>
  290. % <name | array> .cs_get_ncomps <int>
  291. % <name | array> .cs_get_range <range_array>
  292. % <name | array> .cs_get_default_color <c1> ... <cn>
  293. % <c1> ... <cn> <name | array> .cs_get_currentgray <gray>
  294. % <c1> ... <cn> <name | array> .cs_get_currentrgb <r> <g> <b>
  295. % <c1> ... <cn> <name | array> .cs_get_currentcmyk <c> <m> <y> <k>
  296. % <name | array> .cs_validate <name | array>
  297. % <name1 | array1> .cs_substitute <name1 | array1> <array2>
  298. % <name1 | array1> <array2> .cs_prepare <name1 | array1> <array2>
  299. % <name | array> .cs_install -
  300. % <c1> ... <cn> <array> .cs_prepare_color <c1> ... <cn>
  301. % <array> .cs_complete_setcolor -
  302. %
  303. % These procedures provide access to the corresponding methods of the
  304. % operand color space.
  305. %
  306. /.cs_potential_indexed_base
  307. { /cs_potential_indexed_base //.get_method exec }
  308. bind def
  309. /.cs_potential_pattern_base
  310. { /cs_potential_pattern_base //.get_method exec }
  311. bind def
  312. /.cs_potential_alternate
  313. { /cs_potential_alternate //.get_method exec }
  314. bind def
  315. /.cs_potential_icc_alternate
  316. { /cs_potential_icc_alternate //.get_method exec }
  317. bind def
  318. /.cs_get_ncomps
  319. { dup /cs_get_ncomps //.get_method exec exec }
  320. bind def
  321. /.cs_get_range
  322. { dup /cs_get_range //.get_method exec exec }
  323. bind def
  324. /.cs_get_default_color
  325. { dup /cs_get_default_color //.get_method exec exec }
  326. bind def
  327. /.cs_get_currentgray
  328. { dup /cs_get_currentgray //.get_method exec exec }
  329. bind def
  330. /.cs_get_currentrgb
  331. { dup /cs_get_currentrgb //.get_method exec exec }
  332. bind def
  333. /.cs_get_currentcmyk
  334. { dup /cs_get_currentcmyk //.get_method exec exec }
  335. bind def
  336. /.cs_validate
  337. { dup /cs_validate //.get_method exec exec }
  338. bind def
  339. /.cs_substitute
  340. { dup /cs_substitute //.get_method exec exec }
  341. bind def
  342. /.cs_prepare
  343. { dup /cs_prepare //.get_method exec exec }
  344. bind def
  345. /.cs_install
  346. { dup /cs_install //.get_method exec exec }
  347. bind def
  348. /.cs_prepare_color
  349. { dup /cs_prepare_color //.get_method exec exec }
  350. bind def
  351. /.cs_complete_setcolor
  352. { dup /cs_complete_setcolor //.get_method exec exec }
  353. bind def
  354. %
  355. % Make sure we have an interpreter color space before redefining
  356. % setcolorspace. The interpreter internal code only sets the effective
  357. % color space; the interpreters color spaces begins as a null object.
  358. %
  359. % NB: This should come prior to the redefinition of setcolorspace, and
  360. % must use an array operand.
  361. %
  362. [ /DeviceGray ] setcolorspace
  363. %
  364. % <c1> ... <cn> setcolor -
  365. %
  366. % As with setcolorspace, setcolor is initially placed in .cspace_util,
  367. % and is copied to level2dict by the Level 2 initialization code. The
  368. % internal definition of setcolor is removed from systemdict as soon
  369. % as this procedure is defined.
  370. %
  371. /setcolor
  372. {
  373. {
  374. currentcolorspace //.cs_prepare_color exec //setcolor
  375. currentcolorspace //.cs_complete_setcolor exec
  376. }
  377. stopped
  378. { //.cspace_util /setcolor get $error /errorname get signalerror }
  379. if
  380. }
  381. bind odef
  382. systemdict /setcolor .undef
  383. %
  384. % <name|array> <bool> _setcolorspace -
  385. % <name|array> _setcolorspace_nosub -
  386. %
  387. % <name|array> setcolorspace -
  388. % <name|array> forcesetcolorspace -
  389. %
  390. % setcolorspace is initially placed in .cspace_util. It is copied to
  391. % level2dict by the Level 2 initialization code. The internal
  392. % setcolorspace operator is removed from systemdict as soon as this
  393. % procedure is defined.
  394. %
  395. % Because some jobs, in particular PDF jobs, repeatedly set the same
  396. % color space, this procedure will check if the operand and current
  397. % color spaces are the same. The check is absolute for parameterless
  398. % color spaces, conservative for others. For PostScript, this
  399. % optimization can only be employed if color space substitution is
  400. % disabled, as otherwise there is no way to account for possible changes
  401. % in the /Default* instances of the ColorSpace resource category. For PDF
  402. % jobs, resource category instances can only be changed at very specific
  403. % times (typically page boundaries), so the "operand color space is the
  404. % same as current color space" optimization may be used even if color
  405. % space substitution is in effect. The optimization is also highly
  406. % desirable in such cases, as it greatly improves performance.
  407. %
  408. % In certain situations, it is critical that a color space be set,
  409. % even if it is the same as the current color space. This is the case
  410. % when a CIEBased color space is used as a base or alternative color
  411. % space, due to some long-standing problems with the graphics libraries
  412. % handling of sampled information from the procedures in CIE color
  413. % spaces and the color rendering dictionary. The forcesetcolorspace
  414. % operator is provided for those situations.
  415. %
  416. % Note also that, if the current color space is not reset, at least
  417. % the current color must be reset to its default value.
  418. %
  419. % Another problem arises in the case of ICCBased color spaces. These
  420. % color spaces may be used to substitute for a DeviceGray/DeviceRGB/
  421. % DeviceCMYK color space, and may themselves require such a color
  422. % space as an alternate. Obviously, when this is the case the normal
  423. % setcolorspace mechanism would encounter and infinite loop if the
  424. % alternate colro space needed to be used. For this particular case,
  425. % the special _setcolorspace_nosub is provided, which suppresses
  426. % color space substitution. This routine does not bother to check if
  427. % the operand and current color space are the same.
  428. %
  429. /_setcolorspace
  430. {
  431. {
  432. % see if the operand space is the same as the current space
  433. currentcolorspace dup length 1 eq
  434. {
  435. 0 get
  436. 2 index dup type dup /arraytype eq exch /packedarraytype eq or
  437. {
  438. dup length 1 eq
  439. { 0 get }
  440. if
  441. }
  442. if
  443. }
  444. { 2 index }
  445. ifelse
  446. eq and dup
  447. {
  448. %
  449. % If PDFfile is defined on the dictionary stack, this is a
  450. % PDF job. No additional check is required in this case (see
  451. % comment above).
  452. %
  453. /PDFfile where
  454. { pop }
  455. { .getuseciecolor not and } % check that UseCIEColor is off
  456. ifelse
  457. }
  458. if
  459. { //.cs_get_default_color exec setcolor }
  460. {
  461. //.cs_validate exec
  462. //.cs_substitute exec
  463. //.cs_prepare exec
  464. //.cs_install exec
  465. //make_array1 exec //setcolorspace
  466. }
  467. ifelse
  468. }
  469. stopped
  470. { //.cspace_util /setcolorspace get $error /errorname get signalerror }
  471. if
  472. }
  473. bind def
  474. /_setcolorspace_nosub
  475. {
  476. {
  477. //.cs_validate exec
  478. dup
  479. //.cs_prepare exec
  480. //.cs_install exec
  481. //make_array1 exec //setcolorspace
  482. }
  483. stopped
  484. { //.cspace_util /setcolorspace get $error /errorname get signalerror }
  485. if
  486. }
  487. bind def
  488. /setcolorspace { //true //_setcolorspace exec } bind odef
  489. /forcesetcolorspace { //false //_setcolorspace exec } bind odef
  490. %
  491. % - initgraphics -
  492. %
  493. % The initgraphics operator must be redefined create a real color space.
  494. % Previously this was unnecessary, as .currentcolorspace could return
  495. % an integer.
  496. %
  497. %
  498. /initgraphics
  499. { initgraphics { /DeviceGray } cvlit forcesetcolorspace }
  500. .bind systemdict begin odef end
  501. systemdict /setcolorspace .undef
  502. %
  503. % <gray> setgray -
  504. %
  505. % <r> <g> <b> setrgbcolor -
  506. %
  507. % <c> <m> <y> <b> setcmykcolor -
  508. %
  509. % The Level 1 color setting operators. setcmykcolor is created only if
  510. % setcolorscreen is present. These operators are always defined in
  511. % systemdict.
  512. %
  513. /setgray
  514. {
  515. { { /DeviceGray } cvlit //setcolorspace //setcolor }
  516. stopped
  517. { /setgray load $error /errorname get signalerror }
  518. if
  519. }
  520. bind systemdict begin odef end
  521. /setrgbcolor
  522. {
  523. { { /DeviceRGB } cvlit //setcolorspace //setcolor }
  524. stopped
  525. { /setrgbcolor load $error /errorname get signalerror }
  526. if
  527. }
  528. bind systemdict begin odef end
  529. /setcolorscreen where
  530. {
  531. pop
  532. /setcmykcolor
  533. {
  534. { { /DeviceCMYK } cvlit //setcolorspace //setcolor }
  535. stopped
  536. { /setcmykcolor load $error /errorname get signalerror }
  537. if
  538. }
  539. bind systemdict begin odef end
  540. }
  541. if
  542. %
  543. % - currentgray <gray>
  544. %
  545. % - currentrgbcolor <r> <g> <b>
  546. %
  547. % - currentcmykcolor <c> <m> <y> <k>
  548. %
  549. % Return the current color, mapped to a DeviceGray, DeviceRGB, or
  550. % DeviceCMYK color space. The latter is only created if setcolorscreen
  551. % is present.
  552. /currentgray
  553. { currentcolor currentcolorspace //.cs_get_currentgray exec }
  554. bind systemdict begin odef end
  555. /currentrgbcolor
  556. { currentcolor currentcolorspace //.cs_get_currentrgb exec }
  557. bind systemdict begin odef end
  558. /setcolorscreen where
  559. {
  560. pop
  561. /currentcmykcolor
  562. { currentcolor currentcolorspace //.cs_get_currentcmyk exec }
  563. bind systemdict begin odef end
  564. }
  565. if
  566. %
  567. % Add some generically useful structures and procedures to .cspace_util.
  568. %
  569. %
  570. % Some common errors. The command for these errors will normally be
  571. % overwritten by the invoking operator. We cannot "load" the secolorspace
  572. % or setcolor operators, as they are not present in Level 1 systems.
  573. %
  574. /setcspace_typecheck
  575. { /setcolorspace cvx /typecheck signalerror }
  576. bind def
  577. /setcspace_rangecheck
  578. { /setcolorspace cvx /rangecheck signalerror }
  579. bind def
  580. /setcspace_invalidaccess
  581. { /setcolorspace cvx /invalidaccess signalerror }
  582. bind def
  583. /setcspace_undefined
  584. { /setcolorspace cvx /undefined signalerror }
  585. bind def
  586. /setcolor_typecheck
  587. { /setcolor cvx /typecheck signalerror }
  588. bind def
  589. /setcolor_invalidaccess
  590. { /setcolor cvx /invalidaccess signalerror }
  591. bind def
  592. %
  593. % <obj> check_array <obj>
  594. %
  595. % Check that an object is an array. Currently we don't check for
  596. % readability, as a failing get or length operator should generate
  597. % the appropriate invalidaccess error.
  598. /check_array
  599. {
  600. dup type dup /arraytype ne exch /packedarraytype ne and
  601. { /setcolorspace cvx /typecheck signalerror }
  602. if
  603. }
  604. bind def
  605. % pre-defined procedures for cs_ncomps and cs_get_range
  606. /ncomps_1 { pop 1 } bind def
  607. /ncomps_3 { pop 3 } bind def
  608. /ncomps_4 { pop 4 } bind def
  609. /dflt_range_4 [ 0 1 0 1 0 1 0 1 ] readonly def
  610. /dflt_range_3 dflt_range_4 0 6 getinterval def
  611. /dflt_range_1 dflt_range_4 0 2 getinterval def
  612. % <obj> get_range_[1|3|4] <range>
  613. /get_range_1 { pop //dflt_range_1 } bind def
  614. /get_range_3 { pop //dflt_range_3 } bind def
  615. /get_range_4 { pop //dflt_range_4 } bind def
  616. %
  617. % <c1> ... <cn> <name | array> <n>
  618. % check_num_stack
  619. % <c1> ... <cn> <array | array>
  620. %
  621. % <c1> <array> validate_color_1 <c1>
  622. % <c1> <c2> <c3> <arraY> validate_color_3 <c1> <c2> <c3>
  623. % <c1> <c2> <c3> <c4> <arraY> validate_color_4 <c1> <c2> <c3> <c4>
  624. %
  625. % check_num_stack verifies that the stack consists of a color space array and
  626. % n numbers. This is used by most of the cs_prepare_color procedures. The
  627. % validate_color_[1|3|4] procedures can be used as the cs_prepare_color
  628. % procedure for Device specific, CIEBased, and Indexed color spaces.
  629. %
  630. % Note that the pseudo-operator that (indirectly) invokes this routine will
  631. % handle resetting the stacks.
  632. %
  633. /check_num_stack
  634. {
  635. dup 2 add copy exch pop
  636. {
  637. type dup /integertype ne exch /realtype ne and
  638. //setcolor_typecheck
  639. if
  640. }
  641. repeat
  642. pop % remove the extra op_count
  643. }
  644. bind def
  645. % <c1> <array> validate_1 <c1>
  646. /validate_1 { 1 //check_num_stack exec pop } bind def
  647. % <c1> <c2> <c3> <array> validate_3 <c1> <c2> <c3>
  648. /validate_3 { 3 //check_num_stack exec pop } bind def
  649. % <c1> <c2> <c3> <c4> <array> validate_4 <c1> <c2> <c3> <c4>
  650. /validate_4 { 4 //check_num_stack exec pop } bind def
  651. %
  652. % <obj> pop_1 -
  653. %
  654. % This is a procedure form of pop. It may be used where a procedure is
  655. % expected, but the function of the procedure is the same as the pop
  656. % operator.
  657. /pop_1 { pop } bind def
  658. %
  659. % <obj> dup_1 <obj> <obj>
  660. %
  661. % An analog to pop_1, this one for dup.
  662. %
  663. /dup_1 { dup } bind def
  664. %
  665. % <obj1> ... <objn> <n> clear_n_objs -
  666. %
  667. % Clear n objects from the operand stack.
  668. %
  669. /clear_n_objs { //pop_1 repeat } bind def
  670. %
  671. % <obj1> ... <objn> <array> clear_setcolor_operands -
  672. %
  673. % Clear the setcolor operands for a color space.
  674. %
  675. /clear_setcolor_operands
  676. { //.cs_get_ncomps exec //clear_n_objs exec }
  677. bind def
  678. %
  679. % Return 1, 3, or 4 zeros. These routines are used primarily for the
  680. % CIEBased color spaces, for which currentgray and currentrgb
  681. % should return 0 for all components, and currentcmyk should return
  682. % 0 0 0 1.0 (this varies from Adobe's documentation but is consistent
  683. % with their impelementations).
  684. %
  685. /no_currentgray { //.cs_get_ncomps exec //clear_n_objs exec 0 } bind def
  686. /no_currentrgb { //.cs_get_ncomps exec //clear_n_objs exec 0 0 0 } bind def
  687. /no_currentcmyk { //.cs_get_ncomps exec //clear_n_objs exec 0 0 0 1.0 } bind def
  688. %
  689. % <num> bound_0_1 <num>
  690. %
  691. % Bound a number to the range [0, 1]
  692. %
  693. /bound_0_1
  694. {
  695. dup 0 lt
  696. { pop 0 }
  697. {
  698. dup 1 gt
  699. { pop 1 }
  700. if
  701. }
  702. ifelse
  703. }
  704. bind def
  705. %
  706. % Provide pseudo-operators for sethsbcolor and currenthsbcolor. These are
  707. % alternate versions of the setrgbcolor and currentrgbcolor operators, which
  708. % make use of a hue/staturation/brightness color description.
  709. %
  710. %
  711. % <num_1> ... <num_n> n max_n <num>
  712. % <num_1> ... <num_n> n min_n <num>
  713. %
  714. % Find the maximum and minum of 3 color component intensities.
  715. %
  716. /max_n
  717. {
  718. 1 sub
  719. { 2 copy lt { exch } if pop }
  720. repeat
  721. }
  722. bind def
  723. /min_n
  724. {
  725. 1 sub
  726. { 2 copy gt { exch } if pop }
  727. repeat
  728. }
  729. bind def
  730. %
  731. % <r> <g> <b> .rgb_2_hsb <h> <s> <br>
  732. % <h> <s> <br> .hsb_2_rgb <r> <g> <b>
  733. %
  734. % Convert between RGB and HSB colors, using the hexcone approach (see
  735. % Rogers, David, "Procedureal Elements For Computer Graphics",
  736. % (McGraw-Hill, 1985), pp. 402 - 3).
  737. %
  738. % The rgb ==> hsb calculation is:
  739. %
  740. % br = max(r, g, b)
  741. %
  742. % if (br == 0)
  743. % h = 0, s = 0;
  744. % else {
  745. % v = min(r, g, b)
  746. % diff = br - v;
  747. % sat = diff / br;
  748. % if (r == br)
  749. % h = (g - b) / (6 * diff) + (b > g ? 1 : 0);
  750. % else if (g == br)
  751. % h = 1/3 + (b - r) / (6 * diff);
  752. % else /* b == br */
  753. % h = 2/3 + (r - g) / (6 * diff);
  754. % }
  755. %
  756. % The hsb ==> rgb conversion is:
  757. %
  758. % mn = (1 - s) * br, md = 6 * s * br;
  759. %
  760. % switch ((int)floor(6 * h)) {
  761. % case 0: /* r >= g >= b */
  762. % r = br;
  763. % g = mn + h * md;
  764. % b = mn;
  765. % break;
  766. %
  767. % case 1: /* g >= r >= b */
  768. % r = mn + md * (1/3 - h);
  769. % g = br;
  770. % b = mn;
  771. % break;
  772. %
  773. % case 2: /* g >= b >= r */
  774. % r = mn;
  775. % g = br;
  776. % b = mn + (h - 1/3) * md;
  777. % break;
  778. %
  779. % case 3: /* b >= g >= r */
  780. % r = mn;
  781. % g = mn + (2/3 - h) * md;
  782. % b = br;
  783. % break;
  784. %
  785. % case 4: /* b >= r >= g */
  786. % r = mn + (h - 2/3) * md;
  787. % g = mn;
  788. % b = br;
  789. % break;
  790. %
  791. % case 5: /* r >= b >= g */
  792. % r = br;
  793. % g = mn;
  794. % b = mn + (1 - h) * md;
  795. % break;
  796. %
  797. % case 6: /* We have wrapped around the hexcone. Thus this case is
  798. % the same as case 0 with h = 0 */
  799. % h = 0;
  800. % r = br;
  801. % g = mn + h * md = mn;
  802. % b = mn;
  803. % break;
  804. % }
  805. %
  806. /.rgb_2_hsb
  807. {
  808. % find the largest and smallest components
  809. 3 copy 3 //max_n exec dup 5 1 roll
  810. dup 0 eq
  811. { pop pop pop pop 0 0 }
  812. {
  813. 4 copy pop 3 //min_n exec 1 index exch sub
  814. dup 2 index div 7 1 roll
  815. dup 0 eq
  816. { 5 { pop } repeat 0 3 1 roll }
  817. {
  818. 6 mul 5 1 roll
  819. 2 copy eq % blue == brightness
  820. { pop pop sub exch div .666667 add }
  821. {
  822. 2 index eq % green == brightness
  823. { exch pop exch sub exch div .3333333 add }
  824. {
  825. % red == brightness
  826. sub exch pop exch div
  827. dup 0 lt
  828. { 1 add }
  829. if
  830. }
  831. ifelse
  832. }
  833. ifelse
  834. 3 1 roll
  835. }
  836. ifelse
  837. }
  838. ifelse
  839. }
  840. bind def
  841. /.hsb_2_rgb
  842. {
  843. 3 { 0 max 1 min 3 1 roll } repeat
  844. 1 2 index sub 1 index mul % (1 - s) * br
  845. 3 -1 roll 2 index mul 6 mul % 6 * s * br
  846. 4 -1 roll % stack: <br> <(1 - s) * br> <6 * s * br> <h>
  847. % array of procedures for the 7 hue cases
  848. {
  849. % 0 ==> r >= g >= b
  850. { mul 1 index add exch }
  851. % 1 ==> g >= r >= b
  852. { 0.333333 exch sub mul 1 index add 3 1 roll }
  853. % 2 ==> g >= b >= r
  854. { 0.333333 sub mul 1 index add 3 1 roll exch 3 -1 roll }
  855. % 3 ==> b >= g >= r
  856. { 0.666667 exch sub mul 1 index add 3 -1 roll }
  857. % 4 ==> b >= r >= g
  858. { 0.666667 sub mul 1 index add 3 1 roll exch }
  859. % 5 ==> r >= b >= g
  860. { 1 exch sub mul 1 index add }
  861. % 6 ==> r = br, g = b = mn
  862. % Case 6 is the same as case 0 with h = 0. This also simplifies
  863. % the calculations.
  864. { pop pop dup }
  865. }
  866. 1 index 6 mul cvi % (int)(6 * h)
  867. get exec
  868. }
  869. bind def
  870. %
  871. % <hue> <saturation> <brightness sethsbcolor -
  872. %
  873. % - currenthsbcolor <hue> <saturation> <brightness>
  874. %
  875. /sethsbcolor
  876. {
  877. { //.hsb_2_rgb exec setrgbcolor }
  878. stopped
  879. { /sethsbcolor load $error /errorname get signalerror }
  880. if
  881. }
  882. bind systemdict begin odef end
  883. /currenthsbcolor
  884. {
  885. { currentrgbcolor //.rgb_2_hsb exec }
  886. stopped
  887. { /currenthsbcolor load $error /errorname get signalerror }
  888. if
  889. }
  890. bind systemdict begin odef end
  891. end % .cspace_util
  892. .setglobal