home *** CD-ROM | disk | FTP | other *** search
/ jppd.dyndns.org / jppd.dyndns.org.tar / jppd.dyndns.org / QUERYPRO / Impressora_PDF / converter.exe / GPLGS / gs_cspace.ps < prev    next >
Text File  |  2003-12-13  |  30KB  |  985 lines

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