Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
 
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