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