1 /* Copyright (C) 1997, 2000 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: zcsdevn.c,v 1.12 2004/08/04 19:36:13 stefan Exp $ */
18 /* DeviceN color space support */
19 #include "memory_.h"
20 #include "ghost.h"
21 #include "oper.h"
22 #include "gxcspace.h" /* must precede gscolor2.h */
23 #include "gscolor2.h"
24 #include "gscdevn.h"
25 #include "gxcdevn.h"
26 #include "estack.h"
27 #include "ialloc.h"
28 #include "icremap.h"
29 #include "ifunc.h"
30 #include "igstate.h"
31 #include "iname.h"
32 #include "zht2.h"
33
34 /* Imported from gscdevn.c */
35 extern const gs_color_space_type gs_color_space_type_DeviceN;
36
37 /* <array> .setdevicenspace - */
38 /* The current color space is the alternate space for the DeviceN space. */
39 private int
zsetdevicenspace(i_ctx_t * i_ctx_p)40 zsetdevicenspace(i_ctx_t *i_ctx_p)
41 {
42 os_ptr op = osp;
43 const ref *pcsa;
44 gs_separation_name *names;
45 gs_device_n_map *pmap;
46 uint num_components;
47 gs_color_space cs;
48 const gs_color_space * pacs;
49 ref_colorspace cspace_old;
50 gs_function_t *pfn;
51 int code;
52
53 /* Verify that we have an array as our input parameter */
54 check_read_type(*op, t_array);
55 if (r_size(op) != 4)
56 return_error(e_rangecheck);
57
58 /* pcsa is a pointer to the color names array (element 1 in input array) */
59 pcsa = op->value.const_refs + 1;
60 if (!r_is_array(pcsa))
61 return_error(e_typecheck);
62 num_components = r_size(pcsa);
63 if (num_components == 0)
64 return_error(e_rangecheck);
65 if (num_components > GS_CLIENT_COLOR_MAX_COMPONENTS)
66 return_error(e_limitcheck);
67
68 /* Check tint transform procedure. Note: Cheap trick to get pointer to it.
69 The tint transform procedure is element 3 in the input array */
70 check_proc(pcsa[2]);
71
72 /* The alternate color space has been selected as the current color space */
73 pacs = gs_currentcolorspace(igs);
74 cs = *pacs;
75 /* See zcsindex.c for why we use memmove here. */
76 memmove(&cs.params.device_n.alt_space, &cs,
77 sizeof(cs.params.device_n.alt_space));
78 gs_cspace_init(&cs, &gs_color_space_type_DeviceN, imemory, false);
79 code = gs_build_DeviceN(&cs, num_components, pacs, imemory);
80 if (code < 0)
81 return code;
82 names = cs.params.device_n.names;
83 pmap = cs.params.device_n.map;
84 cs.params.device_n.get_colorname_string = gs_get_colorname_string;
85
86 /* Pick up the names of the components */
87 {
88 uint i;
89 ref sname;
90
91 for (i = 0; i < num_components; ++i) {
92 array_get(imemory, pcsa, (long)i, &sname);
93 switch (r_type(&sname)) {
94 case t_string:
95 code = name_from_string(imemory, &sname, &sname);
96 if (code < 0) {
97 ifree_object(names, ".setdevicenspace(names)");
98 ifree_object(pmap, ".setdevicenspace(map)");
99 return code;
100 }
101 /* falls through */
102 case t_name:
103 names[i] = name_index(imemory, &sname);
104 break;
105 default:
106 ifree_object(names, ".setdevicenspace(names)");
107 ifree_object(pmap, ".setdevicenspace(map)");
108 return_error(e_typecheck);
109 }
110 }
111 }
112
113 /* Now set the current color space as DeviceN */
114
115 cspace_old = istate->colorspace;
116 /*
117 * pcsa is a pointer to element 1 (2nd element) in the DeviceN
118 * description array. Thus pcsa[2] is element #3 (4th element)
119 * which is the tint transform.
120 */
121 istate->colorspace.procs.special.device_n.layer_names = pcsa[0];
122 istate->colorspace.procs.special.device_n.tint_transform = pcsa[2];
123 pfn = ref_function(pcsa + 2); /* See comment above */
124 if (!pfn)
125 code = gs_note_error(e_rangecheck);
126
127 if (code < 0) {
128 istate->colorspace = cspace_old;
129 ifree_object(names, ".setdevicenspace(names)");
130 ifree_object(pmap, ".setdevicenspace(map)");
131 return code;
132 }
133 gs_cspace_set_devn_function(&cs, pfn);
134 code = gs_setcolorspace(igs, &cs);
135 if (code < 0) {
136 istate->colorspace = cspace_old;
137 return code;
138 }
139 rc_decrement(pmap, ".setdevicenspace(map)"); /* build sets rc = 1 */
140 pop(1);
141 return 0;
142 }
143
144
145 /* ------ Initialization procedure ------ */
146
147 const op_def zcsdevn_op_defs[] =
148 {
149 op_def_begin_ll3(),
150 {"1.setdevicenspace", zsetdevicenspace},
151 op_def_end(0)
152 };
153