1
/* Copyright (C) 2001-2008 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: zcolor.c 12140 2011-02-10 10:43:26Z ken $ */
20
#include "dstack.h" /* for systemdict */
26
#include "gscolor.h" /* for gs_setgray and gs_setrgbcolor */
27
#include "gscsepr.h" /* For declarartion of Separation functions */
28
#include "gscdevn.h" /* For declarartion of DeviceN functions */
29
#include "gscpixel.h" /* For declarartion of DevicePixel functions */
33
#include "gxdcolor.h" /* for gxpcolor.h */
35
#include "gxdevmem.h" /* for gxpcolor.h */
45
#include "ifunc.h" /* For declaration of buildfunction */
49
#include "zcolor.h" /* For the PS_colour_space_t structure */
50
#include "zcie.h" /* For CIE space function declarations */
51
#include "zicc.h" /* For declaration of seticc */
52
#include "gscspace.h" /* Needed for checking if current pgs colorspace is CIE */
53
#include "iddict.h" /* for idict_put_string */
54
#include "zfrsd.h" /* for make_rss() */
56
/* imported from gsht.c */
57
extern void gx_set_effective_transfer(gs_state *);
59
/* Essential forward declarations */
60
static int validate_spaces(i_ctx_t *i_ctx_p, ref *arr, int *depth);
61
static int setcolorspace_cont(i_ctx_t *i_ctx_p);
62
static int setcolor_cont(i_ctx_t *i_ctx_p);
64
/* define the number of stack slots needed for zcolor_remap_one */
65
const int zcolor_remap_one_ostack = 4;
66
const int zcolor_remap_one_estack = 3;
69
/* utility to test whether a Pattern instance uses a base space */
71
pattern_instance_uses_base_space(const gs_pattern_instance_t * pinst)
73
return pinst->type->procs.uses_base_space(
74
pinst->type->procs.get_pattern(pinst) );
78
* - currentcolor <param1> ... <paramN>
80
* Return the current color. <paramN> may be a dictionary or a null
81
* object, if the current color space is a pattern color space. The
82
* other parameters will be numeric.
84
* Note that the results of this operator differ slightly from those of
85
* most currentcolor implementations. If a color component value is
86
* integral (e.g.: 0, 1), it will be pushed on the stack as an integer.
87
* Most currentcolor implementations, including the earlier
88
* implementation in Ghostscript, would push real objects for all
89
* color spaces except indexed color space. The approach taken here is
90
* equally legitimate, and avoids special handling of indexed color
94
zcurrentcolor(i_ctx_t * i_ctx_p)
97
const gs_color_space * pcs = gs_currentcolorspace(igs);
98
const gs_client_color * pcc = gs_currentcolor(igs);
99
int i, n = cs_num_components(pcs);
100
bool push_pattern = n < 0;
102
/* check for pattern */
104
gs_pattern_instance_t * pinst = pcc->pattern;
106
if (pinst == 0 || !pattern_instance_uses_base_space(pinst))
112
/* check for sufficient space on the stack */
116
/* push the numeric operands, if any */
119
for (i = 0; i < n; i++, op++) {
120
float rval = pcc->paint.values[i];
121
int ival = (int)rval;
123
/* the following handles indexed color spaces */
124
if (rval == ival && pcs->type->index == gs_color_space_index_Indexed)
130
/* push the pattern dictionary or null object, if appropriate */
132
*op = istate->pattern[0];
138
* - .currentcolorspace <array>
140
* Return the current color space. Unlike the prior implementation, the
141
* istate->color_space.array field will now always have a legitimate
145
zcurrentcolorspace(i_ctx_t * i_ctx_p)
147
os_ptr op = osp; /* required by "push" macro */
152
/* Adobe applications expect that the Device spaces (DeviceGray
153
* DeviceRGB and DeviceCMYK) will always return the same array.
154
* Not merely the same content but the same actual array. To do
155
* this we define the arrays at startup (see gs_cspace.ps), and
156
* recover them here by executing PostScript.
158
if (r_has_type(&istate->colorspace[0].array, t_name)) {
159
name_string_ref(imemory, &istate->colorspace[0].array, &namestr);
160
if (r_size(&namestr) == 10 && !memcmp(namestr.value.bytes, "DeviceGray", 10)) {
161
body = ialloc_string(32, "string");
163
return_error(e_VMerror);
164
memcpy(body, "systemdict /DeviceGray_array get", 32);
165
make_string(&stref, a_all | icurrent_space, 32, body);
167
if (r_size(&namestr) == 9 && !memcmp(namestr.value.bytes, "DeviceRGB", 9)) {
168
body = ialloc_string(31, "string");
170
return_error(e_VMerror);
171
memcpy(body, "systemdict /DeviceRGB_array get", 31);
172
make_string(&stref, a_all | icurrent_space, 31, body);
174
if (r_size(&namestr) == 10 && !memcmp(namestr.value.bytes, "DeviceCMYK", 10)) {
175
body = ialloc_string(32, "string");
177
return_error(e_VMerror);
178
memcpy(body, "systemdict /DeviceCMYK_array get", 32);
179
make_string(&stref, a_all | icurrent_space, 32, body);
181
/* Not one of the Device spaces, but still just a name. Give
182
* up and return the name on the stack.
185
code = ialloc_ref_array(op, a_all, 1, "currentcolorspace");
188
refset_null(op->value.refs, 1);
189
ref_assign_old(op, op->value.refs,
190
&istate->colorspace[0].array,
191
"currentcolorspace");
196
r_set_attrs(&stref, a_executable);
198
ref_assign(esp, &stref);
199
return o_push_estack;
201
/* If the space isn't a simple name, then we don't need any special
202
* action and can simply use it.
205
*op = istate->colorspace[0].array;
211
* - .getuseciecolor <bool>
213
* Return the current setting of the use_cie_color graphic state parameter,
214
* which tracks the UseCIEColor page device parameter. This parameter may be
215
* read (via this operator) at all language leves, but may only be set (via
216
* the .setuseciecolor operator; see zcolor3.c) only in language level 3.
218
* We handle this parameter separately from the page device primarily for
219
* performance reasons (the parameter may be queried frequently), but as a
220
* side effect achieve proper behavior relative to the language level. The
221
* interpreter is always initialized with this parameter set to false, and
222
* it can only be updated (via setpagedevice) in language level 3.
225
zgetuseciecolor(i_ctx_t * i_ctx_p)
230
*op = istate->use_cie_color;
235
* <param1> ... <paramN> setcolor -
237
* Set the current color. All of the parameters except the topmost (paramN) are
238
* numbers; the topmost (and possibly only) entry may be pattern dictionary or
241
* The use of one operator to set both patterns and "normal" colors is
242
* consistent with Adobe's documentation, but primarily reflects the use of
243
* gs_setcolor for both purposes in the graphic library. An alternate
244
* implementation would use a .setpattern operator, which would interface with
247
* This operator is hidden by a pseudo-operator of the same name, so it will
248
* only be invoked under controlled situations. Hence, it does no operand
252
zsetcolor(i_ctx_t * i_ctx_p)
256
const gs_color_space * pcs = gs_currentcolorspace(igs);
258
int n_comps, n_numeric_comps, num_offset = 0, code, depth;
260
PS_colour_space_t *space;
262
/* initialize the client color pattern pointer for GC */
265
/* check for a pattern color space */
266
if ((n_comps = cs_num_components(pcs)) < 0) {
268
if (r_has_type(op, t_dictionary)) {
269
ref *pImpl, pPatInst;
272
code = dict_find_string(op, "Implementation", &pImpl);
275
code = array_get(imemory, pImpl, 0, &pPatInst);
278
cc.pattern = r_ptr(&pPatInst, gs_pattern_instance_t);
279
n_numeric_comps = ( pattern_instance_uses_base_space(cc.pattern)
282
(void)dict_int_param(op, "PatternType", 1, 2, 1, &ptype);
283
is_ptype2 = ptype == 2;
288
n_numeric_comps = n_comps;
290
/* gather the numeric operands */
291
code = float_params(op - num_offset, n_numeric_comps, cc.paint.values);
295
code = get_space_object(i_ctx_p, &istate->colorspace[0].array, &space);
298
if (space->validatecomponents) {
299
code = space->validatecomponents(i_ctx_p,
300
&istate->colorspace[0].array,
301
cc.paint.values, n_numeric_comps);
306
/* pass the color to the graphic library */
307
if ((code = gs_setcolor(igs, &cc)) >= 0) {
309
if (n_comps > n_numeric_comps) {
310
istate->pattern[0] = *op; /* save pattern dict or null */
311
n_comps = n_numeric_comps + 1;
315
/* Check the color spaces, to see if we need to run any tint transform
316
* procedures. Some Adobe applications *eg Photoshop) expect that the
317
* tint transform will be run and use this to set up duotone DeviceN
320
code = validate_spaces(i_ctx_p, &istate->colorspace[0].array, &depth);
323
/* Set up for the continuation procedure which will do the work */
324
/* Make sure the exec stack has enough space */
326
/* A place holder for data potentially used by transform functions */
329
/* Store the 'depth' of the space returned during checking above */
332
/* Store the 'stage' of processing (initially 0) */
335
/* Store a pointer to the color space stored on the operand stack
336
* as the stack may grow unpredictably making further access
337
* to the space difficult
340
*ep = istate->colorspace[0].array;
341
/* Finally, the actual continuation routine */
342
push_op_estack(setcolor_cont);
343
return o_push_estack;
346
/* This is used to detect color space changes due
347
to the changing of UseCIEColor during transparency
348
soft mask processing */
350
static bool name_is_device_color( char *cs_name )
353
return( strcmp(cs_name, "DeviceGray") == 0 ||
354
strcmp(cs_name, "DeviceRGB") == 0 ||
355
strcmp(cs_name, "DeviceCMYK") == 0);
361
* Given two color space arrays, attempts to determine if they are the
362
* same space by comparing their contents recursively. For some spaces,
363
* especially CIE based color spaces, it can significantly improve
364
* performance if the same space is frequently re-used.
366
static int is_same_colorspace(i_ctx_t * i_ctx_p, ref *space1, ref *space2, bool isCIE)
368
PS_colour_space_t *oldcspace = 0, *newcspace = 0;
369
ref oldspace, *poldspace = &oldspace, newspace, *pnewspace = &newspace;
372
/* Silence compiler warnings */
373
oldspace.tas.type_attrs = 0;
374
oldspace.tas.type_attrs = 0;
376
ref_assign(pnewspace, space1);
377
ref_assign(poldspace, space2);
380
if (r_type(poldspace) != r_type(pnewspace))
383
code = get_space_object(i_ctx_p, poldspace, &oldcspace);
387
code = get_space_object(i_ctx_p, pnewspace, &newcspace);
391
/* Check the two color space types are the same
392
* (Indexed, Separation, DeviceCMYK etc).
394
if (strcmp(oldcspace->name, newcspace->name) != 0)
397
/* Call the space-specific comparison routine */
398
if (!oldcspace->compareproc(i_ctx_p, poldspace, pnewspace))
401
/* See if current space is CIE based (which could happen
402
if UseCIE had been true previously), but UseCIE is false
403
and incoming space is device based. This can occur
404
when we are now processing a soft mask, which should not
405
use the UseCIEColor option.
407
Need to detect this case at both transitions
409
Device Color UseCIEColor true
411
Device color UseCIEColor false
413
Device color UseCIEColor true
416
if ( name_is_device_color(newcspace->name) ){
417
if ( gs_color_space_is_CIE(gs_currentcolorspace_inline(i_ctx_p->pgs)) ){
418
if ( !isCIE ) return 0; /* The color spaces will be different */
420
if ( isCIE ) return 0; /* The color spaces will be different */
424
/* The current space is OK, if there is no alternate, then that's
427
if (!oldcspace->alternateproc)
430
/* Otherwise, retrieve the alternate space for each, and continue
431
* round the loop, checking those.
433
code = oldcspace->alternateproc(i_ctx_p, poldspace, &poldspace, &CIESubst);
437
code = newcspace->alternateproc(i_ctx_p, pnewspace, &pnewspace, &CIESubst);
449
* <array> setcolorspace -
451
* Set the nominal color space. This color space will be pushd by the
452
* currentcolorspace operator, but is not directly used to pass color
453
* space information to the graphic library.
457
zsetcolorspace(i_ctx_t * i_ctx_p)
464
/* Make sure we have an operand... */
466
/* Check its either a name (base space) or an array */
467
if (!r_has_type(op, t_name))
469
return_error(e_typecheck);
471
code = validate_spaces(i_ctx_p, op, &depth);
475
is_CIE = istate->use_cie_color.value.boolval;
477
/* See if its the same as the current space */
478
if (is_same_colorspace(i_ctx_p, op, &istate->colorspace[0].array, is_CIE)) {
479
PS_colour_space_t *cspace;
481
/* Even if its the same space, we still need to set the correct
482
* initial color value.
484
code = get_space_object(i_ctx_p, &istate->colorspace[0].array, &cspace);
487
if (cspace->initialcolorproc) {
488
cspace->initialcolorproc(i_ctx_p, &istate->colorspace[0].array);
490
/* Pop the space off the stack */
494
/* Set up for the continuation procedure which will do the work */
495
/* Make sure the exec stack has enough space */
497
/* Store the initial value of CIE substitution (not substituting) */
500
/* Store the 'depth' of the space returned during checking above */
503
/* Store the 'stage' of processing (initially 0) */
506
/* Store a pointer to the color space stored on the operand stack
507
* as the stack may grow unpredictably making further access
508
* to the space difficult
512
/* Finally, the actual continuation routine */
513
push_op_estack(setcolorspace_cont);
514
return o_push_estack;
518
* A special version of the setcolorspace operation above. This sets the
519
* CIE substitution flag to true before starting, which prevents any further
520
* CIE substitution taking place.
523
setcolorspace_nosubst(i_ctx_t * i_ctx_p)
529
/* Make sure we have an operand... */
531
/* Check its either a name (base space) or an array */
532
if (!r_has_type(op, t_name))
534
return_error(e_typecheck);
536
code = validate_spaces(i_ctx_p, op, &depth);
540
/* Set up for the continuation procedure which will do the work */
541
/* Make sure the exec stack has enough space */
543
/* Store the initial value of CIE substitution (substituting) */
546
/* Store the 'depth' of the space returned during checking above */
549
/* Store the 'stage' of processing (initially 0) */
552
/* Store a pointer to the color space stored on the operand stack
553
* as the stack may grow unpredictably making further access
554
* to the space difficult
558
/* Finally, the actual continuation routine */
559
push_op_estack(setcolorspace_cont);
560
return o_push_estack;
564
* <name> .includecolorspace -
566
* See the comment for gs_includecolorspace in gscolor2.c .
569
zincludecolorspace(i_ctx_t * i_ctx_p)
575
check_type(*op, t_name);
576
name_string_ref(imemory, op, &nsref);
577
code = gs_includecolorspace(igs, nsref.value.const_bytes, r_size(&nsref));
583
/* - currenttransfer <proc> */
585
zcurrenttransfer(i_ctx_t *i_ctx_p)
590
*op = istate->transfer_procs.gray;
595
* - processcolors <int> -
597
* Note: this is an undocumented operator that is not supported
601
zprocesscolors(i_ctx_t * i_ctx_p)
606
make_int(op, gs_currentdevice(igs)->color_info.num_components);
610
/* <proc> settransfer - */
612
zsettransfer(i_ctx_t * i_ctx_p)
618
check_ostack(zcolor_remap_one_ostack - 1);
619
check_estack(1 + zcolor_remap_one_estack);
620
istate->transfer_procs.red =
621
istate->transfer_procs.green =
622
istate->transfer_procs.blue =
623
istate->transfer_procs.gray = *op;
624
if ((code = gs_settransfer_remap(igs, gs_mapped_transfer, false)) < 0)
626
push_op_estack(zcolor_reset_transfer);
628
return zcolor_remap_one( i_ctx_p,
629
&istate->transfer_procs.gray,
630
igs->set_transfer.gray,
632
zcolor_remap_one_finish );
641
* Prepare to remap one color component (also used for black generation
642
* and undercolor removal). Use the 'for' operator to gather the values.
643
* The caller must have done the necessary check_ostack and check_estack.
649
gx_transfer_map * pmap,
650
const gs_state * pgs,
651
op_proc_t finish_proc )
656
* Detect the identity function, which is a common value for one or
657
* more of these functions.
659
if (r_size(pproc) == 0) {
660
gx_set_identity_transfer(pmap);
662
* Even though we don't actually push anything on the e-stack, all
663
* clients do, so we return o_push_estack in this case. This is
664
* needed so that clients' finishing procedures will get run.
666
return o_push_estack;
669
make_real(op - 3, 0);
670
make_int(op - 2, transfer_map_size - 1);
671
make_real(op - 1, 1);
674
make_struct(esp, imemory_space((gs_ref_memory_t *) pgs->memory),
676
push_op_estack(finish_proc);
677
push_op_estack(zfor_samples);
678
return o_push_estack;
681
/* Store the result of remapping a component. */
683
zcolor_remap_one_store(i_ctx_t *i_ctx_p, floatp min_value)
686
gx_transfer_map *pmap = r_ptr(esp, gx_transfer_map);
688
if (ref_stack_count(&o_stack) < transfer_map_size)
689
return_error(e_stackunderflow);
690
for (i = 0; i < transfer_map_size; i++) {
693
real_param(ref_stack_index(&o_stack, transfer_map_size - 1 - i),
699
(v < min_value ? float2frac(min_value) :
703
ref_stack_pop(&o_stack, transfer_map_size);
704
esp--; /* pop pointer to transfer map */
708
zcolor_remap_one_finish(i_ctx_t *i_ctx_p)
710
return zcolor_remap_one_store(i_ctx_p, 0.0);
713
zcolor_remap_one_signed_finish(i_ctx_t *i_ctx_p)
715
return zcolor_remap_one_store(i_ctx_p, -1.0);
718
/* Finally, reset the effective transfer functions and */
719
/* invalidate the current color. */
721
zcolor_reset_transfer(i_ctx_t *i_ctx_p)
723
gx_set_effective_transfer(igs);
724
return zcolor_remap_color(i_ctx_p);
727
zcolor_remap_color(i_ctx_t *i_ctx_p)
729
/* Remap both colors. This should never hurt. */
731
gx_unset_dev_color(igs);
733
gx_unset_dev_color(igs);
738
* <param1> ... <paramN> .color_test <param1> ... <paramN>
740
* encode and decode color to allow mapping to be tested.
743
zcolor_test(i_ctx_t *i_ctx_p)
745
gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
746
gx_device *dev = gs_currentdevice(igs);
747
int ncomp = dev->color_info.num_components;
748
gx_color_index color;
749
os_ptr op = osp - (ncomp-1);
751
if (ref_stack_count(&o_stack) < ncomp)
752
return_error(e_stackunderflow);
753
for (i = 0; i < ncomp; i++) {
754
if (r_has_type(op+i, t_real))
755
cv[i] = (gx_color_value)
756
(op[i].value.realval * gx_max_color_value);
757
else if (r_has_type(op+i, t_integer))
758
cv[i] = (gx_color_value)
759
(op[i].value.intval * gx_max_color_value);
761
return_error(e_typecheck);
763
color = (*dev_proc(dev, encode_color)) (dev, cv);
764
(*dev_proc(dev, decode_color)) (dev, color, cv);
765
for (i = 0; i < ncomp; i++)
766
make_real(op+i, (float)cv[i] / (float)gx_max_color_value);
771
* <levels> .color_test_all <value0> ... <valueN>
773
* Test encode/decode color procedures for a range of values.
774
* Return value with the worst error in a single component.
777
zcolor_test_all(i_ctx_t *i_ctx_p)
780
gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
781
gx_color_value cvout[GX_DEVICE_COLOR_MAX_COMPONENTS];
782
gx_color_value cvbad[GX_DEVICE_COLOR_MAX_COMPONENTS];
783
int counter[GX_DEVICE_COLOR_MAX_COMPONENTS];
784
gx_device *dev = gs_currentdevice(igs);
785
int ncomp = dev->color_info.num_components;
789
int acceptable_error;
790
int linsep = dev->color_info.separable_and_linear == GX_CINFO_SEP_LIN;
791
int linsepfailed = 0;
793
gx_color_index color, lscolor;
798
acceptable_error = gx_max_color_value / dev->color_info.max_gray + 1;
800
acceptable_error = gx_max_color_value / dev->color_info.max_color + 1;
802
if (ref_stack_count(&o_stack) < 1)
803
return_error(e_stackunderflow);
804
if (!r_has_type(&osp[0], t_integer))
805
return_error(e_typecheck);
806
steps = osp[0].value.intval;
807
for (i = 0; i < ncomp; i++) {
812
dprintf1("Number of components = %d\n", ncomp);
813
dprintf1("Depth = %d\n", dev->color_info.depth);
814
dprintf2("max_gray = %d dither_grays = %d\n",
815
dev->color_info.max_gray, dev->color_info.dither_grays);
816
dprintf2("max_color = %d dither_colors = %d\n",
817
dev->color_info.max_color, dev->color_info.dither_colors);
818
dprintf1("polarity = %s\n",
819
dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE ? "Additive" :
820
dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE ?"Subtractive":
822
/* Indicate color index value with all colorants = zero */
823
for (i = 0; i < ncomp; i++)
825
color = (*dev_proc(dev, encode_color)) (dev, cv);
826
if (sizeof(color) <= sizeof(ulong))
827
dprintf1("Zero color index: %8lx\n", (ulong)color);
829
dprintf2("Zero color index: %8lx%08lx\n",
830
(ulong)(color >> 8*(sizeof(color) - sizeof(ulong))), (ulong)color);
832
dprintf1("separable_and_linear = %s\n",
833
linsep == GX_CINFO_SEP_LIN_NONE ? "No" :
834
linsep == GX_CINFO_SEP_LIN ? "Yes" :
836
if (dev->color_info.gray_index == GX_CINFO_COMP_INDEX_UNKNOWN)
837
dprintf("gray_index is unknown\n");
839
dprintf1("gray_index = %d\n", dev->color_info.gray_index);
841
dprintf(" Shift Mask Bits\n");
842
for (i = 0; i < ncomp; i++) {
843
dprintf3(" %5d %8x %4d\n",
844
(int)(dev->color_info.comp_shift[i]),
845
(int)(dev->color_info.comp_mask[i]),
846
(int)(dev->color_info.comp_bits[i]));
851
for (j = 0; j <= steps; j++) {
852
for (i = 0; i < ncomp; i++)
853
cv[i] = counter[i] * gx_max_color_value / steps;
854
color = (*dev_proc(dev, encode_color)) (dev, cv);
856
/* Derive it the other way */
857
lscolor = gx_default_encode_color(dev, cv);
858
if ((color != lscolor) && (linsepfailed < 5)) {
860
dprintf("Failed separable_and_linear for");
861
for (i = 0; i < ncomp; i++)
862
dprintf1(" %d", cv[i]);
864
dprintf2("encode_color=%x gx_default_encode_color=%x\n",
865
(int)color, (int)lscolor);
868
(*dev_proc(dev, decode_color)) (dev, color, cvout);
869
for (i = 0; i < ncomp; i++) {
870
err = (int)cvout[i] - (int)cv[i];
873
if (err > maxerror) {
875
for (k=0; k < ncomp; k++)
880
gx_default_decode_color(dev, color, cvout);
881
for (i = 0; i < ncomp; i++) {
882
err = (int)cvout[i] - (int)cv[i];
885
if (err > lsmaxerror) {
896
if (counter[i] > steps) {
907
dprintf2("Maximum error %g %s\n",
908
(float)maxerror / (float)gx_max_color_value,
909
maxerror <= acceptable_error ? "is Ok" :
910
maxerror <= 3*acceptable_error/2 ? "is POOR" : "FAILED");
913
dprintf2("Maximum linear_and_separable error %g %s\n",
914
(float)lsmaxerror / (float)gx_max_color_value,
915
lsmaxerror <= acceptable_error ? "is Ok" :
916
lsmaxerror <= 3*acceptable_error/2 ? "is POOR" : "FAILED");
918
/* push worst value */
921
for (i = 0; i < ncomp; i++)
922
make_real(op+i, (float)cvbad[i] / (float)gx_max_color_value);
927
/* Convert between RGB and HSB colors, using the hexcone approach (see
928
* Rogers, David, "Procedureal Elements For Computer Graphics",
929
* (McGraw-Hill, 1985), pp. 402 - 3).
931
* The rgb ==> hsb calculation is:
942
* h = (g - b) / (6 * diff) + (b > g ? 1 : 0);
944
* h = 1/3 + (b - r) / (6 * diff);
946
* h = 2/3 + (r - g) / (6 * diff);
949
static int rgb2hsb(float *RGB)
951
float HSB[3], v, diff;
958
if (RGB[i] > HSB[2]) {
967
HSB[1] = diff / HSB[2];
969
case 0 : /* R == Brightness */
970
/* diff can only be zero if r == br, so we need to make sure here we
971
* don't divide by zero
974
HSB[0] = ((RGB[1] - RGB[2]) / (6.0 * diff)) + (RGB[2] > RGB[1] ? 1.0 : 0.0);
976
HSB[0] = (RGB[1] - RGB[2]) + (RGB[2] > RGB[1] ? 1.0 : 0.0);
978
case 1 : /* G == Brightness */
979
HSB[0] = (1.0 / 3.0) + (RGB[2] - RGB[0]) / (6.0 * diff);
981
case 2 : /* B == Brightness */
982
HSB[0] = (2.0 / 3.0) + (RGB[0] - RGB[1]) / (6.0 * diff);
995
/* The hsb ==> rgb conversion is:
997
* mn = (1 - s) * br, md = 6 * s * br;
999
* switch ((int)floor(6 * h)) {
1000
* case 0: %% r >= g >= b
1006
* case 1: %% g >= r >= b
1007
* r = mn + md * (1/3 - h);
1012
* case 2: %% g >= b >= r
1015
* b = mn + (h - 1/3) * md;
1018
* case 3: %% b >= g >= r
1020
* g = mn + (2/3 - h) * md;
1024
* case 4: %% b >= r >= g
1025
* r = mn + (h - 2/3) * md;
1030
* case 5: %% r >= b >= g
1033
* b = mn + (1 - h) * md;
1036
* case 6: %% We have wrapped around the hexcone. Thus this case is
1037
* the same as case 0 with h = 0
1040
* g = mn + h * md = mn;
1045
static int hsb2rgb(float *HSB)
1047
float RGB[3], mn, md;
1050
mn = (1.0 - HSB[1]) * HSB[2];
1051
md = 6.0 * HSB[1] * HSB[2];
1053
switch ((int)floor(6.0 * HSB[0])) {
1056
default: /* Shuts up compiler warning about RGB being uninited */
1059
RGB[1] = mn + (HSB[0] * md);
1063
RGB[0] = mn + (md * ((1.0 / 3.0) - HSB[0]));
1070
RGB[2] = mn + ((HSB[0] - (1.0 / 3.0)) * md);
1074
RGB[1] = mn + (((2.0 / 3.0f) - HSB[0]) * md);
1078
RGB[0] = mn + ((HSB[0] - (2.0 / 3.0)) * md);
1085
RGB[2] = mn + ((1.0 - HSB[0]) * md);
1098
/* The routines for handling colors and color spaces, moved from
1099
* PostScript to C, start here.
1103
static int setgrayspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
1106
gs_color_space *pcs;
1113
if (istate->use_cie_color.value.boolval && !CIESubst) {
1117
code = dict_find_string(systemdict, "NOSUBSTDEVICECOLORS", &nosubst);
1120
if (!r_has_type(nosubst, t_boolean))
1121
return_error(e_typecheck);
1122
if (nosubst->value.boolval) {
1125
body = ialloc_string(32, "string");
1127
return_error(e_VMerror);
1128
memcpy(body, "/DefaultGray ..nosubstdevicetest",32);
1129
make_string(&stref, a_all | icurrent_space, 32, body);
1130
r_set_attrs(&stref, a_executable);
1132
ref_assign(esp, &stref);
1133
return o_push_estack;
1137
body = ialloc_string(47, "string");
1139
return_error(e_VMerror);
1140
memcpy(body, "{/DefaultGray /ColorSpace findresource} stopped",47);
1141
make_string(&stref, a_all | icurrent_space, 47, body);
1142
r_set_attrs(&stref, a_executable);
1144
ref_assign(esp, &stref);
1145
return o_push_estack;
1151
pcs = gs_cspace_new_DeviceGray(imemory);
1153
return_error(e_VMerror);
1154
code = gs_setcolorspace(igs, pcs);
1156
gs_client_color *pcc = gs_currentcolor_inline(igs);
1158
cs_adjust_color_count(igs, -1); /* not strictly necessary */
1159
pcc->paint.values[0] = (0);
1160
pcc->pattern = 0; /* for GC */
1161
gx_unset_dev_color(igs);
1163
rc_decrement_only_cs(pcs, "zsetdevcspace");
1168
if (!r_has_type(op, t_boolean))
1169
return_error(e_typecheck);
1170
if (op->value.boolval) {
1171
/* Failed to find the /DefaultGray CSA, so give up and
1172
* just use DeviceGray
1181
code = setcolorspace_nosubst(i_ctx_p);
1186
/* We end up here after setting the DefaultGray space
1187
* We've finished setting the gray color space, so we
1194
/* We come here if /UseCIEColor is true, and NOSUBSTDEVICECOLORS
1195
* is also true. We will have a boolean on the stack, if its true
1196
* then we need to set the space (also on the stack), invoke
1197
* .includecolorspace, and set /DeviceGray, otherwise we just need
1198
* to set DeviceGray. See gs_cspace.ps.
1200
if (!r_has_type(op, t_boolean))
1201
return_error(e_typecheck);
1205
if (op->value.boolval) {
1207
code = setcolorspace_nosubst(i_ctx_p);
1213
/* After stage 4 above, if we had to set a color space, we come
1214
* here. Now we need to use .includecolorspace to register the space
1215
* with any high-level devices which want it.
1219
code = zincludecolorspace(i_ctx_p);
1227
static int graydomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
1233
static int grayrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
1239
/* This routine converts a Gray value into its equivalent in a different
1240
* device space, required by currentgray, currentrgb, currenthsb and
1241
* currentcmyk. The actual color value will have been processed through
1242
* the tint transform(s) of the parent space(s) until it reaches a device
1243
* space. This converts that final value into the requested space.
1245
static int graybasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth)
1253
if (!r_has_type(op, t_integer)) {
1254
if (r_has_type(op, t_real)) {
1255
Gray = op->value.realval;
1257
return_error(e_typecheck);
1259
Gray = (float)op->value.intval;
1261
if (Gray < 0 || Gray > 1)
1262
return_error(e_rangecheck);
1266
/* Requested space is DeviceGray, just use the value */
1267
make_real(op, Gray);
1270
/* Requested space is HSB */
1272
/* Requested space is RGB, set all the components
1276
RGB[0] = RGB[1] = RGB[2] = Gray;
1278
/* If the requested space is HSB, convert the RGB to HSB */
1279
rgb2hsb((float *)&RGB);
1280
make_real(&op[-2], RGB[0]);
1281
make_real(&op[-1], RGB[1]);
1282
make_real(op, RGB[2]);
1285
/* Requested space is CMYK, use the gray value to set the
1289
make_real(&op[-3], (float)0);
1290
make_real(&op[-2], (float)0);
1291
make_real(&op[-1], (float)0);
1292
make_real(op, (float)1.0 - Gray);
1295
return_error(e_undefined);
1299
static int grayvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
1303
if (!r_has_type(op, t_integer) && !r_has_type(op, t_real))
1304
return_error(e_typecheck);
1307
return_error(e_stackunderflow);
1317
static int grayinitialproc(i_ctx_t *i_ctx_p, ref *space)
1322
cc.paint.values[0] = 0;
1323
return gs_setcolor(igs, &cc);
1327
static int setrgbspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
1330
gs_color_space *pcs;
1337
if (istate->use_cie_color.value.boolval && !CIESubst) {
1341
code = dict_find_string(systemdict, "NOSUBSTDEVICECOLORS", &nosubst);
1344
if (!r_has_type(nosubst, t_boolean))
1345
return_error(e_typecheck);
1346
if (nosubst->value.boolval) {
1349
body = ialloc_string(31, "string");
1351
return_error(e_VMerror);
1352
memcpy(body, "/DefaultRGB ..nosubstdevicetest",31);
1353
make_string(&stref, a_all | icurrent_space, 31, body);
1354
r_set_attrs(&stref, a_executable);
1356
ref_assign(esp, &stref);
1357
return o_push_estack;
1361
body = ialloc_string(46, "string");
1363
return_error(e_VMerror);
1364
memcpy(body, "{/DefaultRGB /ColorSpace findresource} stopped", 46);
1365
make_string(&stref, a_all | icurrent_space, 46, body);
1366
r_set_attrs(&stref, a_executable);
1368
ref_assign(esp, &stref);
1369
return o_push_estack;
1374
pcs = gs_cspace_new_DeviceRGB(imemory);
1376
return_error(e_VMerror);
1377
code = gs_setcolorspace(igs, pcs);
1379
gs_client_color *pcc = gs_currentcolor_inline(igs);
1381
cs_adjust_color_count(igs, -1); /* not strictly necessary */
1382
pcc->paint.values[0] = 0;
1383
pcc->paint.values[1] = 0;
1384
pcc->paint.values[2] = 0;
1385
pcc->pattern = 0; /* for GC */
1386
gx_unset_dev_color(igs);
1388
rc_decrement_only_cs(pcs, "zsetdevcspace");
1393
if (!r_has_type(op, t_boolean))
1394
return_error(e_typecheck);
1395
if (op->value.boolval) {
1396
/* Failed to find the /DefaultRGB CSA, so give up and
1397
* just use DeviceRGB
1405
code = setcolorspace_nosubst(i_ctx_p);
1410
/* We end up here after setting the DefaultGray CIE space
1411
* We've finished setting the gray color space, so we
1418
/* We come here if /UseCIEColor is true, and NOSUBSTDEVICECOLORS
1419
* is also true. We will have a boolean on the stack, if its true
1420
* then we need to set the space (also on the stack), invoke
1421
* .includecolorspace, and set /DeviceGray, otherwise we just need
1422
* to set DeviceGray. See gs-cspace.ps.
1424
if (!r_has_type(op, t_boolean))
1425
return_error(e_typecheck);
1429
if (op->value.boolval) {
1431
code = setcolorspace_nosubst(i_ctx_p);
1437
/* After stage 4 above, if we had to set a color space, we come
1438
* here. Now we need to use .includecolorspace to register the space
1439
* with any high-level devices which want it.
1443
code = zincludecolorspace(i_ctx_p);
1451
static int rgbdomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
1455
for (i = 0;i < 6;i+=2) {
1461
static int rgbrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
1465
for (i = 0;i < 6;i+=2) {
1471
/* This routine converts an RGB value into its equivalent in a different
1472
* device space, required by currentgray, currentrgb, currenthsb and
1473
* currentcmyk. The actual color value will have been processed through
1474
* the tint transform(s) of the parent space(s) until it reaches a device
1475
* space. This converts that final value into the requested space.
1477
static int rgbbasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth)
1480
float RGB[3], CMYK[4], Gray, UCR, BG;
1489
if (!r_has_type(op, t_integer)) {
1490
if (r_has_type(op, t_real)) {
1491
RGB[i] = op->value.realval;
1493
return_error(e_typecheck);
1495
RGB[i] = (float)op->value.intval;
1496
if (RGB[i] < 0 || RGB[i] > 1)
1497
return_error(e_rangecheck);
1506
/* If R == G == B, then this is gray, so just use it. Avoids
1509
if (RGB[0] == RGB[1] && RGB[1] == RGB[2])
1512
Gray = (0.3 * RGB[0]) + (0.59 * RGB[1]) + (0.11 * RGB[2]);
1513
make_real(op, Gray);
1517
rgb2hsb((float *)&RGB);
1518
make_real(&op[-2], RGB[0]);
1519
make_real(&op[-1], RGB[1]);
1520
make_real(op, RGB[2]);
1524
make_real(&op[-2], RGB[0]);
1525
make_real(&op[-1], RGB[1]);
1526
make_real(op, RGB[2]);
1533
CMYK[i] = 1 - RGB[i];
1534
if (CMYK[0] < CMYK[1]) {
1535
if (CMYK[0] < CMYK[2])
1540
if (CMYK[1] < CMYK[2])
1549
make_real(op, CMYK[i]);
1552
make_real(op, CMYK[3]);
1554
*esp = istate->undercolor_removal;
1555
return o_push_estack;
1558
return_error(e_undefined);
1569
if (!r_has_type(op, t_integer)) {
1570
if (r_has_type(op, t_real)) {
1571
CMYK[i] = op->value.realval;
1573
return_error(e_typecheck);
1575
CMYK[i] = (float)op->value.intval;
1578
if (!r_has_type(op, t_integer)) {
1579
if (r_has_type(op, t_real)) {
1580
UCR = op->value.realval;
1582
return_error(e_typecheck);
1584
UCR = (float)op->value.intval;
1586
CMYK[i] = CMYK[i] - UCR;
1594
make_real(op, CMYK[i]);
1597
make_real(op, CMYK[3]);
1599
*esp = istate->black_generation;
1600
return o_push_estack;
1606
if (!r_has_type(op, t_integer)) {
1607
if (r_has_type(op, t_real)) {
1608
BG = op->value.realval;
1610
return_error(e_typecheck);
1612
BG = (float)op->value.intval;
1624
static int rgbvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
1630
return_error(e_stackunderflow);
1634
if (!r_has_type(op, t_integer) && !r_has_type(op, t_real))
1635
return_error(e_typecheck);
1639
for (i=0;i < 3; i++) {
1640
if (values[i] > 1.0)
1643
if (values[i] < 0.0)
1649
static int rgbinitialproc(i_ctx_t *i_ctx_p, ref *space)
1654
cc.paint.values[0] = 0;
1655
cc.paint.values[1] = 0;
1656
cc.paint.values[2] = 0;
1657
return gs_setcolor(igs, &cc);
1661
static int setcmykspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
1664
gs_color_space *pcs;
1671
if (istate->use_cie_color.value.boolval && !CIESubst) {
1675
code = dict_find_string(systemdict, "NOSUBSTDEVICECOLORS", &nosubst);
1678
if (!r_has_type(nosubst, t_boolean))
1679
return_error(e_typecheck);
1680
if (nosubst->value.boolval) {
1683
body = ialloc_string(32, "string");
1685
return_error(e_VMerror);
1686
memcpy(body, "/DefaultCMYK ..nosubstdevicetest",32);
1687
make_string(&stref, a_all | icurrent_space, 32, body);
1688
r_set_attrs(&stref, a_executable);
1690
ref_assign(esp, &stref);
1691
return o_push_estack;
1695
body = ialloc_string(47, "string");
1697
return_error(e_VMerror);
1698
memcpy(body, "{/DefaultCMYK /ColorSpace findresource} stopped", 47);
1699
make_string(&stref, a_all | icurrent_space, 47, body);
1700
r_set_attrs(&stref, a_executable);
1702
ref_assign(esp, &stref);
1703
return o_push_estack;
1708
pcs = gs_cspace_new_DeviceCMYK(imemory);
1710
return_error(e_VMerror);
1711
code = gs_setcolorspace(igs, pcs);
1713
gs_client_color *pcc = gs_currentcolor_inline(igs);
1715
cs_adjust_color_count(igs, -1); /* not strictly necessary */
1716
pcc->paint.values[0] = 0;
1717
pcc->paint.values[1] = 0;
1718
pcc->paint.values[2] = 0;
1719
pcc->paint.values[3] = 1;
1720
pcc->pattern = 0; /* for GC */
1721
gx_unset_dev_color(igs);
1723
rc_decrement_only_cs(pcs, "zsetdevcspace");
1728
if (!r_has_type(op, t_boolean))
1729
return_error(e_typecheck);
1730
if (op->value.boolval) {
1731
/* Failed to find the /DefaultCMYK CSA, so give up and
1732
* just use DeviceCMYK
1740
code = setcolorspace_nosubst(i_ctx_p);
1745
/* We end up here after setting the DefaultGray CIE space
1746
* We've finished setting the gray color space, so we
1753
/* We come here if /UseCIEColor is true, and NOSUBSTDEVICECOLORS
1754
* is also true. We will have a boolean on the stack, if its true
1755
* then we need to set the space (also on the stack), invoke
1756
* .includecolorspace, and set /DeviceGray, otherwise we just need
1757
* to set DeviceGray. See gs-cspace.ps.
1759
if (!r_has_type(op, t_boolean))
1760
return_error(e_typecheck);
1764
if (op->value.boolval) {
1766
code = setcolorspace_nosubst(i_ctx_p);
1772
/* After stage 4 above, if we had to set a color space, we come
1773
* here. Now we need to use .includecolorspace to register the space
1774
* with any high-level devices which want it.
1778
code = zincludecolorspace(i_ctx_p);
1786
static int cmykdomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
1790
for (i = 0;i < 8;i+=2) {
1796
static int cmykrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
1800
for (i = 0;i < 8;i+=2) {
1806
/* This routine converts a CMYK value into its equivalent in a different
1807
* device space, required by currentgray, currentrgb, currenthsb and
1808
* currentcmyk. The actual color value will have been processed through
1809
* the tint transform(s) of the parent space(s) until it reaches a device
1810
* space. This converts that final value into the requested space.
1812
static int cmykbasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth)
1815
float CMYK[4], Gray, RGB[3];
1823
if (!r_has_type(op, t_integer)) {
1824
if (r_has_type(op, t_real)) {
1825
CMYK[i] = op->value.realval;
1827
return_error(e_typecheck);
1829
CMYK[i] = (float)op->value.intval;
1830
if (CMYK[i] < 0 || CMYK[i] > 1)
1831
return_error(e_rangecheck);
1839
Gray = (0.3 * CMYK[0]) + (0.59 * CMYK[1]) + (0.11 * CMYK[2]) + CMYK[3];
1844
make_real(op, Gray);
1850
RGB[0] = 1.0 - (CMYK[0] + CMYK[3]);
1853
RGB[1] = 1.0 - (CMYK[1] + CMYK[3]);
1856
RGB[2] = 1.0 - (CMYK[2] + CMYK[3]);
1860
rgb2hsb((float *)&RGB);
1861
make_real(&op[-2], RGB[0]);
1862
make_real(&op[-1], RGB[1]);
1863
make_real(op, RGB[2]);
1867
make_real(&op[-3], CMYK[0]);
1868
make_real(&op[-2], CMYK[1]);
1869
make_real(&op[-1], CMYK[2]);
1870
make_real(op, CMYK[3]);
1873
return_error(e_undefined);
1877
static int cmykvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
1883
return_error(e_stackunderflow);
1886
for (i=0;i < 4;i++) {
1887
if (!r_has_type(op, t_integer) && !r_has_type(op, t_real))
1888
return_error(e_typecheck);
1892
for (i=0;i < 4; i++) {
1893
if (values[i] > 1.0)
1896
if (values[i] < 0.0)
1902
static int cmykinitialproc(i_ctx_t *i_ctx_p, ref *space)
1907
cc.paint.values[0] = 0;
1908
cc.paint.values[1] = 0;
1909
cc.paint.values[2] = 0;
1910
cc.paint.values[3] = 1;
1911
return gs_setcolor(igs, &cc);
1915
/* A utility routine to check whether two arrays contain the same
1916
* contents. Used to check whether two color spaces are the same
1917
* Note that this can be recursive if the array contains arrays.
1919
static int comparearrays(i_ctx_t * i_ctx_p, ref *m1, ref *m2)
1924
if (r_size(m1) != r_size(m2))
1927
for (i=0;i < r_size(m1);i++) {
1928
code = array_get(imemory, m1, i, &ref1);
1931
code = array_get(imemory, m2, i, &ref2);
1935
if (r_type(&ref1) != r_type(&ref2))
1938
code = r_type(&ref1);
1939
switch(r_type(&ref1)) {
1943
if (ref1.value.boolval != ref2.value.boolval)
1947
if (ref1.value.intval != ref2.value.intval)
1951
if (ref1.value.realval != ref2.value.realval)
1955
if (!name_eq(&ref1, &ref2))
1959
if (r_size(&ref1) != r_size(&ref2))
1961
if (strncmp((const char *)ref1.value.const_bytes, (const char *)ref2.value.const_bytes, r_size(&ref1)) != 0)
1967
if (!comparearrays(i_ctx_p, &ref1, &ref2))
1973
if (ref1.value.opproc != ref2.value.opproc)
1979
case t_unused_array_:
1988
/* Some high frequency operators are defined starting at t_next_index
1989
* I think as long as the 'type' of each is the same, we are OK
1996
/* A utility routine to check whether two dictionaries contain the same
1997
* arrays. This is a simple routine, unlike comparearrays above it is only
1998
* used by the CIE comparison code and expects only to check that the
1999
* dictionary contains an array, and checks the arrays.
2001
static int comparedictkey(i_ctx_t * i_ctx_p, ref *CIEdict1, ref *CIEdict2, char *key)
2004
ref *tempref1, *tempref2;
2006
code = dict_find_string(CIEdict1, key, &tempref1);
2007
code1 = dict_find_string(CIEdict2, key, &tempref2);
2014
if (r_type(tempref1) != r_type(tempref2))
2017
if (r_type(tempref1) == t_null)
2020
return comparearrays(i_ctx_p, tempref1, tempref2);
2023
/* Check that the WhitePoint of a CIE space is valid */
2024
static int checkWhitePoint(i_ctx_t * i_ctx_p, ref *CIEdict)
2028
ref *tempref, valref;
2030
code = dict_find_string(CIEdict, "WhitePoint", &tempref);
2031
if (code < 0 || r_has_type(tempref, t_null))
2034
if (!r_is_array(tempref))
2035
return_error(e_typecheck);
2036
if (r_size(tempref) != 3)
2037
return_error(e_rangecheck);
2040
code = array_get(imemory, tempref, i, &valref);
2043
if (r_has_type(&valref, t_integer))
2044
value[i] = (float)valref.value.intval;
2045
else if (r_has_type(&valref, t_real))
2046
value[i] = (float)valref.value.realval;
2048
return_error(e_typecheck);
2050
/* Xw and Zw must be positive and Yw must be 1 (3rd edition PLRM p230) */
2051
if (value[0] < 0 || value[1] != 1 || value[2] < 0 )
2052
return_error(e_rangecheck);
2056
/* Check that the BlackPoint of a CIE space is valid */
2057
static int checkBlackPoint(i_ctx_t * i_ctx_p, ref *CIEdict)
2061
ref *tempref, valref;
2063
code = dict_find_string(CIEdict, "BlackPoint", &tempref);
2064
if (code >= 0 && !r_has_type(tempref, t_null)) {
2065
if (!r_is_array(tempref))
2066
return_error(e_typecheck);
2067
if (r_size(tempref) != 3)
2068
return_error(e_rangecheck);
2071
code = array_get(imemory, tempref, i, &valref);
2074
if (r_has_type(&valref, t_integer))
2075
value[i] = (float)valref.value.intval;
2076
else if (r_has_type(&valref, t_real))
2077
value[i] = (float)valref.value.realval;
2079
return_error(e_typecheck);
2084
/* Check that the RangeLMN of a CIE space is valid */
2085
static int checkRangeLMN(i_ctx_t * i_ctx_p, ref *CIEdict)
2089
ref *tempref, valref;
2091
code = dict_find_string(CIEdict, "RangeLMN", &tempref);
2092
if (code >= 0 && !r_has_type(tempref, t_null)) {
2093
if (!r_is_array(tempref))
2094
return_error(e_typecheck);
2095
if (r_size(tempref) != 6)
2096
return_error(e_rangecheck);
2099
code = array_get(imemory, tempref, i, &valref);
2102
if (r_has_type(&valref, t_integer))
2103
value[i] = (float)valref.value.intval;
2104
else if (r_has_type(&valref, t_real))
2105
value[i] = (float)valref.value.realval;
2107
return_error(e_typecheck);
2109
if (value[1] < value[0] || value[3] < value[2] || value[5] < value[4])
2110
return_error(e_rangecheck);
2114
/* Check that the DecodeLMN of a CIE space is valid */
2115
static int checkDecodeLMN(i_ctx_t * i_ctx_p, ref *CIEdict)
2118
ref *tempref, valref;
2120
code = dict_find_string(CIEdict, "DecodeLMN", &tempref);
2121
if (code >= 0 && !r_has_type(tempref, t_null)) {
2122
if (!r_is_array(tempref))
2123
return_error(e_typecheck);
2124
if (r_size(tempref) != 3)
2125
return_error(e_rangecheck);
2128
code = array_get(imemory, tempref, i, &valref);
2136
/* Check that the MatrixLMN of a CIE space is valid */
2137
static int checkMatrixLMN(i_ctx_t * i_ctx_p, ref *CIEdict)
2141
ref *tempref, valref;
2143
code = dict_find_string(CIEdict, "MatrixLMN", &tempref);
2144
if (code >= 0 && !r_has_type(tempref, t_null)) {
2145
if (!r_is_array(tempref))
2146
return_error(e_typecheck);
2147
if (r_size(tempref) != 9)
2148
return_error(e_rangecheck);
2151
code = array_get(imemory, tempref, i, &valref);
2154
if (r_has_type(&valref, t_integer))
2155
value[i] = (float)valref.value.intval;
2156
else if (r_has_type(&valref, t_real))
2157
value[i] = (float)valref.value.realval;
2159
return_error(e_typecheck);
2166
static int setcieaspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
2169
ref CIEDict, *nocie;
2172
if (i_ctx_p->language_level < 2)
2173
return_error(e_undefined);
2175
code = dict_find_string(systemdict, "NOCIE", &nocie);
2178
if (!r_has_type(nocie, t_boolean))
2179
return_error(e_typecheck);
2180
if (nocie->value.boolval)
2181
return setgrayspace(i_ctx_p, r, stage, cont, 1);
2184
code = array_get(imemory, r, 1, &CIEDict);
2191
cc.paint.values[0] = 0;
2192
code = gs_setcolor(igs, &cc);
2196
dictkey = r->value.refs->value.saveid;
2197
code = cieaspace(i_ctx_p, &CIEDict, dictkey);
2202
static int validatecieaspace(i_ctx_t * i_ctx_p, ref **r)
2206
ref CIEdict, *CIEspace = *r, *tempref, valref;
2208
if (!r_is_array(CIEspace))
2209
return_error(e_typecheck);
2210
/* Validate parameters, check we have enough operands */
2211
if (r_size(CIEspace) != 2)
2212
return_error(e_rangecheck);
2214
code = array_get(imemory, CIEspace, 1, &CIEdict);
2218
check_read_type(CIEdict, t_dictionary);
2220
/* Check white point exists, and is an array of three numbers */
2221
code = checkWhitePoint(i_ctx_p, &CIEdict);
2225
/* Remaining parameters are optional, but we must validate
2226
* them if they are present
2228
code = dict_find_string(&CIEdict, "RangeA", &tempref);
2229
if (code >= 0 && !r_has_type(tempref, t_null)) {
2230
/* Array of two numbers A0 < A1 */
2231
if (!r_is_array(tempref))
2232
return_error(e_typecheck);
2233
if (r_size(tempref) != 2)
2234
return_error(e_rangecheck);
2237
code = array_get(imemory, tempref, i, &valref);
2240
if (r_has_type(&valref, t_integer))
2241
value[i] = (float)valref.value.intval;
2242
else if (r_has_type(&valref, t_real))
2243
value[i] = (float)valref.value.realval;
2245
return_error(e_typecheck);
2247
if (value[1] < value[0])
2248
return_error(e_rangecheck);
2251
code = dict_find_string(&CIEdict, "DecodeA", &tempref);
2252
if (code >= 0 && !r_has_type(tempref, t_null)) {
2253
check_proc(*tempref);
2256
code = dict_find_string(&CIEdict, "MatrixA", &tempref);
2257
if (code >= 0 && !r_has_type(tempref, t_null)) {
2258
if (!r_is_array(tempref))
2259
return_error(e_typecheck);
2260
if (r_size(tempref) != 3)
2261
return_error(e_rangecheck);
2264
code = array_get(imemory, tempref, i, &valref);
2267
if (r_has_type(&valref, t_integer))
2268
value[i] = (float)valref.value.intval;
2269
else if (r_has_type(&valref, t_real))
2270
value[i] = (float)valref.value.realval;
2272
return_error(e_typecheck);
2276
code = checkRangeLMN(i_ctx_p, &CIEdict);
2280
code = checkDecodeLMN(i_ctx_p, &CIEdict);
2284
code = checkMatrixLMN(i_ctx_p, &CIEdict);
2288
code = checkBlackPoint(i_ctx_p, &CIEdict);
2295
static int cieadomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
2298
ref CIEdict, *tempref, valref;
2300
code = array_get(imemory, space, 1, &CIEdict);
2304
/* If we have a RangeA entry in the dictionary, get the
2307
code = dict_find_string(&CIEdict, "RangeA", &tempref);
2308
if (code >= 0 && !r_has_type(tempref, t_null)) {
2310
code = array_get(imemory, tempref, i, &valref);
2313
if (r_has_type(&valref, t_integer))
2314
ptr[i] = (float)valref.value.intval;
2315
else if (r_has_type(&valref, t_real))
2316
ptr[i] = (float)valref.value.realval;
2318
return_error(e_typecheck);
2321
/* Default values for CIEBasedA */
2327
static int ciearange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
2330
ref CIEdict, *tempref, valref;
2332
code = array_get(imemory, space, 1, &CIEdict);
2336
/* If we have a RangeA entry in the dictionary, get the
2339
code = dict_find_string(&CIEdict, "RangeA", &tempref);
2340
if (code >= 0 && !r_has_type(tempref, t_null)) {
2342
code = array_get(imemory, tempref, i, &valref);
2345
if (r_has_type(&valref, t_integer))
2346
ptr[i] = (float)valref.value.intval;
2347
else if (r_has_type(&valref, t_real))
2348
ptr[i] = (float)valref.value.realval;
2350
return_error(e_typecheck);
2353
/* Default values for CIEBasedA */
2359
static int cieavalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
2364
return_error(e_stackunderflow);
2366
if (!r_has_type(op, t_integer) && !r_has_type(op, t_real))
2367
return_error(e_typecheck);
2371
static int cieacompareproc(i_ctx_t *i_ctx_p, ref *space, ref *testspace)
2374
ref CIEdict1, CIEdict2;
2376
code = array_get(imemory, space, 1, &CIEdict1);
2379
code = array_get(imemory, testspace, 1, &CIEdict2);
2382
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"WhitePoint"))
2384
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"BlackPoint"))
2386
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeA"))
2388
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"DecodeA"))
2390
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"MatrixA"))
2392
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeLMN"))
2394
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"DecodeLMN"))
2396
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"MatrixMN"))
2402
static int setcieabcspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
2405
ref CIEDict, *nocie;
2408
if (i_ctx_p->language_level < 2)
2409
return_error(e_undefined);
2411
code = dict_find_string(systemdict, "NOCIE", &nocie);
2414
if (!r_has_type(nocie, t_boolean))
2415
return_error(e_typecheck);
2416
if (nocie->value.boolval)
2417
return setrgbspace(i_ctx_p, r, stage, cont, 1);
2420
code = array_get(imemory, r, 1, &CIEDict);
2430
cc.paint.values[i] = 0;
2431
code = gs_setcolor(igs, &cc);
2435
dictkey = r->value.refs->value.saveid;
2436
code = cieabcspace(i_ctx_p, &CIEDict,dictkey);
2441
static int validatecieabcspace(i_ctx_t * i_ctx_p, ref **r)
2445
ref CIEdict, *CIEspace = *r, *tempref, valref;
2447
if (!r_is_array(CIEspace))
2448
return_error(e_typecheck);
2449
/* Validate parameters, check we have enough operands */
2450
if (r_size(CIEspace) != 2)
2451
return_error(e_rangecheck);
2453
code = array_get(imemory, CIEspace, 1, &CIEdict);
2456
check_read_type(CIEdict, t_dictionary);
2458
/* Check white point exists, and is an array of three numbers */
2459
code = checkWhitePoint(i_ctx_p, &CIEdict);
2463
/* Remaining parameters are optional, but we must validate
2464
* them if they are present
2466
code = dict_find_string(&CIEdict, "RangeABC", &tempref);
2467
if (code >= 0 && !r_has_type(tempref, t_null)) {
2468
if (!r_is_array(tempref))
2469
return_error(e_typecheck);
2470
if (r_size(tempref) != 6)
2471
return_error(e_rangecheck);
2474
code = array_get(imemory, tempref, i, &valref);
2477
if (r_has_type(&valref, t_integer))
2478
value[i] = (float)valref.value.intval;
2479
else if (r_has_type(&valref, t_real))
2480
value[i] = (float)valref.value.realval;
2482
return_error(e_typecheck);
2484
if (value[1] < value[0] || value[3] < value[2] || value[5] < value[4])
2485
return_error(e_rangecheck);
2488
code = dict_find_string(&CIEdict, "DecodeABC", &tempref);
2489
if (code >= 0 && !r_has_type(tempref, t_null)) {
2490
if (!r_is_array(tempref))
2491
return_error(e_typecheck);
2492
if (r_size(tempref) != 3)
2493
return_error(e_rangecheck);
2496
code = array_get(imemory, tempref, i, &valref);
2503
code = dict_find_string(&CIEdict, "MatrixABC", &tempref);
2504
if (code >= 0 && !r_has_type(tempref, t_null)) {
2505
if (!r_is_array(tempref))
2506
return_error(e_typecheck);
2507
if (r_size(tempref) != 9)
2508
return_error(e_rangecheck);
2511
code = array_get(imemory, tempref, i, &valref);
2514
if (r_has_type(&valref, t_integer))
2515
value[i] = (float)valref.value.intval;
2516
else if (r_has_type(&valref, t_real))
2517
value[i] = (float)valref.value.realval;
2519
return_error(e_typecheck);
2524
code = checkRangeLMN(i_ctx_p, &CIEdict);
2528
code = checkDecodeLMN(i_ctx_p, &CIEdict);
2532
code = checkMatrixLMN(i_ctx_p, &CIEdict);
2536
code = checkBlackPoint(i_ctx_p, &CIEdict);
2543
static int cieabcdomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
2546
ref CIEdict, *tempref, valref;
2548
code = array_get(imemory, space, 1, &CIEdict);
2552
/* If we have a RangeABC, get the values from that */
2553
code = dict_find_string(&CIEdict, "RangeABC", &tempref);
2554
if (code >= 0 && !r_has_type(tempref, t_null)) {
2556
code = array_get(imemory, tempref, i, &valref);
2559
if (r_has_type(&valref, t_integer))
2560
ptr[i] = (float)valref.value.intval;
2561
else if (r_has_type(&valref, t_real))
2562
ptr[i] = (float)valref.value.realval;
2564
return_error(e_typecheck);
2567
/* Default values for CIEBasedABC */
2570
ptr[(2 * i) + 1] = 1;
2575
static int cieabcrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
2578
ref CIEdict, *tempref, valref;
2580
code = array_get(imemory, space, 1, &CIEdict);
2584
/* If we have a RangeABC, get the values from that */
2585
code = dict_find_string(&CIEdict, "RangeABC", &tempref);
2586
if (code >= 0 && !r_has_type(tempref, t_null)) {
2588
code = array_get(imemory, tempref, i, &valref);
2591
if (r_has_type(&valref, t_integer))
2592
ptr[i] = (float)valref.value.intval;
2593
else if (r_has_type(&valref, t_real))
2594
ptr[i] = (float)valref.value.realval;
2596
return_error(e_typecheck);
2599
/* Default values for CIEBasedABC */
2602
ptr[(2 * i) + 1] = 1;
2607
static int cieabcvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
2613
return_error(e_stackunderflow);
2617
if (!r_has_type(op, t_integer) && !r_has_type(op, t_real))
2618
return_error(e_typecheck);
2624
static int cieabccompareproc(i_ctx_t *i_ctx_p, ref *space, ref *testspace)
2627
ref CIEdict1, CIEdict2;
2629
code = array_get(imemory, space, 1, &CIEdict1);
2632
code = array_get(imemory, testspace, 1, &CIEdict2);
2635
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"WhitePoint"))
2637
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"BlackPoint"))
2639
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeABC"))
2641
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"DecodeABC"))
2643
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"MatrixABC"))
2645
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeLMN"))
2647
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"DecodeLMN"))
2649
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"MatrixMN"))
2655
static int setciedefspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
2658
ref CIEDict, *nocie;
2661
if (i_ctx_p->language_level < 3)
2662
return_error(e_undefined);
2664
code = dict_find_string(systemdict, "NOCIE", &nocie);
2667
if (!r_has_type(nocie, t_boolean))
2668
return_error(e_typecheck);
2669
if (nocie->value.boolval)
2670
return setrgbspace(i_ctx_p, r, stage, cont, 1);
2673
code = array_get(imemory, r, 1, &CIEDict);
2682
cc.paint.values[i] = 0;
2683
code = gs_setcolor(igs, &cc);
2687
dictkey = r->value.refs->value.saveid;
2688
code = ciedefspace(i_ctx_p, &CIEDict, dictkey);
2693
static int validateciedefspace(i_ctx_t * i_ctx_p, ref **r)
2697
ref CIEdict, *pref, *CIEspace = *r, tempref, valref;
2699
if (!r_is_array(CIEspace))
2700
return_error(e_typecheck);
2701
/* Validate parameters, check we have enough operands */
2702
if (r_size(CIEspace) != 2)
2703
return_error(e_rangecheck);
2705
code = array_get(imemory, CIEspace, 1, &CIEdict);
2708
check_read_type(CIEdict, t_dictionary);
2710
code = validatecieabcspace(i_ctx_p, r);
2715
code = dict_find_string(&CIEdict, "Table", &pref);
2717
if (!r_is_array(pref))
2718
return_error(e_typecheck);
2719
if (r_size(pref) != 4)
2720
return_error(e_rangecheck);
2723
code = array_get(imemory, pref, i, &valref);
2726
if (r_has_type(&valref, t_integer))
2727
value[i] = (float)valref.value.intval;
2729
return_error(e_typecheck);
2731
if (value[0] <= 1 || value[1] <= 1 || value[2] <= 1)
2732
return_error(e_rangecheck);
2734
code = array_get(imemory, pref, 3, &valref);
2737
if (!r_is_array(&valref))
2738
return_error(e_typecheck);
2739
if (r_size(&valref) != value[0])
2740
return_error(e_rangecheck);
2742
for (i=0;i<value[0];i++) {
2743
code = array_get(imemory, &valref, i, &tempref);
2746
if (!r_has_type(&tempref, t_string))
2747
return_error(e_typecheck);
2749
if (r_size(&tempref) != (3 * value[1] * value[2]))
2750
return_error(e_rangecheck);
2753
return_error(e_rangecheck);
2756
/* Remaining parameters are optional, but we must validate
2757
* them if they are present
2759
code = dict_find_string(&CIEdict, "RangeDEF", &pref);
2760
if (code >= 0 && !r_has_type(&tempref, t_null)) {
2761
if (!r_is_array(pref))
2762
return_error(e_typecheck);
2763
if (r_size(pref) != 6)
2764
return_error(e_rangecheck);
2767
code = array_get(imemory, pref, i, &valref);
2770
if (r_has_type(&valref, t_integer))
2771
value[i] = (float)valref.value.intval;
2772
else if (r_has_type(&valref, t_real))
2773
value[i] = (float)valref.value.realval;
2775
return_error(e_typecheck);
2777
if (value[1] < value[0] || value[3] < value[2] || value[5] < value[4])
2778
return_error(e_rangecheck);
2781
code = dict_find_string(&CIEdict, "DecodeDEF", &pref);
2782
if (code >= 0 && !r_has_type(pref, t_null)) {
2783
if (!r_is_array(pref))
2784
return_error(e_typecheck);
2785
if (r_size(pref) != 3)
2786
return_error(e_rangecheck);
2789
code = array_get(imemory, pref, i, &valref);
2796
code = dict_find_string(&CIEdict, "RangeHIJ", &pref);
2797
if (code >= 0 && !r_has_type(pref, t_null)) {
2798
if (!r_is_array(pref))
2799
return_error(e_typecheck);
2800
if (r_size(pref) != 6)
2801
return_error(e_rangecheck);
2804
code = array_get(imemory, pref, i, &valref);
2807
if (r_has_type(&valref, t_integer))
2808
value[i] = (float)valref.value.intval;
2809
else if (r_has_type(&valref, t_real))
2810
value[i] = (float)valref.value.realval;
2812
return_error(e_typecheck);
2814
if (value[1] < value[0] || value[3] < value[2] || value[5] < value[4])
2815
return_error(e_rangecheck);
2821
static int ciedefdomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
2824
ref CIEdict, *tempref, valref;
2826
code = array_get(imemory, space, 1, &CIEdict);
2830
/* If we have a RangeDEF, get the values from that */
2831
code = dict_find_string(&CIEdict, "RangeDEF", &tempref);
2832
if (code >= 0 && !r_has_type(tempref, t_null)) {
2834
code = array_get(imemory, tempref, i, &valref);
2837
if (r_has_type(&valref, t_integer))
2838
ptr[i] = (float)valref.value.intval;
2839
else if (r_has_type(&valref, t_real))
2840
ptr[i] = (float)valref.value.realval;
2842
return_error(e_typecheck);
2845
/* Default values for a CIEBasedDEF */
2848
ptr[(2 * i) + 1] = 1;
2853
static int ciedefrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
2856
ref CIEdict, *tempref, valref;
2858
code = array_get(imemory, space, 1, &CIEdict);
2862
/* If we have a RangeDEF, get the values from that */
2863
code = dict_find_string(&CIEdict, "RangeDEF", &tempref);
2864
if (code >= 0 && !r_has_type(tempref, t_null)) {
2866
code = array_get(imemory, tempref, i, &valref);
2869
if (r_has_type(&valref, t_integer))
2870
ptr[i] = (float)valref.value.intval;
2871
else if (r_has_type(&valref, t_real))
2872
ptr[i] = (float)valref.value.realval;
2874
return_error(e_typecheck);
2877
/* Default values for a CIEBasedDEF */
2880
ptr[(2 * i) + 1] = 1;
2885
static int ciedefvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
2891
return_error(e_stackunderflow);
2895
if (!r_has_type(op, t_integer) && !r_has_type(op, t_real))
2896
return_error(e_typecheck);
2902
static int ciedefcompareproc(i_ctx_t *i_ctx_p, ref *space, ref *testspace)
2905
ref CIEdict1, CIEdict2;
2907
code = array_get(imemory, space, 1, &CIEdict1);
2910
code = array_get(imemory, testspace, 1, &CIEdict2);
2913
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"WhitePoint"))
2915
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"BlackPoint"))
2917
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeABC"))
2919
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"DecodeABC"))
2921
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"MatrixABC"))
2923
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeLMN"))
2925
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"DecodeLMN"))
2927
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"MatrixMN"))
2929
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeDEF"))
2931
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"DecodeDEF"))
2933
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeHIJ"))
2935
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"Table"))
2941
static int setciedefgspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
2944
ref CIEDict, *nocie;
2947
if (i_ctx_p->language_level < 3)
2948
return_error(e_undefined);
2950
code = dict_find_string(systemdict, "NOCIE", &nocie);
2953
if (!r_has_type(nocie, t_boolean))
2954
return_error(e_typecheck);
2955
if (nocie->value.boolval)
2956
return setcmykspace(i_ctx_p, r, stage, cont, 1);
2959
code = array_get(imemory, r, 1, &CIEDict);
2968
cc.paint.values[i] = 0;
2969
code = gs_setcolor(igs, &cc);
2973
dictkey = r->value.refs->value.saveid;
2974
code = ciedefgspace(i_ctx_p, &CIEDict,dictkey);
2979
static int validateciedefgspace(i_ctx_t * i_ctx_p, ref **r)
2983
ref CIEdict, *CIEspace = *r, tempref, arrayref, valref, *pref = &tempref;
2985
if (!r_is_array(CIEspace))
2986
return_error(e_typecheck);
2987
/* Validate parameters, check we have enough operands */
2988
if (r_size(CIEspace) != 2)
2989
return_error(e_rangecheck);
2991
code = array_get(imemory, CIEspace, 1, &CIEdict);
2994
check_read_type(CIEdict, t_dictionary);
2996
code = validatecieabcspace(i_ctx_p, r);
3000
code = dict_find_string(&CIEdict, "Table", &pref);
3002
if (!r_is_array(pref))
3003
return_error(e_typecheck);
3004
if (r_size(pref) != 5)
3005
return_error(e_rangecheck);
3008
code = array_get(imemory, pref, i, &valref);
3011
if (r_has_type(&valref, t_integer))
3012
value[i] = (float)valref.value.intval;
3014
return_error(e_typecheck);
3016
if (value[0] <= 1 || value[1] <= 1 || value[2] <= 1 || value[3] <= 1)
3017
return_error(e_rangecheck);
3019
code = array_get(imemory, pref, 4, &arrayref);
3022
if (!r_is_array(&arrayref))
3023
return_error(e_typecheck);
3024
if (r_size(&arrayref) != value[0])
3025
return_error(e_rangecheck);
3027
for (i=0;i<value[0];i++) {
3028
code = array_get(imemory, &arrayref, i, &tempref);
3031
for (j=0;j<value[1];j++) {
3032
code = array_get(imemory, &tempref, i, &valref);
3035
if (!r_has_type(&valref, t_string))
3036
return_error(e_typecheck);
3038
if (r_size(&valref) != (3 * value[2] * value[3]))
3039
return_error(e_rangecheck);
3043
return_error(e_rangecheck);
3046
/* Remaining parameters are optional, but we must validate
3047
* them if they are present
3049
code = dict_find_string(&CIEdict, "RangeDEFG", &pref);
3050
if (code >= 0 && !r_has_type(pref, t_null)) {
3051
if (!r_is_array(pref))
3052
return_error(e_typecheck);
3053
if (r_size(pref) != 8)
3054
return_error(e_rangecheck);
3057
code = array_get(imemory, pref, i, &valref);
3060
if (r_has_type(&valref, t_integer))
3061
value[i] = (float)valref.value.intval;
3062
else if (r_has_type(&valref, t_real))
3063
value[i] = (float)valref.value.realval;
3065
return_error(e_typecheck);
3067
if (value[1] < value[0] || value[3] < value[2] || value[5] < value[4] || value[7] < value[6])
3068
return_error(e_rangecheck);
3071
code = dict_find_string(&CIEdict, "DecodeDEFG", &pref);
3072
if (code >= 0 && !r_has_type(pref, t_null)) {
3073
if (!r_is_array(pref))
3074
return_error(e_typecheck);
3075
if (r_size(pref) != 4)
3076
return_error(e_rangecheck);
3079
code = array_get(imemory, pref, i, &valref);
3086
code = dict_find_string(&CIEdict, "RangeHIJK", &pref);
3087
if (code >= 0 && !r_has_type(pref, t_null)) {
3088
if (!r_is_array(pref))
3089
return_error(e_typecheck);
3090
if (r_size(pref) != 8)
3091
return_error(e_rangecheck);
3094
code = array_get(imemory, pref, i, &valref);
3097
if (r_has_type(&valref, t_integer))
3098
value[i] = (float)valref.value.intval;
3099
else if (r_has_type(&valref, t_real))
3100
value[i] = (float)valref.value.realval;
3102
return_error(e_typecheck);
3104
if (value[1] < value[0] || value[3] < value[2] || value[5] < value[4] || value[7] < value[6])
3105
return_error(e_rangecheck);
3111
static int ciedefgdomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
3114
ref CIEdict, *tempref, valref;
3116
code = array_get(imemory, space, 1, &CIEdict);
3120
/* If we have a RangeDEFG, get the values from that */
3121
code = dict_find_string(&CIEdict, "RangeDEFG", &tempref);
3122
if (code >= 0 && !r_has_type(tempref, t_null)) {
3124
code = array_get(imemory, tempref, i, &valref);
3127
if (r_has_type(&valref, t_integer))
3128
ptr[i] = (float)valref.value.intval;
3129
else if (r_has_type(&valref, t_real))
3130
ptr[i] = (float)valref.value.realval;
3132
return_error(e_typecheck);
3135
/* Default values for a CIEBasedDEFG */
3138
ptr[(2 * i) + 1] = 1;
3143
static int ciedefgrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
3146
ref CIEdict, *tempref, valref;
3148
code = array_get(imemory, space, 1, &CIEdict);
3152
/* If we have a RangeDEFG, get the values from that */
3153
code = dict_find_string(&CIEdict, "RangeDEFG", &tempref);
3154
if (code >= 0 && !r_has_type(tempref, t_null)) {
3156
code = array_get(imemory, tempref, i, &valref);
3159
if (r_has_type(&valref, t_integer))
3160
ptr[i] = (float)valref.value.intval;
3161
else if (r_has_type(&valref, t_real))
3162
ptr[i] = (float)valref.value.realval;
3164
return_error(e_typecheck);
3167
/* Default values for a CIEBasedDEFG */
3170
ptr[(2 * i) + 1] = 1;
3175
static int ciedefgvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
3181
return_error(e_stackunderflow);
3184
for (i=0;i < 4;i++) {
3185
if (!r_has_type(op, t_integer) && !r_has_type(op, t_real))
3186
return_error(e_typecheck);
3191
static int ciedefgcompareproc(i_ctx_t *i_ctx_p, ref *space, ref *testspace)
3193
/* If the problems mentioned above are resolved, then this code could
3197
ref CIEdict1, CIEdict2;
3199
code = array_get(imemory, space, 1, &CIEdict1);
3202
code = array_get(imemory, testspace, 1, &CIEdict2);
3205
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"WhitePoint"))
3207
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"BlackPoint"))
3209
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeABC"))
3211
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"DecodeABC"))
3213
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"MatrixABC"))
3215
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeLMN"))
3217
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"DecodeLMN"))
3219
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"MatrixMN"))
3221
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeDEFG"))
3223
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"DecodeDEFG"))
3225
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"RangeHIJK"))
3227
if (!comparedictkey(i_ctx_p, &CIEdict1, &CIEdict2, (char *)"Table"))
3232
static char const * const CIESpaces[] = {
3238
/* This routine returns the Device space equivalents for a CIEBased space.
3239
* Used by currentgray, currentrgb and currentcmyk, the PLRM says that CIE
3240
* spaces return 0 for all components.
3242
static int ciebasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth)
3245
ref *spacename, nref;
3246
int i, components=1, code;
3248
/* If the spaece is an array, the first element is always the name */
3249
if (r_is_array(space))
3250
spacename = space->value.refs;
3253
/* Check that it really is a name */
3254
if (!r_has_type(spacename, t_name))
3255
return_error(e_typecheck);
3257
/* Find the relevant color space object */
3259
code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)CIESpaces[i], strlen(CIESpaces[i]), &nref, 0);
3262
if (name_eq(spacename, &nref)) {
3266
/* Find out how many values are on the stack, which depends
3267
* on what kind of CIEBased space this is.
3281
/* Remove teh requisite number of values */
3284
/* Find out how many values we need to return, which
3285
* depends on the requested space.
3300
/* The PLRM says that all the components should be returned as 0.0 */
3302
for (i=0;i<components;i++) {
3303
make_real(op, (float)0);
3306
/* However, Adobe implementations actually return 1.0 for the black
3307
* channel of CMYK...
3309
if (components == 4) {
3311
make_real(op, (float)1);
3318
/* This routine used by both Separatin and DeviceN spaces to convert
3319
* a PostScript tint transform into a Function, either a type 4
3320
* 'PostScript calculator (see PDF reference) or a type 0 'sampled'
3323
static int convert_transform(i_ctx_t * i_ctx_p, ref *arr, ref *pproc)
3325
os_ptr op = osp; /* required by "push" macro */
3328
/* buildfunction returns an operand on the stack. In fact
3329
* it replaces the lowest operand, so make sure there is an
3330
* empty sacrificial one present.
3333
/* Start by trying a type 4 function */
3334
code = buildfunction(i_ctx_p, arr, pproc, 4);
3337
/* If that fails, try a type 0. We prefer a type 4
3338
* because a type 0 will require us to sample the
3339
* space, which is expensive
3341
code = buildfunction(i_ctx_p, arr, pproc, 0);
3347
static int setseparationspace(i_ctx_t * i_ctx_p, ref *sepspace, int *stage, int *cont, int CIESubst)
3349
os_ptr op = osp; /* required by "push" macro */
3352
ref name_none, name_all;
3353
separation_type sep_type;
3354
ref_colorspace cspace_old;
3355
gs_color_space *pcs;
3356
gs_color_space * pacs;
3357
gs_function_t *pfn = NULL;
3360
if (i_ctx_p->language_level < 2)
3361
return_error(e_undefined);
3364
if ((*stage) == 0) {
3365
code = array_get(imemory, sepspace, 3, &proc);
3368
/* Check to see if we already have a function (eg from a PDF file) */
3369
pfn = ref_function(&proc);
3371
/* Convert tint transform to a PostScript function */
3372
code = convert_transform(i_ctx_p, sepspace, &proc);
3380
/* We can only get here if the transform converted to a function
3381
* without requiring a continuation. Most likely this means its a
3382
* type 4 function. If so then it is still on the stack.
3385
pfn = ref_function(op);
3389
/* The function is returned on the operand stack */
3391
pfn = ref_function(op);
3396
if ((code = name_ref(imemory, (const byte *)"All", 3, &name_all, 0)) < 0)
3398
if ((code = name_ref(imemory, (const byte *)"None", 4, &name_none, 0)) < 0)
3400
/* Check separation name is a string or name object */
3401
code = array_get(imemory, sepspace, 1, &sname);
3405
if (r_has_type(&sname, t_string)) {
3406
code = name_from_string(imemory, &sname, &sname);
3410
sep_type = ( name_eq(&sname, &name_all) ? SEP_ALL :
3411
name_eq(&sname, &name_none) ? SEP_NONE : SEP_OTHER);
3413
/* The alternate color space has been selected as the current color space */
3414
pacs = gs_currentcolorspace(igs);
3416
cspace_old = istate->colorspace[0];
3417
/* Now set the current color space as Separation */
3418
code = gs_cspace_new_Separation(&pcs, pacs, imemory);
3421
pcs->params.separation.sep_type = sep_type;
3422
pcs->params.separation.sep_name = name_index(imemory, &sname);
3423
pcs->params.separation.get_colorname_string = gs_get_colorname_string;
3424
code = array_get(imemory, sepspace, 1, &proc);
3427
istate->colorspace[0].procs.special.separation.layer_name = proc;
3428
code = array_get(imemory, sepspace, 3, &proc);
3431
istate->colorspace[0].procs.special.separation.tint_transform = proc;
3433
code = gs_cspace_set_sepr_function(pcs, pfn);
3435
code = gs_setcolorspace(igs, pcs);
3436
/* release reference from construction */
3437
rc_decrement_only_cs(pcs, "setseparationspace");
3439
istate->colorspace[0] = cspace_old;
3443
cc.paint.values[0] = 1.0;
3444
code = gs_setcolor(igs, &cc);
3447
static int validateseparationspace(i_ctx_t * i_ctx_p, ref **space)
3450
ref *sepspace = *space;
3451
ref nameref, sref, sname, altspace, tref;
3453
if (!r_is_array(sepspace))
3454
return_error(e_typecheck);
3455
/* Validate parameters, check we have enough operands */
3456
if (r_size(sepspace) != 4)
3457
return_error(e_rangecheck);
3459
/* Check separation name is a string or name object */
3460
code = array_get(imemory, sepspace, 1, &sname);
3463
if (!r_has_type(&sname, t_name)) {
3464
if (!r_has_type(&sname, t_string))
3465
return_error(e_typecheck);
3467
code = name_from_string(imemory, &sname, &sname);
3473
/* Check the tint transform is a procedure */
3474
code = array_get(imemory, sepspace, 3, &tref);
3479
/* Get the name of the alternate space */
3480
code = array_get(imemory, sepspace, 2, &altspace);
3483
if (r_has_type(&altspace, t_name))
3484
ref_assign(&nameref, &altspace);
3486
/* Make sure the alternate space is an array */
3487
if (!r_is_array(&altspace))
3488
return_error(e_typecheck);
3489
/* And has a name for its type */
3490
code = array_get(imemory, &altspace, 0, &tref);
3493
if (!r_has_type(&tref, t_name))
3494
return_error(e_typecheck);
3495
ref_assign(&nameref, &tref);
3498
/* Convert alternate space name to string */
3499
name_string_ref(imemory, &nameref, &sref);
3500
/* Check its not /Indexed or /Pattern or /DeviceN */
3501
if (r_size(&sref) == 7) {
3502
if (strncmp((const char *)sref.value.const_bytes, "Indexed", 7) == 0)
3503
return_error(e_typecheck);
3504
if (strncmp((const char *)sref.value.const_bytes, "Pattern", 7) == 0)
3505
return_error(e_typecheck);
3506
if (strncmp((const char *)sref.value.const_bytes, "DeviceN", 7) == 0)
3507
return_error(e_typecheck);
3509
/* and also not /Separation */
3510
if (r_size(&sref) == 9 && strncmp((const char *)sref.value.const_bytes, "Separation", 9) == 0)
3511
return_error(e_typecheck);
3513
ref_assign(*space, &altspace);
3516
static int separationalternatespace(i_ctx_t * i_ctx_p, ref *sepspace, ref **r, int *CIESubst)
3521
code = array_get(imemory, sepspace, 2, &tref);
3524
ref_assign(*r, &tref);
3527
static int sepdomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
3533
static int seprange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
3539
static int septransform(i_ctx_t *i_ctx_p, ref *sepspace, int *usealternate, int *stage, int *stack_depth)
3541
gx_device * dev = igs->device;
3543
int code, colorant_number;
3545
code = array_get(imemory, sepspace, 1, &sname);
3548
if (r_has_type(&sname, t_name)) {
3549
name_string_ref(imemory, &sname, &sname);
3552
/* Check for /All and /None, never need the alternate for these */
3553
if (r_size(&sname) == 3 &&
3554
strncmp("All", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
3558
if (r_size(&sname) == 4 &&
3559
strncmp("None", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
3564
* Compare the colorant name to the device's. If the device's
3565
* compare routine returns GX_DEVICE_COLOR_MAX_COMPONENTS then the
3566
* colorant is in the SeparationNames list but not in the
3567
* SeparationOrder list.
3569
colorant_number = (*dev_proc(dev, get_color_comp_index))
3570
(dev, (const char *)sname.value.bytes, r_size(&sname), SEPARATION_NAME);
3571
if (colorant_number >= 0) { /* If valid colorant name */
3576
if (r_size(&sname) == 4 &&
3577
strncmp("Gray", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
3580
if (r_size(&sname) == 4 &&
3581
strncmp("Cyan", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
3584
if (r_size(&sname) == 7 &&
3585
strncmp("Magenta", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
3588
if (r_size(&sname) == 6 &&
3589
strncmp("Yellow", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
3592
if (r_size(&sname) == 5 &&
3593
strncmp("Black", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
3596
if (r_size(&sname) == 3 &&
3597
strncmp("Red", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
3600
if (r_size(&sname) == 5 &&
3601
strncmp("Green", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
3604
if (r_size(&sname) == 4 &&
3605
strncmp("Blue", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
3608
if (*usealternate && *stage == 0) {
3611
code = array_get(imemory, sepspace, 3, &proc);
3615
return o_push_estack;
3620
static int sepbasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth)
3622
os_ptr op = osp; /* required by "push" macro */
3625
code = septransform(i_ctx_p, space, &use, stage, stack_depth);
3641
make_real(&op[-2], 0.0);
3642
make_real(&op[-1], 0.0);
3647
make_real(&op[-3], 0.0);
3648
make_real(&op[-2], 0.0);
3649
make_real(&op[-1], 0.0);
3659
static int sepvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
3664
return_error(e_stackunderflow);
3666
if (!r_has_type(op, t_integer) && !r_has_type(op, t_real))
3667
return_error(e_typecheck);
3677
static int sepcompareproc(i_ctx_t *i_ctx_p, ref *space, ref *testspace)
3682
code = array_get(imemory, space, 1, &sname1);
3686
code = array_get(imemory, testspace, 1, &sname2);
3690
if (r_type(&sname1) != r_type(&sname2))
3693
switch(r_type(&sname1)) {
3695
if (!name_eq(&sname1, &sname2))
3699
if (r_size(&sname1) != r_size(&sname2))
3701
if (strncmp((const char *)sname1.value.const_bytes, (const char *)sname2.value.const_bytes, r_size(&sname1)) != 0)
3707
code = array_get(imemory, testspace, 2, &sname1);
3710
code = array_get(imemory, testspace, 2, &sname2);
3713
if (r_type(&sname1) != r_type(&sname2))
3716
if (r_is_array(&sname1)) {
3717
if (!comparearrays(i_ctx_p, &sname1, &sname2))
3720
if (!r_has_type(&sname1, t_name))
3722
if (!name_eq(&sname1, &sname2))
3725
code = array_get(imemory, space, 3, &sname1);
3728
code = array_get(imemory, testspace, 3, &sname2);
3731
return(comparearrays(i_ctx_p, &sname1, &sname2));
3733
static int sepinitialproc(i_ctx_t *i_ctx_p, ref *space)
3738
cc.paint.values[0] = 1.0;
3739
return gs_setcolor(igs, &cc);
3743
static int devicencolorants_cont(i_ctx_t *i_ctx_p)
3745
ref dict, *pdict = &dict, space[2], sname;
3746
int index, code, depth, stage;
3747
es_ptr ep = esp, pindex, pstage;
3749
gs_separation_name sep_name;
3753
index = (int)pindex->value.intval;
3754
stage = (int)pstage->value.intval;
3755
ref_assign(&dict, ep);
3758
if (index >= dict_length(pdict)) {
3760
return o_pop_estack;
3764
code = gs_gsave(igs);
3768
code = dict_index_entry(pdict, index, (ref *)&space);
3770
make_int(pindex, ++index);
3771
code = gs_grestore(igs);
3777
code = validate_spaces(i_ctx_p, &space[1], &depth);
3779
make_int(pindex, ++index);
3780
code = gs_grestore(igs);
3783
return o_push_estack;
3786
/* If we get a continuation from a sub-procedure, we will want to come back
3787
* here afterward, to do any remaining stages. We need to set up for that now.
3788
* so that our continuation is ahead of the sub-proc's continuation.
3792
/* The push_op_estack macro increments esp before use, so we don't need to */
3793
push_op_estack(devicencolorants_cont);
3795
make_int(pstage, 1);
3797
code = zsetcolorspace(i_ctx_p);
3802
code = dict_index_entry(pdict, index, (ref *)&space);
3804
switch (r_type(&space[0])) {
3806
code = name_from_string(imemory, &space[0], &sname);
3808
sep_name = name_index(imemory, &sname);
3811
sep_name = name_index(imemory, &space[0]);
3817
make_int(pindex, ++index);
3818
make_int(pstage, stage);
3820
gs_attachattributecolorspace(sep_name, igs);
3821
code = gs_grestore(igs);
3829
static int setdevicenspace(i_ctx_t * i_ctx_p, ref *devicenspace, int *stage, int *cont, int CIESubst)
3831
os_ptr op = osp; /* required by "push" macro */
3832
int code = 0, num_components, i;
3833
ref namesarray, proc, sname, tname, sref, tempref[2];
3834
ref_colorspace cspace_old;
3835
gs_color_space *pcs;
3836
gs_color_space * pacs;
3837
gs_function_t *pfn = NULL;
3838
gs_separation_name *names;
3839
gs_device_n_map *pmap;
3842
if (i_ctx_p->language_level < 3)
3843
return_error(e_undefined);
3846
if ((*stage) == 2) {
3847
if (r_size(devicenspace) == 5) {
3848
/* We have a Colorants dictionary from a PDF file. We need to handle this by
3849
* temporarily setting each of the spaces in the dict, and attaching the
3850
* resulting space to the DeviceN array. This is complicated, because
3851
* each space must be fully set up, and may result in running tint transform
3852
* procedures and caching results. We need to handle this in yet another
3853
* layering of continuation procedures.
3855
code = array_get(imemory, devicenspace, 4, &sref);
3858
if (!r_has_type(&sref, t_dictionary)) {
3862
if (dict_length(&sref) == 0)
3865
code = dict_index_entry(&sref, 0, (ref *)&tempref);
3868
name_string_ref(imemory, &tempref[0], &sname);
3869
if (r_size(&sname) != 9 || strncmp((const char *)sname.value.const_bytes, "Colorants", r_size(&sname)) != 0) {
3877
push_mark_estack(es_other, 0);
3879
/* variable to hold index of the space we are dealing with */
3882
/* variable to hold processing step */
3885
/* Store a pointer to the Colorants dictionary
3887
ref_assign(esp, &tempref[1]);
3888
push_op_estack(devicencolorants_cont);
3889
return o_push_estack;
3895
if ((*stage) == 3) {
3899
if ((*stage) == 0) {
3900
code = array_get(imemory, devicenspace, 3, &proc);
3903
pfn = ref_function(&proc);
3905
/* Convert tint transform to a PostScript function */
3906
code = convert_transform(i_ctx_p, devicenspace, &proc);
3914
/* We can only get here if the transform converted to a function
3915
* without requiring a continuation. Most likely this means its a
3916
* type 4 function. If so then it is still on the stack.
3919
pfn = ref_function(op);
3923
/* The function is returned on the operand stack */
3925
pfn = ref_function(op);
3931
code = array_get(imemory, devicenspace, 1, &namesarray);
3934
num_components = r_size(&namesarray);
3935
/* The alternate color space has been selected as the current color space */
3936
pacs = gs_currentcolorspace(igs);
3938
if (num_components == 1) {
3939
array_get(imemory, &namesarray, (long)0, &sname);
3940
switch (r_type(&sname)) {
3945
name_string_ref(imemory, &sname, &tname);
3948
return_error(e_typecheck);
3951
if (strncmp((const char *)tname.value.const_bytes, "All", 3) == 0 && r_size(&tname) == 3) {
3952
separation_type sep_type;
3954
/* Sigh, Acrobat allows this, even though its contra the spec. Convert to
3955
* a /Separation space and go on
3959
/* The alternate color space has been selected as the current color space */
3960
pacs = gs_currentcolorspace(igs);
3962
cspace_old = istate->colorspace[0];
3963
/* Now set the current color space as Separation */
3964
code = gs_cspace_new_Separation(&pcs, pacs, imemory);
3967
pcs->params.separation.sep_type = sep_type;
3968
pcs->params.separation.sep_name = name_index(imemory, &sname);
3969
pcs->params.separation.get_colorname_string = gs_get_colorname_string;
3970
code = array_get(imemory, &namesarray, (long)0, &sname);
3973
istate->colorspace[0].procs.special.separation.layer_name = sname;
3974
code = array_get(imemory, devicenspace, 3, &proc);
3977
istate->colorspace[0].procs.special.separation.tint_transform = proc;
3979
code = gs_cspace_set_sepr_function(pcs, pfn);
3981
code = gs_setcolorspace(igs, pcs);
3982
/* release reference from construction */
3983
rc_decrement_only_cs(pcs, "setseparationspace");
3985
istate->colorspace[0] = cspace_old;
3989
cc.paint.values[0] = 1.0;
3990
code = gs_setcolor(igs, &cc);
3994
code = gs_cspace_new_DeviceN(&pcs, num_components, pacs, imemory);
3997
names = pcs->params.device_n.names;
3998
pmap = pcs->params.device_n.map;
3999
pcs->params.device_n.get_colorname_string = gs_get_colorname_string;
4001
/* Pick up the names of the components */
4006
for (i = 0; i < num_components; ++i) {
4007
array_get(imemory, &namesarray, (long)i, &sname);
4008
switch (r_type(&sname)) {
4010
code = name_from_string(imemory, &sname, &sname);
4012
rc_decrement_cs(pcs, "setdevicenspace");
4017
names[i] = name_index(imemory, &sname);
4020
rc_decrement_cs(pcs, "setdevicenspace");
4021
return_error(e_typecheck);
4026
/* Now set the current color space as DeviceN */
4028
cspace_old = istate->colorspace[0];
4029
istate->colorspace[0].procs.special.device_n.layer_names = namesarray;
4030
code = array_get(imemory, devicenspace, 3, &proc);
4033
istate->colorspace[0].procs.special.device_n.tint_transform = proc;
4034
gs_cspace_set_devn_function(pcs, pfn);
4035
code = gs_setcolorspace(igs, pcs);
4036
/* release reference from construction */
4037
rc_decrement_only_cs(pcs, "setdevicenspace");
4039
istate->colorspace[0] = cspace_old;
4044
for (i=0;i<num_components;i++)
4045
cc.paint.values[i] = 1.0;
4046
code = gs_setcolor(igs, &cc);
4050
static int validatedevicenspace(i_ctx_t * i_ctx_p, ref **space)
4053
ref *devicenspace = *space, proc;
4054
ref nameref, sref, altspace, namesarray, sname;
4056
/* Check enough arguments in the space */
4057
if (r_size(devicenspace) < 4)
4058
return_error(e_rangecheck);
4059
/* Check the names parameter is an array */
4060
code = array_get(imemory, devicenspace, 1, &namesarray);
4063
if (!r_is_array(&namesarray))
4064
return_error(e_typecheck);
4065
/* Ensure we have at least one ink */
4066
if (r_size(&namesarray) < 1)
4067
return_error(e_typecheck);
4068
/* Make sure no more inks than we can cope with */
4069
if (r_size(&namesarray) > GS_CLIENT_COLOR_MAX_COMPONENTS)
4070
return_error(e_limitcheck);
4071
/* Check the tint transform is a procedure */
4072
code = array_get(imemory, devicenspace, 3, &proc);
4077
/* Check the array of ink names only contains names or strings */
4078
for (i = 0; i < r_size(&namesarray); ++i) {
4079
array_get(imemory, &namesarray, (long)i, &sname);
4080
switch (r_type(&sname)) {
4085
return_error(e_typecheck);
4089
/* Get the name of the alternate space */
4090
code = array_get(imemory, devicenspace, 2, &altspace);
4093
if (r_has_type(&altspace, t_name))
4094
ref_assign(&nameref, &altspace);
4096
/* Make sure the alternate space is an array */
4097
if (!r_is_array(&altspace))
4098
return_error(e_typecheck);
4099
/* And has a name for its type */
4100
code = array_get(imemory, &altspace, 0, &nameref);
4103
if (!r_has_type(&nameref, t_name))
4104
return_error(e_typecheck);
4106
/* Convert alternate space name to string */
4107
name_string_ref(imemory, &nameref, &sref);
4108
/* Check its not /Indexed, /Pattern, /DeviceN */
4109
if (r_size(&sref) == 7) {
4110
if (strncmp((const char *)sref.value.const_bytes, "Indexed", 7) == 0)
4111
return_error(e_typecheck);
4112
if (strncmp((const char *)sref.value.const_bytes, "Pattern", 7) == 0)
4113
return_error(e_typecheck);
4114
if (strncmp((const char *)sref.value.const_bytes, "DeviceN", 7) == 0)
4115
return_error(e_typecheck);
4117
/* and also not /Separation */
4118
if (r_size(&sref) == 9 && strncmp((const char *)sref.value.const_bytes, "Separation", 9) == 0)
4119
return_error(e_typecheck);
4121
ref_assign(*space, &altspace);
4124
static int devicenalternatespace(i_ctx_t * i_ctx_p, ref *space, ref **r, int *CIESubst)
4129
code = array_get(imemory, space, 2, &altspace);
4132
ref_assign(*r, &altspace);
4135
static int devicencomponents(i_ctx_t * i_ctx_p, ref *space, int *n)
4140
code = array_get(imemory, space, 1, &namesarray);
4143
*n = r_size(&namesarray);
4146
static int devicendomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
4151
code = array_get(imemory, space, 1, &namesarray);
4155
limit = r_size(&namesarray) * 2;
4156
for (i = 0;i < limit;i+=2) {
4162
static int devicenrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
4165
PS_colour_space_t *cspace;
4169
code = array_get(imemory, space, 1, &altspace);
4173
code = get_space_object(i_ctx_p, &altspace, &cspace);
4177
code = cspace->numcomponents(i_ctx_p, &altspace, &limit);
4181
for (i = 0;i < limit * 2;i+=2) {
4187
static int devicentransform(i_ctx_t *i_ctx_p, ref *devicenspace, int *usealternate, int *stage, int *stack_depth)
4189
gx_device * dev = igs->device;
4190
ref narray, sname, proc;
4191
int i, code, colorant_number;
4194
code = array_get(imemory, devicenspace, 1, &narray);
4197
if (!r_is_array(&narray))
4198
return_error(e_typecheck);
4200
for (i=0;i<r_size(&narray);i++) {
4201
code = array_get(imemory, &narray, i, &sname);
4204
if (r_has_type(&sname, t_name)) {
4205
name_string_ref(imemory, &sname, &sname);
4208
/* Check for /All and /None, never need the alternate for these */
4209
if (r_size(&sname) == 3 &&
4210
strncmp("All", (const char *)sname.value.bytes, r_size(&sname)) == 0)
4212
if (r_size(&sname) == 4 &&
4213
strncmp("None", (const char *)sname.value.bytes, r_size(&sname)) == 0)
4216
* Compare the colorant name to the device's. If the device's
4217
* compare routine returns GX_DEVICE_COLOR_MAX_COMPONENTS then the
4218
* colorant is in the SeparationNames list but not in the
4219
* SeparationOrder list.
4221
colorant_number = (*dev_proc(dev, get_color_comp_index))
4222
(dev, (const char *)sname.value.bytes, r_size(&sname), SEPARATION_NAME);
4223
if (colorant_number < 0) { /* If not valid colorant name */
4227
if (r_size(&sname) == 4 &&
4228
strncmp("Gray", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
4232
if (r_size(&sname) == 4 &&
4233
strncmp("Cyan", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
4237
if (r_size(&sname) == 7 &&
4238
strncmp("Magenta", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
4242
if (r_size(&sname) == 6 &&
4243
strncmp("Yellow", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
4247
if (r_size(&sname) == 5 &&
4248
strncmp("Black", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
4252
if (r_size(&sname) == 3 &&
4253
strncmp("Red", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
4257
if (r_size(&sname) == 5 &&
4258
strncmp("Green", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
4262
if (r_size(&sname) == 4 &&
4263
strncmp("Blue", (const char *)sname.value.bytes, r_size(&sname)) == 0) {
4268
if (*usealternate && *stage == 0) {
4271
code = array_get(imemory, devicenspace, 3, &proc);
4275
return o_push_estack;
4284
static int devicenbasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth)
4286
os_ptr op = osp; /* required by "push" macro */
4287
int code, use, n_comp;
4290
code = devicentransform(i_ctx_p, space, &use, stage, stack_depth);
4296
code = array_get(imemory, space, 1, &narray);
4299
n_comp = r_size(&narray);
4310
make_real(&op[-2], 0.0);
4311
make_real(&op[-1], 0.0);
4316
make_real(&op[-3], 0.0);
4317
make_real(&op[-2], 0.0);
4318
make_real(&op[-1], 0.0);
4328
static int devicenvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
4334
code = array_get(imemory, space, 1, &narray);
4337
if (!r_is_array(&narray))
4338
return_error(e_typecheck);
4340
if (num_comps < r_size(&narray))
4341
return_error(e_stackunderflow);
4343
op -= r_size(&narray) - 1;
4345
for (i=0;i < r_size(&narray); i++) {
4346
if (!r_has_type(op, t_integer) && !r_has_type(op, t_real))
4347
return_error(e_typecheck);
4349
if (values[i] > 1.0)
4352
if (values[i] < 0.0)
4359
static int devicencompareproc(i_ctx_t *i_ctx_p, ref *space, ref *testspace)
4364
code = array_get(imemory, space, 1, &sname1);
4368
code = array_get(imemory, testspace, 1, &sname2);
4372
if (!r_is_array(&sname1))
4374
if (!r_is_array(&sname2))
4377
if (!comparearrays(i_ctx_p, &sname1, &sname2))
4380
code = array_get(imemory, testspace, 2, &sname1);
4383
code = array_get(imemory, testspace, 2, &sname2);
4386
if (r_type(&sname1) != r_type(&sname2))
4389
if (r_is_array(&sname1)) {
4390
if (!comparearrays(i_ctx_p, &sname1, &sname2))
4393
if (!r_has_type(&sname1, t_name))
4395
if (!name_eq(&sname1, &sname2))
4398
code = array_get(imemory, space, 3, &sname1);
4401
code = array_get(imemory, testspace, 3, &sname2);
4404
return(comparearrays(i_ctx_p, &sname1, &sname2));
4406
static int deviceninitialproc(i_ctx_t *i_ctx_p, ref *space)
4409
int i, num_components, code;
4412
code = array_get(imemory, space, 1, &namesarray);
4415
num_components = r_size(&namesarray);
4417
for (i=0;i<num_components;i++)
4418
cc.paint.values[i] = 1.0;
4419
return gs_setcolor(igs, &cc);
4424
* This routine samples the indexed space, it pushes values from -1
4425
* to 'hival', then executes the tint transform procedure. Returns here
4426
* to store the resulting value(s) in the indexed map.
4429
indexed_cont(i_ctx_t *i_ctx_p)
4433
int i = (int)ep[csme_index].value.intval;
4435
if (i >= 0) { /* i.e., not first time */
4436
int m = (int)ep[csme_num_components].value.intval;
4437
int code = float_params(op, m, &r_ptr(&ep[csme_map], gs_indexed_map)->values[i * m]);
4443
if (i == (int)ep[csme_hival].value.intval) { /* All done. */
4445
return o_pop_estack;
4449
ep[csme_index].value.intval = ++i;
4451
make_op_estack(ep + 1, indexed_cont);
4452
ep[2] = ep[csme_proc]; /* lookup proc */
4454
return o_push_estack;
4456
static int setindexedspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
4458
ref *pproc = &istate->colorspace[0].procs.special.index_proc;
4460
uint edepth = ref_stack_count(&e_stack);
4461
ref_colorspace cspace_old;
4463
gs_color_space *pcs;
4464
gs_color_space *pcs_base;
4466
if (i_ctx_p->language_level < 2)
4467
return_error(e_undefined);
4475
cspace_old = istate->colorspace[0];
4477
pcs_base = gs_currentcolorspace(igs);
4479
code = array_get(imemory, r, 3, &lookup);
4482
code = array_get(imemory, r, 2, &hival);
4485
if (r_has_type(&lookup, t_string)) {
4486
int num_values = (hival.value.intval + 1) * cs_num_components(pcs_base);
4491
* The PDF and PS specifications state that the lookup table must have
4492
* the exact number of of data bytes needed. However we have found
4493
* PDF files from Amyuni with extra data bytes. Acrobat 6.0 accepts
4494
* these files without complaint, so we ignore the extra data.
4496
if (r_size(&lookup) < num_values)
4497
return_error(e_rangecheck);
4498
pcs = gs_cspace_alloc(imemory, &gs_color_space_type_Indexed);
4500
return_error(e_VMerror);
4502
pcs->base_space = pcs_base;
4503
rc_increment_cs(pcs_base);
4505
data_tmp = (byte *) (pcs->params.indexed.lookup.table.data = ialloc_string (lookup.tas.rsize, "setindexedspace"));
4507
rc_decrement(pcs, "setindexedspace");
4508
return_error(e_VMerror);
4511
memcpy(data_tmp, lookup.value.const_bytes, lookup.tas.rsize);
4513
pcs->params.indexed.lookup.table.size = num_values;
4514
pcs->params.indexed.use_proc = 0;
4518
gs_indexed_map *map;
4521
* We have to call zcs_begin_map before moving the parameters,
4522
* since if the color space is a DeviceN or Separation space,
4523
* the memmove will overwrite its parameters.
4525
code = zcs_begin_map(i_ctx_p, &map, &lookup, (hival.value.intval + 1),
4526
pcs_base, indexed_cont);
4529
pcs = gs_cspace_alloc(imemory, &gs_color_space_type_Indexed);
4530
pcs->base_space = pcs_base;
4531
rc_increment_cs(pcs_base);
4532
pcs->params.indexed.use_proc = 1;
4534
map->proc.lookup_index = lookup_indexed_map;
4535
pcs->params.indexed.lookup.map = map;
4537
pcs->params.indexed.hival = hival.value.intval;
4538
pcs->params.indexed.n_comps = cs_num_components(pcs_base);
4539
code = gs_setcolorspace(igs, pcs);
4540
/* release reference from construction */
4541
rc_decrement_only_cs(pcs, "setindexedspace");
4543
istate->colorspace[0] = cspace_old;
4544
ref_stack_pop_to(&e_stack, edepth);
4548
if (ref_stack_count(&e_stack) == edepth) {
4553
return o_push_estack; /* installation will load the caches */
4556
static int validateindexedspace(i_ctx_t * i_ctx_p, ref **space)
4560
ref nameref, sref, hival, lookup, altspace;
4563
return_error(e_typecheck);
4564
/* Validate parameters, check we have enough operands */
4566
return_error(e_rangecheck);
4567
/* Check operand type(s) */
4568
/* Make sure 'hival' is an integer */
4569
code = array_get(imemory, r, 2, &hival);
4572
if (!r_has_type(&hival, t_integer))
4573
return_error(e_typecheck);
4574
/* Make sure 'hival' lies between 0 and 4096 */
4575
if (hival.value.intval < 0 || hival.value.intval > 4096)
4576
return_error(e_rangecheck);
4577
/* Ensure the 'lookup' is either a string or a procedure */
4578
code = array_get(imemory, r, 3, &lookup);
4581
if (!r_has_type(&lookup, t_string))
4584
/* Get the name of the alternate space */
4585
code = array_get(imemory, r, 1, &altspace);
4588
if (r_has_type(&altspace, t_name))
4589
ref_assign(&nameref, &altspace);
4591
if (!r_is_array(&altspace))
4592
return_error(e_typecheck);
4593
code = array_get(imemory, &altspace, 0, &nameref);
4597
/* Convert alternate space name to string */
4598
name_string_ref(imemory, &nameref, &sref);
4599
/* Check its not /Indexed or /Pattern */
4600
if (r_size(&sref) == 7) {
4601
if (strncmp((const char *)sref.value.const_bytes, "Indexed", 7) == 0)
4602
return_error(e_typecheck);
4603
if (strncmp((const char *)sref.value.const_bytes, "Pattern", 7) == 0)
4604
return_error(e_typecheck);
4606
ref_assign(*space, &altspace);
4609
static int indexedalternatespace(i_ctx_t * i_ctx_p, ref *space, ref **r, int *CIESubst)
4614
code = array_get(imemory, *r, 1, &alt);
4617
ref_assign(*r, &alt);
4620
static int indexeddomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
4625
code = array_get(imemory, space, 2, &hival);
4629
ptr[1] = (float)hival.value.intval;
4632
static int indexedrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
4637
code = array_get(imemory, space, 2, &hival);
4641
ptr[1] = (float)hival.value.intval;
4644
static int indexedbasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth)
4649
/* Usefully /Indexed can't be the base of any other space, so we know
4650
* the current space in the graphics state is this one.
4652
gs_color_space *pcs;
4653
pcs = gs_currentcolorspace(igs);
4655
/* Update the counters */
4659
/* Indexed spaces can have *either* a procedure or a string for the
4662
if (pcs->params.indexed.use_proc) {
4666
/* We have a procedure, set up the continuation to run the
4667
* lookup procedure. (The index is already on the operand stack)
4670
code = array_get(imemory, space, 3, &proc);
4673
*ep = proc; /* lookup proc */
4674
return o_push_estack;
4678
unsigned char *ptr = (unsigned char *)pcs->params.indexed.lookup.table.data;
4681
/* We have a string, start by retrieving the index from the op stack */
4682
/* Make sure its an integer! */
4683
if (!r_has_type(op, t_integer))
4684
return_error (e_typecheck);
4685
index = op->value.intval;
4686
/* And remove it from the stack. */
4690
/* Make sure we have enough space on the op stack to hold
4691
* one value for each component of the alternate space
4693
push(pcs->params.indexed.n_comps);
4694
op -= pcs->params.indexed.n_comps - 1;
4696
/* Move along the lookup table, one byte for each component , the
4697
* number of times required to get to the lookup for this index
4699
ptr += index * pcs->params.indexed.n_comps;
4701
/* For all the components of the alternate space, push the value
4702
* of the component on the stack. The value is given by the byte
4703
* from the lookup table divided by 255 to give a value between
4706
for (i = 0; i < pcs->params.indexed.n_comps; i++, op++) {
4707
float rval = (*ptr++) / 255.0;
4708
make_real(op, rval);
4718
static int indexedvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
4725
return_error(e_stackunderflow);
4727
if (!r_has_type(op, t_integer) && !r_has_type(op, t_real))
4728
return_error(e_typecheck);
4730
code = array_get(imemory, space, 2, &hival);
4734
if (*values > hival.value.intval)
4735
*values = (float)hival.value.intval;
4740
/* The PLRM says 'If it is a real number, it is rounded to the nearest integer
4741
* but in fact Acrobat simply floors the value.
4743
*values = floor(*values);
4749
static int setpatternspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
4751
gs_color_space *pcs;
4752
gs_color_space *pcs_base;
4753
uint edepth = ref_stack_count(&e_stack);
4756
if (i_ctx_p->language_level < 2)
4757
return_error(e_undefined);
4761
if (r_is_array(r)) {
4764
switch (r_size(r)) {
4765
case 1: /* no base space */
4769
return_error(e_rangecheck);
4771
pcs_base = gs_currentcolorspace(igs);
4772
if (cs_num_components(pcs_base) < 0) /* i.e., Pattern space */
4773
return_error(e_rangecheck);
4776
pcs = gs_cspace_alloc(imemory, &gs_color_space_type_Pattern);
4777
pcs->base_space = pcs_base;
4778
pcs->params.pattern.has_base_space = (pcs_base != NULL);
4779
rc_increment_cs(pcs_base);
4780
code = gs_setcolorspace(igs, pcs);
4781
/* release reference from construction */
4782
rc_decrement_only_cs(pcs, "zsetpatternspace");
4784
ref_stack_pop_to(&e_stack, edepth);
4787
make_null(&istate->pattern[0]); /* PLRM: initial color value is a null object */
4789
return (ref_stack_count(&e_stack) == edepth ? 0 : o_push_estack); /* installation will load the caches */
4791
static int validatepatternspace(i_ctx_t * i_ctx_p, ref **r)
4796
/* since makepattern has already been run, we don't need to do much validation */
4797
if (!r_has_type(*r, t_name)) {
4798
if (r_is_array(*r)) {
4799
if (r_size(*r) > 1) {
4800
code = array_get(imemory, *r, 1, &tref);
4803
ref_assign(*r, &tref);
4807
return_error(e_typecheck);
4812
static int patternalternatespace(i_ctx_t * i_ctx_p, ref *space, ref **r, int *CIESubst)
4817
if (!r_has_type(*r, t_name)) {
4818
if (r_is_array(*r)) {
4819
if (r_size(*r) > 1) {
4820
code = array_get(imemory, space, 1, &tref);
4823
ref_assign(*r, &tref);
4827
return_error(e_typecheck);
4832
static int patterncomponent(i_ctx_t * i_ctx_p, ref *space, int *n)
4836
const gs_color_space * pcs = gs_currentcolorspace(igs);
4839
/* check for a pattern color space */
4840
if ((n_comps = cs_num_components(pcs)) < 0) {
4842
if (r_has_type(op, t_dictionary)) {
4843
ref *pImpl, pPatInst;
4845
code = dict_find_string(op, "Implementation", &pImpl);
4848
code = array_get(imemory, pImpl, 0, &pPatInst);
4851
cc.pattern = r_ptr(&pPatInst, gs_pattern_instance_t);
4852
if (pattern_instance_uses_base_space(cc.pattern))
4859
return_error(e_typecheck);
4863
static int patternbasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth)
4866
int i, components=0;
4868
if (r_size(space) > 1) {
4869
const gs_color_space * pcs = gs_currentcolorspace(igs);
4870
const gs_client_color * pcc = gs_currentcolor(igs);
4871
int n = cs_num_components(pcs);
4872
bool push_pattern = n < 0;
4873
gs_pattern_instance_t * pinst = pcc->pattern;
4875
if (pinst != 0 && pattern_instance_uses_base_space(pinst)) {
4876
/* check for pattern */
4878
pop(1); /* The pattern instance */
4883
/* If the pattern isn't yet initialised, or doesn't use the
4884
* base space, treat as uncolored and return defaults below
4905
for (i=0;i<components;i++) {
4906
make_real(op, (float)0);
4909
if (components == 4) {
4911
make_real(op, (float)1);
4917
static int patternvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
4923
if (!r_has_type(op, t_dictionary) && !r_has_type(op, t_null))
4924
return_error(e_typecheck);
4930
static int setdevicepspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
4933
gs_color_space *pcs;
4936
/* The comment in the original PostScript (gs_lev2.ps) said
4937
* "DevicePixel is actually a LanguageLevel 3 feature; it is here for
4938
* historical reasons." Actually DevicePixel is a Display PostScript
4939
* space, as far as I can tell. It certainly isn't a level 3 space.
4940
* Preserve the old behaviour anyway.
4942
if (i_ctx_p->language_level < 2)
4943
return_error(e_undefined);
4946
code = array_get(imemory, r, 1, &bpp);
4949
if (!r_has_type(&bpp, t_integer))
4950
return_error(e_typecheck);
4951
code = gs_cspace_new_DevicePixel(imemory, &pcs, (int)bpp.value.intval);
4954
code = gs_setcolorspace(igs, pcs);
4955
/* release reference from construction */
4957
rc_decrement_only_cs(pcs, "setseparationspace");
4960
static int validatedevicepspace(i_ctx_t * i_ctx_p, ref **space)
4963
ref *r = *space, bpp;
4966
return_error(e_typecheck);
4967
/* Validate parameters, check we have enough operands */
4969
return_error(e_rangecheck);
4970
/* Make sure 'bits per pixel' is an integer */
4971
code = array_get(imemory, r, 1, &bpp);
4974
if (!r_has_type(&bpp, t_integer))
4975
return_error(e_typecheck);
4977
/* Make sure 'bits per pixel' lies between 0 and 31 */
4978
if (bpp.value.intval < 0 || bpp.value.intval > 31)
4979
return_error(e_rangecheck);
4984
static int devicepdomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
4989
code = array_get(imemory, space, 1, &tref);
4993
ptr[1] = (float)(1 << tref.value.intval);
4996
static int deviceprange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
5001
code = array_get(imemory, space, 1, &tref);
5005
ptr[1] = (float)(1 << tref.value.intval);
5008
static int devicepbasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth)
5017
static int devicepvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
5022
static int set_dev_space(i_ctx_t * i_ctx_p, int components)
5024
int code, stage = 1, cont = 0;
5025
switch(components) {
5027
code = setgrayspace(i_ctx_p, (ref *)0, &stage, &cont, 1);
5030
code = setrgbspace(i_ctx_p, (ref *)0, &stage, &cont, 1);
5033
code = setcmykspace(i_ctx_p, (ref *)0, &stage, &cont, 1);
5036
code = gs_note_error(e_rangecheck);
5044
/* Check that the range of a the ab values is valid */
5045
static int checkrangeab(i_ctx_t * i_ctx_p, ref *labdict)
5049
ref *tempref, valref;
5051
code = dict_find_string(labdict, "Range", &tempref);
5052
if (code >= 0 && !r_has_type(tempref, t_null)) {
5053
if (!r_is_array(tempref))
5054
return_error(e_typecheck);
5055
if (r_size(tempref) != 4)
5056
return_error(e_rangecheck);
5059
code = array_get(imemory, tempref, i, &valref);
5062
if (r_has_type(&valref, t_integer))
5063
value[i] = (float)valref.value.intval;
5064
else if (r_has_type(&valref, t_real))
5065
value[i] = (float)valref.value.realval;
5067
return_error(e_typecheck);
5069
if (value[1] < value[0] || value[3] < value[2] )
5070
return_error(e_rangecheck);
5075
static int setlabspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont,
5078
/* In this case, we will treat this as an ICC color space, with a
5079
CIELAB 16 bit profile */
5082
float range_buff[4], white[3], black[3];
5083
static const float dflt_range[4] = { -100, 100, -100, 100 };
5084
static const float dflt_black[3] = {0,0,0}, dflt_white[3] = {0,0,0};
5089
code = array_get(imemory, r, 1, &labdict);
5092
/* Get all the parts */
5093
code = dict_floats_param( imemory, &labdict, "Range", 4, range_buff,
5095
for (i = 0; i < 4 && range_buff[i + 1] >= range_buff[i]; i += 2);
5097
return_error(e_rangecheck);
5098
code = dict_floats_param( imemory, &labdict, "BlackPoint", 3, black,
5100
code = dict_floats_param( imemory, &labdict, "WhitePoint", 3, white,
5102
if (white[0] <= 0 || white[1] != 1.0 || white[2] <= 0)
5103
return_error(e_rangecheck);
5104
code = seticc_lab(i_ctx_p, white, black, range_buff);
5106
return gs_rethrow(code, "setting PDF lab color space");
5109
cc.paint.values[i] = 0;
5110
code = gs_setcolor(igs, &cc);
5114
static int validatelabspace(i_ctx_t * i_ctx_p, ref **r)
5117
ref *space, labdict;
5120
if (!r_is_array(space))
5121
return_error(e_typecheck);
5122
/* Validate parameters, check we have enough operands */
5123
if (r_size(space) < 2)
5124
return_error(e_rangecheck);
5125
code = array_get(imemory, space, 1, &labdict);
5128
/* Check the white point, which is required. */
5129
code = checkWhitePoint(i_ctx_p, &labdict);
5132
/* The rest are optional. Need to validate though */
5133
code = checkBlackPoint(i_ctx_p, &labdict);
5136
/* Range on a b values */
5137
code = checkrangeab(i_ctx_p, &labdict);
5140
*r = 0; /* No nested space */
5144
static int labrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
5147
ref CIEdict, *tempref, valref;
5149
code = array_get(imemory, space, 1, &CIEdict);
5153
/* If we have a Range entry, get the values from that */
5154
code = dict_find_string(&CIEdict, "Range", &tempref);
5155
if (code >= 0 && !r_has_type(tempref, t_null)) {
5157
code = array_get(imemory, tempref, i, &valref);
5160
if (r_has_type(&valref, t_integer))
5161
ptr[i] = (float)valref.value.intval;
5162
else if (r_has_type(&valref, t_real))
5163
ptr[i] = (float)valref.value.realval;
5165
return_error(e_typecheck);
5168
/* Default values for Lab */
5171
ptr[(2 * i) + 1] = 100;
5178
static int labdomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
5181
ref CIEdict, *tempref, valref;
5183
code = array_get(imemory, space, 1, &CIEdict);
5187
/* If we have a Range, get the values from that */
5188
code = dict_find_string(&CIEdict, "Range", &tempref);
5189
if (code >= 0 && !r_has_type(tempref, t_null)) {
5191
code = array_get(imemory, tempref, i, &valref);
5194
if (r_has_type(&valref, t_integer))
5195
ptr[i] = (float)valref.value.intval;
5196
else if (r_has_type(&valref, t_real))
5197
ptr[i] = (float)valref.value.realval;
5199
return_error(e_typecheck);
5202
/* Default values for Lab */
5205
ptr[(2 * i) + 1] = 100;
5211
static int labbasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth)
5214
int i, components=1;
5222
for (i=0;i<components;i++) {
5223
make_real(op, (float)0);
5231
static int labvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
5237
return_error(e_stackunderflow);
5240
if (!r_has_type(op, t_integer) && !r_has_type(op, t_real))
5241
return_error(e_typecheck);
5247
/* Check that the Matrix of a CalRGB and CalGray space is valid */
5248
static int checkCalMatrix(i_ctx_t * i_ctx_p, ref *CIEdict)
5252
ref *tempref, valref;
5254
code = dict_find_string(CIEdict, "Matrix", &tempref);
5255
if (code >= 0 && !r_has_type(tempref, t_null)) {
5256
if (!r_is_array(tempref))
5257
return_error(e_typecheck);
5258
if (r_size(tempref) != 9)
5259
return_error(e_rangecheck);
5261
code = array_get(imemory, tempref, i, &valref);
5264
if (r_has_type(&valref, t_integer))
5265
value[i] = (float)valref.value.intval;
5266
else if (r_has_type(&valref, t_real))
5267
value[i] = (float)valref.value.realval;
5269
return_error(e_typecheck);
5275
/* Check that the Gamma of a CalRGB and CalGray space is valid */
5276
static int checkGamma(i_ctx_t * i_ctx_p, ref *CIEdict, int numvalues)
5280
ref *tempref, valref;
5282
code = dict_find_string(CIEdict, "Gamma", &tempref);
5283
if (code >= 0 && !r_has_type(tempref, t_null)) {
5284
if (numvalues > 1) {
5285
/* Array of gammas (RGB) */
5286
if (!r_is_array(tempref))
5287
return_error(e_typecheck);
5288
if (r_size(tempref) != numvalues)
5289
return_error(e_rangecheck);
5290
for (i=0;i<numvalues;i++) {
5291
code = array_get(imemory, tempref, i, &valref);
5294
if (r_has_type(&valref, t_integer))
5295
value[i] = (float)valref.value.intval;
5296
else if (r_has_type(&valref, t_real))
5297
value[i] = (float)valref.value.realval;
5299
return_error(e_typecheck);
5300
if (value[i] <= 0) return_error(e_rangecheck);
5303
/* Single gamma (gray) */
5304
if (r_has_type(tempref, t_real))
5305
value[0] = (float)(tempref->value.realval);
5306
else if (r_has_type(tempref, t_integer))
5307
value[0] = (float)(tempref->value.intval);
5309
return_error(e_typecheck);
5310
if (value[0] <= 0) return_error(e_rangecheck);
5316
/* Here we set up an equivalent ICC form for the CalGray color space */
5317
static int setcalgrayspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
5321
float gamma, white[3], black[3];
5322
floatp dflt_gamma = 1.0;
5323
static const float dflt_black[3] = {0,0,0}, dflt_white[3] = {0,0,0};
5327
code = array_get(imemory, r, 1, &graydict);
5330
/* Get all the parts */
5331
code = dict_float_param(&graydict, "Gamma",
5332
dflt_gamma, &gamma);
5333
if (gamma <= 0 ) return_error(e_rangecheck);
5334
code = dict_floats_param( imemory,
5340
code = dict_floats_param( imemory,
5346
if (white[0] <= 0 || white[1] != 1.0 || white[2] <= 0)
5347
return_error(e_rangecheck);
5348
code = seticc_cal(i_ctx_p, white, black, &gamma, NULL, 1,
5349
graydict.value.saveid);
5351
return gs_rethrow(code, "setting CalGray color space");
5353
cc.paint.values[0] = 0;
5354
code = gs_setcolor(igs, &cc);
5358
static int validatecalgrayspace(i_ctx_t * i_ctx_p, ref **r)
5361
ref *space, calgraydict;
5364
if (!r_is_array(space))
5365
return_error(e_typecheck);
5366
/* Validate parameters, check we have enough operands */
5367
if (r_size(space) < 2)
5368
return_error(e_rangecheck);
5369
code = array_get(imemory, space, 1, &calgraydict);
5372
/* Check the white point, which is required */
5373
/* We have to have a white point */
5374
/* Check white point exists, and is an array of three numbers */
5375
code = checkWhitePoint(i_ctx_p, &calgraydict);
5378
/* The rest are optional. Need to validate though */
5379
code = checkBlackPoint(i_ctx_p, &calgraydict);
5382
/* Check Gamma values */
5383
code = checkGamma(i_ctx_p, &calgraydict, 1);
5386
*r = 0; /* No nested space */
5390
/* Here we set up an equivalent ICC form for the CalRGB color space */
5391
static int setcalrgbspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
5395
float gamma[3], white[3], black[3], matrix[9];
5396
static const float dflt_gamma[3] = { 1.0, 1.0, 1.0 };
5397
static const float dflt_black[3] = {0,0,0}, dflt_white[3] = {0,0,0};
5398
static const float dflt_matrix[9] = {1,0,0,0,1,0,0,0,1};
5403
code = array_get(imemory, r, 1, &rgbdict);
5406
/* Get all the parts */
5407
code = dict_floats_param( imemory,
5413
if (gamma[0] <= 0 || gamma[1] <= 0 || gamma[2] <= 0)
5414
return_error(e_rangecheck);
5415
code = dict_floats_param( imemory,
5421
code = dict_floats_param( imemory,
5427
if (white[0] <= 0 || white[1] != 1.0 || white[2] <= 0)
5428
return_error(e_rangecheck);
5429
code = dict_floats_param( imemory,
5435
code = seticc_cal(i_ctx_p, white, black, gamma, matrix, 3, rgbdict.value.saveid);
5437
return gs_rethrow(code, "setting CalRGB color space");
5440
cc.paint.values[i] = 0;
5441
code = gs_setcolor(igs, &cc);
5445
static int validatecalrgbspace(i_ctx_t * i_ctx_p, ref **r)
5448
ref *space, calrgbdict;
5451
if (!r_is_array(space))
5452
return_error(e_typecheck);
5453
/* Validate parameters, check we have enough operands */
5454
if (r_size(space) < 2)
5455
return_error(e_rangecheck);
5456
code = array_get(imemory, space, 1, &calrgbdict);
5459
/* Check the white point, which is required */
5460
code = checkWhitePoint(i_ctx_p, &calrgbdict);
5463
/* The rest are optional. Need to validate though */
5464
code = checkBlackPoint(i_ctx_p, &calrgbdict);
5467
/* Check Gamma values */
5468
code = checkGamma(i_ctx_p, &calrgbdict, 3);
5472
code = checkCalMatrix(i_ctx_p, &calrgbdict);
5475
*r = 0; /* No nested space */
5480
static int iccrange(i_ctx_t * i_ctx_p, ref *space, float *ptr);
5481
static int seticcspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
5484
ref ICCdict, *tempref, *altref=NULL, *nocie;
5485
int components, code;
5488
code = dict_find_string(systemdict, "NOCIE", &nocie);
5491
if (!r_has_type(nocie, t_boolean))
5492
return_error(e_typecheck);
5498
code = array_get(imemory, r, 1, &ICCdict);
5501
code = dict_find_string(&ICCdict, "N", &tempref);
5504
components = tempref->value.intval;
5506
/* Don't allow ICCBased spaces if NOCIE is true */
5507
if (nocie->value.boolval) {
5508
code = dict_find_string(&ICCdict, "Alternate", &altref); /* Alternate is optional */
5511
if ((altref != NULL) && (r_type(altref) != t_null)) {
5512
/* The PDF interpreter sets a null Alternate. If we have an
5513
* Alternate, and its not null, and NOCIE is true, then use the
5514
* Alternate instead of the ICC
5517
ref_assign(op, altref);
5518
/* If CIESubst, we are already substituting for CIE, so use nosubst
5519
* to prevent further substitution!
5521
return setcolorspace_nosubst(i_ctx_p);
5523
/* There's no /Alternate (or it is null), set a default space
5524
* based on the number of components in the ICCBased space
5526
code = set_dev_space(i_ctx_p, components);
5532
code = iccrange(i_ctx_p, r, (float *)&range);
5535
code = dict_find_string(&ICCdict, "DataSource", &tempref);
5538
/* Check for string based ICC and convert to a file */
5539
if (r_has_type(tempref, t_string)){
5540
uint n = r_size(tempref);
5543
code = make_rss(i_ctx_p, &rss, tempref->value.const_bytes, n, r_space(tempref), 0L, n, false);
5546
ref_assign(tempref, &rss);
5548
/* Make space on operand stack to pass the ICC dictionary */
5550
ref_assign(op, &ICCdict);
5551
code = seticc(i_ctx_p, components, op, (float *)&range);
5553
code = dict_find_string(&ICCdict, "Alternate", &altref); /* Alternate is optional */
5556
if ((altref != NULL) && (r_type(altref) != t_null)) {
5557
/* We have a /Alternate in the ICC space */
5558
/* Our ICC dictionary still on operand stack, we can reuse the
5559
* slot on the stack to hold the alternate space.
5561
ref_assign(op, (ref *)altref);
5562
/* If CIESubst, we are already substituting for CIE, so use nosubst
5563
* to prevent further substitution!
5566
return setcolorspace_nosubst(i_ctx_p);
5568
return zsetcolorspace(i_ctx_p);
5570
/* We have no /Alternate in the ICC space, use hte /N key to
5571
* determine an 'appropriate' default space.
5573
code = set_dev_space(i_ctx_p, components);
5585
/* All done, exit */
5590
return_error (e_rangecheck);
5596
static int validateiccspace(i_ctx_t * i_ctx_p, ref **r)
5598
int code=0, i, components = 0;
5599
ref *space, *tempref, valref, ICCdict, sref;
5602
if (!r_is_array(space))
5603
return_error(e_typecheck);
5604
/* Validate parameters, check we have enough operands */
5605
if (r_size(space) != 2)
5606
return_error(e_rangecheck);
5608
code = array_get(imemory, space, 1, &ICCdict);
5612
code = dict_find_string(&ICCdict, "N", &tempref);
5615
if (!r_has_type(tempref, t_null)) {
5616
if (!r_has_type(tempref, t_integer))
5617
return_error(e_typecheck);
5618
components = tempref->value.intval;
5620
return_error(e_typecheck);
5621
code = dict_find_string(&ICCdict, "DataSource", &tempref);
5623
return_error(e_typecheck);
5624
if (!r_has_type(tempref, t_null)) {
5625
if (!r_has_type(tempref, t_string) && !r_has_type(tempref, t_file))
5626
return_error(e_typecheck);
5628
return_error(e_typecheck);
5630
/* Following are optional entries */
5631
code = dict_find_string(&ICCdict, "Range", &tempref);
5632
if (code >= 0 && !r_has_type(tempref, t_null)) {
5633
if (!r_is_array(tempref))
5634
return_error(e_typecheck);
5635
if (r_size(tempref) < (components * 2))
5636
return_error(e_rangecheck);
5637
for (i=0;i<components * 2;i++) {
5638
code = array_get(imemory, tempref, i, &valref);
5641
if (!r_has_type(&valref, t_integer) && !r_has_type(&valref, t_real))
5642
return_error(e_typecheck);
5645
code = dict_find_string(&ICCdict, "Alternate", &tempref);
5646
if (code >= 0 && !r_has_type(tempref, t_null)) {
5647
ref_assign(*r, tempref);
5648
if (r_has_type(tempref, t_name)) {
5649
name_string_ref(imemory, tempref, &sref);
5650
if (sref.value.bytes && strncmp((const char *)sref.value.bytes, "Pattern", 7) == 0)
5651
return_error(e_typecheck);
5653
if (r_is_array(tempref)) {
5654
code = array_get(imemory, tempref, 0, &valref);
5657
if (!r_has_type(&valref, t_name) && !r_has_type(&valref, t_string))
5658
return_error(e_typecheck);
5659
if (r_has_type(&valref, t_name))
5660
name_string_ref(imemory, &valref, &sref);
5662
sref.value.bytes = valref.value.bytes;
5663
if (sref.value.bytes && strncmp((const char *)sref.value.bytes, "Pattern", 7) == 0)
5664
return_error(e_typecheck);
5666
return_error(e_typecheck);
5671
switch (components) {
5673
code = name_enter_string(imemory, "DeviceGray", &nameref);
5676
code = name_enter_string(imemory, "DeviceRGB", &nameref);
5679
code = name_enter_string(imemory, "DeviceCMYK", &nameref);
5682
return_error(e_rangecheck);
5684
/* In case this space is the /ALternate for a previous ICCBased space
5685
* insert the named space into the ICC dictionary. If we simply returned
5686
* the named space, as before, then we are replacing the second ICCBased
5687
* space in the first ICCBased space with the named space!
5689
code = idict_put_string(&ICCdict, "Alternate", &nameref);
5693
/* And now revalidate with the newly updated dictionary */
5694
return validateiccspace(i_ctx_p, r);
5699
static int iccalternatespace(i_ctx_t * i_ctx_p, ref *space, ref **r, int *CIESubst)
5701
int components, code = 0;
5702
ref *tempref, ICCdict;
5704
if (!r_is_array(space))
5705
return_error(e_typecheck);
5706
/* Validate parameters, check we have enough operands */
5707
if (r_size(space) != 2)
5708
return_error(e_rangecheck);
5710
code = array_get(imemory, space, 1, &ICCdict);
5714
code = dict_find_string(&ICCdict, "N", &tempref);
5718
components = tempref->value.intval;
5720
code = dict_find_string(&ICCdict, "Alternate", &tempref);
5721
if (code >= 0 && !r_has_type(tempref, t_null)) {
5724
switch (components) {
5726
code = name_enter_string(imemory, "DeviceGray", *r);
5729
code = name_enter_string(imemory, "DeviceRGB", *r);
5732
code = name_enter_string(imemory, "DeviceCMYK", *r);
5735
return_error(e_rangecheck);
5741
static int icccomponents(i_ctx_t * i_ctx_p, ref *space, int *n)
5744
ref *tempref, ICCdict;
5746
code = array_get(imemory, space, 1, &ICCdict);
5750
code = dict_find_string(&ICCdict, "N", &tempref);
5751
*n = tempref->value.intval;
5754
static int iccdomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
5756
int components, i, code = 0;
5757
ref *tempref, ICCdict, valref;
5759
code = array_get(imemory, space, 1, &ICCdict);
5762
code = dict_find_string(&ICCdict, "N", &tempref);
5763
components = tempref->value.intval;
5764
code = dict_find_string(&ICCdict, "Range", &tempref);
5765
if (code >= 0 && !r_has_type(tempref, t_null)) {
5766
for (i=0;i<components * 2;i++) {
5767
code = array_get(imemory, tempref, i, &valref);
5770
if (r_has_type(&valref, t_integer))
5771
ptr[i * 2] = (float)valref.value.intval;
5773
ptr[i * 2] = valref.value.realval;
5776
for (i=0;i<components;i++) {
5778
ptr[(i * 2) + 1] = 1;
5783
static int iccrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
5785
int components, i, code = 0;
5786
ref *tempref, ICCdict, valref;
5788
code = array_get(imemory, space, 1, &ICCdict);
5791
code = dict_find_string(&ICCdict, "N", &tempref);
5792
components = tempref->value.intval;
5793
code = dict_find_string(&ICCdict, "Range", &tempref);
5794
if (code >= 0 && !r_has_type(tempref, t_null)) {
5795
for (i=0;i<components * 2;i++) {
5796
code = array_get(imemory, tempref, i, &valref);
5799
if (r_has_type(&valref, t_integer))
5800
ptr[i] = (float)valref.value.intval;
5802
ptr[i] = (float)valref.value.realval;
5805
for (i=0;i<components;i++) {
5807
ptr[(i * 2) + 1] = 1;
5812
static int iccbasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth)
5818
static int iccvalidate(i_ctx_t *i_ctx_p, ref *space, float *values, int num_comps)
5823
static int dummydomain(i_ctx_t * i_ctx_p, ref *space, float *ptr)
5827
static int dummyrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)
5831
static int onecomponent(i_ctx_t * i_ctx_p, ref *space, int *n)
5836
static int threecomponent(i_ctx_t * i_ctx_p, ref *space, int *n)
5841
static int fourcomponent(i_ctx_t * i_ctx_p, ref *space, int *n)
5846
static int truecompareproc(i_ctx_t *i_ctx_p, ref *space, ref *testspace)
5850
static int falsecompareproc(i_ctx_t *i_ctx_p, ref *space, ref *testspace)
5855
PS_colour_space_t colorProcs[] = {
5856
{(char *)"DeviceGray", setgrayspace, 0, 0, onecomponent, grayrange, graydomain,
5857
graybasecolor, 0, grayvalidate, truecompareproc, grayinitialproc},
5858
{(char *)"DeviceRGB", setrgbspace, 0, 0, threecomponent, rgbrange, rgbdomain,
5859
rgbbasecolor, 0, rgbvalidate, truecompareproc, rgbinitialproc},
5860
{(char *)"DeviceCMYK", setcmykspace, 0, 0, fourcomponent, cmykrange, cmykdomain,
5861
cmykbasecolor, 0, cmykvalidate, truecompareproc, cmykinitialproc},
5862
{(char *)"CIEBasedA", setcieaspace, validatecieaspace, 0, onecomponent, ciearange, cieadomain,
5863
ciebasecolor, 0, cieavalidate, cieacompareproc, 0},
5864
{(char *)"CIEBasedABC", setcieabcspace, validatecieabcspace, 0, threecomponent, cieabcrange, cieabcdomain,
5865
ciebasecolor, 0, cieabcvalidate, cieabccompareproc, 0},
5866
{(char *)"CIEBasedDEF", setciedefspace, validateciedefspace, 0, threecomponent, ciedefrange, ciedefdomain,
5867
ciebasecolor, 0, ciedefvalidate, ciedefcompareproc, 0},
5868
{(char *)"CIEBasedDEFG", setciedefgspace, validateciedefgspace, 0, fourcomponent, ciedefgrange, ciedefgdomain,
5869
ciebasecolor, 0, ciedefgvalidate, ciedefgcompareproc, 0},
5870
{(char *)"Separation", setseparationspace, validateseparationspace, separationalternatespace, onecomponent, seprange, sepdomain,
5871
sepbasecolor, septransform, sepvalidate, sepcompareproc, sepinitialproc},
5872
{(char *)"DeviceN", setdevicenspace, validatedevicenspace, devicenalternatespace, devicencomponents, devicenrange, devicendomain,
5873
devicenbasecolor, devicentransform, devicenvalidate, devicencompareproc, deviceninitialproc},
5874
{(char *)"Indexed", setindexedspace, validateindexedspace, indexedalternatespace, onecomponent, indexedrange, indexeddomain,
5875
indexedbasecolor, 0, indexedvalidate, falsecompareproc, 0},
5876
{(char *)"Pattern", setpatternspace, validatepatternspace, patternalternatespace, patterncomponent, dummyrange, dummydomain,
5877
patternbasecolor, 0, patternvalidate, falsecompareproc, 0},
5878
{(char *)"DevicePixel", setdevicepspace, validatedevicepspace, 0, onecomponent, deviceprange, devicepdomain,
5879
devicepbasecolor, 0, devicepvalidate, falsecompareproc, 0},
5880
{(char *)"ICCBased", seticcspace, validateiccspace, iccalternatespace, icccomponents, iccrange, iccdomain,
5881
iccbasecolor, 0, iccvalidate, falsecompareproc, 0},
5882
{(char *)"Lab", setlabspace, validatelabspace, 0, threecomponent, labrange, labdomain,
5883
labbasecolor, 0, labvalidate, truecompareproc, 0},
5884
{(char *)"CalGray", setcalgrayspace, validatecalgrayspace, 0, onecomponent, grayrange, graydomain,
5885
graybasecolor, 0, grayvalidate, truecompareproc, grayinitialproc},
5886
{(char *)"CalRGB", setcalrgbspace, validatecalrgbspace, 0, threecomponent, rgbrange, rgbdomain,
5887
rgbbasecolor, 0, rgbvalidate, truecompareproc, rgbinitialproc}
5891
* Given a color space, this finds the appropriate object from the list above
5893
int get_space_object(i_ctx_t *i_ctx_p, ref *arr, PS_colour_space_t **obj)
5895
ref spacename, nref;
5896
int i, nprocs = sizeof(colorProcs) / sizeof(PS_colour_space_t), code;
5898
/* If the spaece is an array, the first element is always the name */
5899
if (r_is_array(arr))
5900
code = array_get(imemory, arr, 0, &spacename);
5902
ref_assign(&spacename, arr);
5904
/* Check that it really is a name */
5905
if (!r_has_type(&spacename, t_name))
5906
return_error(e_typecheck);
5908
/* Find the relevant color space object */
5909
for (i=0;i<nprocs;i++) {
5910
code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)colorProcs[i].name, strlen(colorProcs[i].name), &nref, 0);
5913
if (name_eq(&spacename, &nref)) {
5914
*obj = &colorProcs[i];
5918
return_error(e_undefined);
5921
* This routine checks all the color spaces in an operand by
5922
* calling the specific 'validate' method for each in turn. It also
5923
* returns the 'depth' which is the number of nested spaces.
5925
static int validate_spaces(i_ctx_t *i_ctx_p, ref *arr, int *depth)
5927
ref space, *sp = &space;
5929
PS_colour_space_t *obj;
5931
ref_assign(&space, arr);
5934
code = get_space_object(i_ctx_p, sp, &obj);
5939
if (!obj->validateproc)
5942
code = obj->validateproc(i_ctx_p, &sp);
5949
* The routine which does all the setcolor dispatching. This is initially set up by
5950
* zsetcolor above. Because setcolorspace samples the space and converts the tint
5951
* transform to a function, we don't need to run the PS tint transform in order to
5952
* set the color. However, some applications, notably Photoshop 5 and above, rely
5953
* on the tint transform being executed, so we must do so if the normal PostScript
5954
* processing would result in the tintr transform being executed.
5956
* We check each space in turn to see whether we would normally run the tint
5957
* transform, eg Indexed is always executed, Separation and DeviceN only if the
5958
* required ink(s) aren't present in the device. If we discover that any space
5959
* doesn't require a tint transform, then we can short-circuit the processing.
5960
* Otherwise we set up to execute the tint transform.
5963
setcolor_cont(i_ctx_t *i_ctx_p)
5965
ref arr, *parr = &arr;
5967
int i=0, code = 0,depth, usealternate, stage, stack_depth, CIESubst = 0;
5968
PS_colour_space_t *obj;
5970
stack_depth = (int)ep[-3].value.intval;
5971
depth = (int)ep[-2].value.intval;
5972
stage = (int)ep[-1].value.intval;
5973
/* If we get a continuation from a sub-procedure, we will want to come back
5974
* here afterward, to do any remaining spaces. We need to set up for that now.
5975
* so that our continuation is ahead of the sub-proc's continuation.
5978
push_op_estack(setcolor_cont);
5981
ref_assign(&arr, ep);
5982
/* Run along the nested color spaces until we get to the first one
5983
* that we haven't yet processed (given by 'depth')
5985
for (i=0;i<=depth;i++) {
5986
code = get_space_object(i_ctx_p, parr, &obj);
5991
if (!obj->alternateproc) {
5992
return_error(e_typecheck);
5994
code = obj->alternateproc(i_ctx_p, parr, &parr, &CIESubst);
5999
if (obj->runtransformproc) {
6000
code = obj->runtransformproc(i_ctx_p, &istate->colorspace[0].array, &usealternate, &stage, &stack_depth);
6001
make_int(&ep[-3], stack_depth);
6002
make_int(&ep[-1], stage);
6006
make_int(&ep[-2], ++depth);
6012
/* Remove our next continuation and our data */
6013
obj->numcomponents(i_ctx_p, parr, &i);
6016
return o_pop_estack;
6019
* The routine which does all the setcolorspace dispatching. This is initially set up by
6020
* zsetcolorspace above. It starts by descending to the bottom-most space
6021
* and setting that as the current space. It then descends the array again
6022
* to the next-to-bottom- space and sets that as the current, and so on.
6024
* The 'stage' parameter is passed in to each 'set' method. If a method needs
6025
* to do a continuation itself (eg sample a space) then it should set the stage
6026
* to a non-zero value. When the continuation is complete we return here, and
6027
* attempt to 'set' the same space again. This time stage will be whatever was
6028
* set the first time, which is a signal to the 'set' routine that a continuation
6029
* took place, and is complete. Stage must always be set to 0 when a 'set'
6030
* of a color space is complete.
6033
setcolorspace_cont(i_ctx_t *i_ctx_p)
6035
ref arr, *parr = &arr;
6037
es_ptr ep = esp, pdepth, pstage, pCIESubst;
6038
int i, code = 0,depth, stage, cont, CIESubst = 0;
6039
PS_colour_space_t *obj;
6041
pCIESubst = &ep[-3];
6045
CIESubst = (int)pCIESubst->value.intval;
6046
depth = (int)pdepth->value.intval;
6047
stage = (int)pstage->value.intval;
6048
/* If we get a continuation from a sub-procedure, we will want to come back
6049
* here afterward, to do any remaining stages. We need to set up for that now.
6050
* so that our continuation is ahead of the sub-proc's continuation.
6053
push_op_estack(setcolorspace_cont);
6055
while (code == 0 && depth) {
6056
ref_assign(&arr, ep);
6057
/* Run along the nested color spaces until we get to the lowest one
6058
* that we haven't yet processed (given by 'depth')
6060
for (i = 0;i < depth;i++) {
6061
code = get_space_object(i_ctx_p, parr, &obj);
6065
if (i < (depth - 1)) {
6066
if (!obj->alternateproc) {
6067
return_error(e_typecheck);
6069
code = obj->alternateproc(i_ctx_p, parr, &parr, &CIESubst);
6075
code = obj->setproc(i_ctx_p, parr, &stage, &cont, CIESubst);
6076
make_int(pstage, stage);
6080
/* Completed that space, decrement the 'depth' */
6081
make_int(pdepth, --depth);
6086
/* Remove our next continuation and our data */
6089
istate->colorspace[0].array = *op;
6090
/* Remove the colorspace array form the operand stack */
6092
code = o_pop_estack;
6097
* The routine which does all the dispatching for the device-space specific
6098
* operators below (eg setgray). This is initially set up by the routines below.
6100
* It would seem unnecessary to have a continuation procedure, because at first
6101
* sight these can only be a single space with no alternate and can't require
6102
* sampling, because they are device space. However if UseCIEColor is true, then
6103
* we will actually use a Default Color Space Array in place of the requested color
6104
* space. These are often CIEBased spaces, and these do need to be sampled. So
6105
* actually we do need a continuation procedure, unfortunately.
6107
* Also, we need to set the initial color value after we have set the color space.
6110
setdevicecolor_cont(i_ctx_t *i_ctx_p)
6113
es_ptr ep = esp, pstage;
6114
int code = 0, stage, base;
6117
base = (int)ep[-1].value.intval;
6118
stage = (int)pstage->value.intval;
6119
/* If we get a continuation from a sub-procedure, we will want to come back
6120
* here afterward, to do any remaining stages. We need to set up for that now.
6121
* so that our continuation is ahead of the sub-proc's continuation.
6124
/* May need to push a /Device... name on the stack so make sure we have space */
6126
/* The push_op_estack macro increments esp before use, so we don't need to */
6127
push_op_estack(setdevicecolor_cont);
6132
make_int(pstage, ++stage);
6135
case 0: /* DeviceGray */
6136
code = name_enter_string(imemory, "DeviceGray", op);
6138
case 1: /* DeviceRGB */
6139
code = name_enter_string(imemory, "DeviceRGB", op);
6141
case 2: /* DeviceCMYK */
6142
code = name_enter_string(imemory, "DeviceCMYK", op);
6147
code = zsetcolorspace(i_ctx_p);
6152
make_int(pstage, ++stage);
6153
code = zsetcolor(i_ctx_p);
6159
return o_pop_estack;
6166
/* These routines implement the device-space set color routines
6167
* These set both the space and the color in a single operation.
6168
* Previously these were implemented in PostScript.
6171
zsetgray(i_ctx_t * i_ctx_p)
6173
os_ptr op = osp; /* required by "push" macro */
6177
/* Gather numeric operand value(s) */
6178
code = float_params(op, 1, &value);
6181
/* Clamp numeric operand range(s) */
6186
code = make_floats(op, &value, 1);
6190
/* Set up for the continuation procedure which will do the work */
6191
/* Make sure the exec stack has enough space */
6193
push_mark_estack(es_other, 0);
6195
/* variable to hold base type (0 = gray) */
6198
/* Store the 'stage' of processing (initially 0) */
6200
/* Finally, the actual continuation routine */
6201
push_op_estack(setdevicecolor_cont);
6202
return o_push_estack;
6205
zsethsbcolor(i_ctx_t * i_ctx_p)
6207
os_ptr op = osp; /* required by "push" macro */
6211
/* Gather numeric operand value(s) (also checks type) */
6212
code = float_params(op, 3, (float *)&values);
6215
/* Clamp numeric operand range(s) */
6216
for (i = 0;i < 3; i++) {
6219
else if (values[i] > 1)
6223
hsb2rgb((float *)&values);
6225
code = make_floats(&op[-2], (const float *)&values, 3);
6229
/* Set up for the continuation procedure which will do the work */
6230
/* Make sure the exec stack has enough space */
6232
push_mark_estack(es_other, 0);
6234
/* variable to hold base type (1 = RGB) */
6237
/* Store the 'stage' of processing (initially 0) */
6239
/* Finally, the actual continuation routine */
6240
push_op_estack(setdevicecolor_cont);
6241
return o_push_estack;
6244
zsetrgbcolor(i_ctx_t * i_ctx_p)
6246
os_ptr op = osp; /* required by "push" macro */
6250
/* Gather numeric operand value(s) (also checks type) */
6251
code = float_params(op, 3, (float *)&values);
6254
/* Clamp numeric operand range(s) */
6255
for (i = 0;i < 3; i++) {
6258
else if (values[i] > 1)
6262
code = make_floats(&op[-2], (const float *)&values, 3);
6266
/* Set up for the continuation procedure which will do the work */
6267
/* Make sure the exec stack has enough space */
6269
push_mark_estack(es_other, 0);
6271
/* variable to hold base type (1 = RGB) */
6274
/* Store the 'stage' of processing (initially 0) */
6276
/* Finally, the actual continuation routine */
6277
push_op_estack(setdevicecolor_cont);
6278
return o_push_estack;
6282
zsetcmykcolor(i_ctx_t * i_ctx_p)
6284
os_ptr op = osp; /* required by "push" macro */
6288
/* Gather numeric operand value(s) (also checks type) */
6289
code = float_params(op, 4, (float *)&values);
6292
/* Clamp numeric operand range(s) */
6293
for (i = 0;i < 4; i++) {
6296
else if (values[i] > 1)
6300
code = make_floats(&op[-3], (const float *)&values, 4);
6304
/* Set up for the continuation procedure which will do the work */
6305
/* Make sure the exec stack has enough space */
6307
push_mark_estack(es_other, 0);
6309
/* variable to hold base type (2 = CMYK) */
6312
/* Store the 'stage' of processing (initially 0) */
6314
/* Finally, the actual continuation routine */
6315
push_op_estack(setdevicecolor_cont);
6316
return o_push_estack;
6320
* The routine which does all the dispatching for the device-space specific
6321
* 'current color' routines currentgray, currentrgbcolo and currentcmykcolor.
6323
* Starting with the top-level color space we need to take the current color
6324
* value(s) and pass it through the tint transform procedure (actually we use the
6325
* converted function) to get equivalent components for the next space. We then
6326
* repeat with each alternate space in turn until we reach a 'terminal' space.
6327
* That can be a device space (eg DeviceGray), a CIEBased or ICCBased space, or
6328
* a Separation or DeviceN space which is not using its alternate space.
6330
* Depending on which kind of terminal space we reach we will either return
6331
* fixed values (all 0.0) or we will convert the terminal device space components
6332
* into the requested device space.
6334
* Because we might need to run a tint transform procedure, this requires a
6335
* continuation procedure.
6338
currentbasecolor_cont(i_ctx_t *i_ctx_p)
6340
ref arr, *parr = &arr;
6342
int i, code = 0,depth, stage, base, cont=1, stack_depth = 0, CIESubst=0;
6343
PS_colour_space_t *obj;
6345
stack_depth = (int)ep[-4].value.intval;
6346
base = (int)ep[-3].value.intval;
6347
depth = (int)ep[-2].value.intval;
6348
stage = (int)ep[-1].value.intval;
6349
/* If we get a continuation from a sub-procedure, we will want to come back
6350
* here afterward, to do any remaining stages. We need to set up for that now.
6351
* so that our continuation is ahead of the sub-proc's continuation.
6354
/* The push_op_estack macro increments esp before use, so we don't need to */
6355
push_op_estack(currentbasecolor_cont);
6357
while (code == 0 && cont) {
6358
ref_assign(&arr, ep);
6360
/* Run along the nested color spaces until we get to the lowest one
6361
* that we haven't yet processed (given by 'depth')
6363
for (i = 0;i < depth;i++) {
6364
code = get_space_object(i_ctx_p, parr, &obj);
6368
if (i < (depth - 1)) {
6369
if (!obj->alternateproc) {
6370
return_error(e_typecheck);
6372
code = obj->alternateproc(i_ctx_p, parr, &parr, &CIESubst);
6378
code = obj->basecolorproc(i_ctx_p, parr, base, &stage, &cont, &stack_depth);
6379
make_int(&ep[-4], stack_depth);
6380
make_int(&ep[-1], stage);
6383
/* Completed that space, increment the 'depth' */
6384
make_int(&ep[-2], ++depth);
6387
/* Remove our next continuation and our data */
6389
code = o_pop_estack;
6394
/* These routines implement the device-space 'current' color routines.
6395
* Previously these were implemented in PostScript.
6398
zcurrentgray(i_ctx_t * i_ctx_p)
6402
code = validate_spaces(i_ctx_p, &istate->colorspace[0].array, &depth);
6406
code = zcurrentcolor(i_ctx_p);
6409
/* Set up for the continuation procedure which will do the work */
6410
/* Make sure the exec stack has enough space */
6412
push_mark_estack(es_other, 0);
6414
/* variable to hold stack depth for tint transform */
6415
make_int(&esp[0], 0);
6417
/* Store the 'base' type color wanted, in this case Gray */
6418
make_int(&esp[0], 0);
6419
make_int(&esp[1], 1);
6420
/* Store the 'stage' of processing (initially 0) */
6421
make_int(&esp[2], 0);
6422
/* Store a pointer to the color space stored on the operand stack
6423
* as the stack may grow unpredictably making further access
6424
* to the space difficult
6426
esp[3] = istate->colorspace[0].array;
6427
esp += 3; /* The push_op_estack macro increments esp before using it */
6428
/* Finally, the actual continuation routine */
6429
push_op_estack(currentbasecolor_cont);
6430
return o_push_estack;
6433
zcurrenthsbcolor(i_ctx_t * i_ctx_p)
6437
code = validate_spaces(i_ctx_p, &istate->colorspace[0].array, &depth);
6441
code = zcurrentcolor(i_ctx_p);
6444
/* Set up for the continuation procedure which will do the work */
6445
/* Make sure the exec stack has enough space */
6447
push_mark_estack(es_other, 0);
6449
/* variable to hold stack depth for tint transform */
6450
make_int(&esp[0], 0);
6452
/* Store the 'base' type color wanted, in this case HSB */
6453
make_int(&esp[0], 1);
6454
make_int(&esp[1], 1);
6455
/* Store the 'stage' of processing (initially 0) */
6456
make_int(&esp[2], 0);
6457
/* Store a pointer to the color space stored on the operand stack
6458
* as the stack may grow unpredictably making further access
6459
* to the space difficult
6461
esp[3] = istate->colorspace[0].array;
6462
esp += 3; /* The push_op_estack macro increments esp before using it */
6463
/* Finally, the actual continuation routine */
6464
push_op_estack(currentbasecolor_cont);
6465
return o_push_estack;
6468
zcurrentrgbcolor(i_ctx_t * i_ctx_p)
6472
code = zcurrentcolor(i_ctx_p);
6475
/* Set up for the continuation procedure which will do the work */
6476
/* Make sure the exec stack has enough space */
6478
push_mark_estack(es_other, 0);
6480
/* variable to hold stack depth for tint transform */
6481
make_int(&esp[0], 0);
6483
/* Store the 'base' type color wanted, in this case RGB */
6484
make_int(&esp[0], 2);
6485
make_int(&esp[1], 1);
6486
/* Store the 'stage' of processing (initially 0) */
6487
make_int(&esp[2], 0);
6488
/* Store a pointer to the color space stored on the operand stack
6489
* as the stack may grow unpredictably making further access
6490
* to the space difficult
6492
esp[3] = istate->colorspace[0].array;
6493
esp += 3; /* The push_op_estack macro increments esp before using it */
6494
/* Finally, the actual continuation routine */
6495
push_op_estack(currentbasecolor_cont);
6496
return o_push_estack;
6499
zcurrentcmykcolor(i_ctx_t * i_ctx_p)
6503
code = zcurrentcolor(i_ctx_p);
6506
/* Set up for the continuation procedure which will do the work */
6507
/* Make sure the exec stack has enough space */
6509
push_mark_estack(es_other, 0);
6511
/* variable to hold stack depth for tint transform */
6512
make_int(&esp[0], 0);
6514
/* Store the 'base' type color wanted, in this case CMYK */
6515
make_int(&esp[0], 3);
6516
make_int(&esp[1], 1);
6517
/* Store the 'stage' of processing (initially 0) */
6518
make_int(&esp[2], 0);
6519
/* Store a pointer to the color space stored on the operand stack
6520
* as the stack may grow unpredictably making further access
6521
* to the space difficult
6523
esp[3] = istate->colorspace[0].array;
6524
esp += 3; /* The push_op_estack macro increments esp before using it */
6525
/* Finally, the actual continuation routine */
6526
push_op_estack(currentbasecolor_cont);
6527
return o_push_estack;
6531
zswapcolors(i_ctx_t * i_ctx_p)
6533
ref_colorspace tmp_cs;
6536
tmp_cs = istate->colorspace[0];
6537
istate->colorspace[0] = istate->colorspace[1];
6538
istate->colorspace[1] = tmp_cs;
6540
tmp_pat = istate->pattern[0];
6541
istate->pattern[0] = istate->pattern[1];
6542
istate->pattern[1] = tmp_pat;
6544
return gs_swapcolors(igs);
6547
/* ------ Initialization procedure ------ */
6549
/* We need to split the table because of the 16-element limit. */
6550
const op_def zcolor_op_defs[] =
6552
{ "0currentcolor", zcurrentcolor },
6553
{ "0currentcolorspace", zcurrentcolorspace },
6554
{ "0.getuseciecolor", zgetuseciecolor },
6555
{ "1setcolor", zsetcolor },
6556
{ "1setcolorspace", zsetcolorspace },
6558
/* basic transfer operators */
6559
{ "0currenttransfer", zcurrenttransfer },
6560
{ "0processcolors", zprocesscolors },
6561
{ "1settransfer", zsettransfer },
6563
/* internal operators */
6564
{ "1%zcolor_remap_one_finish", zcolor_remap_one_finish },
6565
{ "1%zcolor_remap_one_signed_finish", zcolor_remap_one_signed_finish },
6566
{ "0%zcolor_reset_transfer", zcolor_reset_transfer },
6567
{ "0%zcolor_remap_color", zcolor_remap_color },
6568
{ "0.color_test", zcolor_test },
6569
{ "1.color_test_all", zcolor_test_all },
6571
/* high level device support */
6572
{ "0.includecolorspace", zincludecolorspace },
6576
const op_def zcolor_ext_op_defs[] =
6578
{ "0currentgray", zcurrentgray },
6579
{ "1setgray", zsetgray },
6580
{ "0currenthsbcolor", zcurrenthsbcolor },
6581
{ "3sethsbcolor", zsethsbcolor },
6582
{ "0currentrgbcolor", zcurrentrgbcolor },
6583
{ "3setrgbcolor", zsetrgbcolor },
6584
{ "0currentcmykcolor", zcurrentcmykcolor },
6585
{ "4setcmykcolor", zsetcmykcolor },
6587
/* Operators to deal with setting stroking/non-stroking colors
6589
{ "1.swapcolors", zswapcolors },
6591
/* internal operators, entries here only used for error reporting */
6592
{ "0%setcolorspace_cont", setcolorspace_cont },
6593
{ "0%setcolor_cont", setcolor_cont },
6594
{ "0%devicencolorants_cont", devicencolorants_cont },
6595
{ "0%indexed_cont", indexed_cont },
6596
{ "0%setdevicecolor_cont", setdevicecolor_cont },
6597
{ "0%currentbasecolor_cont", currentbasecolor_cont },