1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13 CA 94903, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17 /* Level 1 extended color operators for Ghostscript library */
18 #include "gx.h"
19 #include "gserrors.h"
20 #include "gsstruct.h"
21 #include "gsutil.h" /* for gs_next_ids */
22 #include "gsccolor.h"
23 #include "gxcspace.h"
24 #include "gxdcconv.h"
25 #include "gxdevice.h" /* for gx_color_index */
26 #include "gxcmap.h"
27 #include "gzstate.h"
28 #include "gscolor1.h"
29 #include "gscolor2.h"
30 #include "gxhttype.h"
31 #include "gzht.h"
32
33 /* Imports from gscolor.c */
34 void load_transfer_map(gs_state *, gx_transfer_map *, floatp);
35
36 /* Imported from gsht.c */
37 void gx_set_effective_transfer(gs_state *);
38
39 /* Force a parameter into the range [0.0..1.0]. */
40 #define FORCE_UNIT(p) (p < 0.0 ? 0.0 : p > 1.0 ? 1.0 : p)
41
42 /* setcmykcolor */
43 int
gs_setcmykcolor(gs_state * pgs,floatp c,floatp m,floatp y,floatp k)44 gs_setcmykcolor(gs_state * pgs, floatp c, floatp m, floatp y, floatp k)
45 {
46 gs_color_space *pcs;
47 int code;
48
49 pcs = gs_cspace_new_DeviceCMYK(pgs->memory);
50 if (pcs == NULL)
51 return_error(gs_error_VMerror);
52 if ((code = gs_setcolorspace(pgs, pcs)) >= 0) {
53 gs_client_color *pcc = gs_currentcolor_inline(pgs);
54
55 cs_adjust_color_count(pgs, -1); /* not strictly necessary */
56 pcc->paint.values[0] = FORCE_UNIT(c);
57 pcc->paint.values[1] = FORCE_UNIT(m);
58 pcc->paint.values[2] = FORCE_UNIT(y);
59 pcc->paint.values[3] = FORCE_UNIT(k);
60 pcc->pattern = 0; /* for GC */
61 gx_unset_dev_color(pgs);
62 }
63 rc_decrement_only_cs(pcs, "gs_setcmykcolor");
64 return code;
65 }
66
67 /* setblackgeneration */
68 /* Remap=0 is used by the interpreter. */
69 int
gs_setblackgeneration(gs_state * pgs,gs_mapping_proc proc)70 gs_setblackgeneration(gs_state * pgs, gs_mapping_proc proc)
71 {
72 return gs_setblackgeneration_remap(pgs, proc, true);
73 }
74 int
gs_setblackgeneration_remap(gs_state * pgs,gs_mapping_proc proc,bool remap)75 gs_setblackgeneration_remap(gs_state * pgs, gs_mapping_proc proc, bool remap)
76 {
77 rc_unshare_struct(pgs->black_generation, gx_transfer_map,
78 &st_transfer_map, pgs->memory,
79 return_error(gs_error_VMerror),
80 "gs_setblackgeneration");
81 pgs->black_generation->proc = proc;
82 pgs->black_generation->id = gs_next_ids(pgs->memory, 1);
83 if (remap) {
84 load_transfer_map(pgs, pgs->black_generation, 0.0);
85 gx_unset_dev_color(pgs);
86 }
87 return 0;
88 }
89
90 /* currentblackgeneration */
91 gs_mapping_proc
gs_currentblackgeneration(const gs_state * pgs)92 gs_currentblackgeneration(const gs_state * pgs)
93 {
94 return pgs->black_generation->proc;
95 }
96
97 /* setundercolorremoval */
98 /* Remap=0 is used by the interpreter. */
99 int
gs_setundercolorremoval(gs_state * pgs,gs_mapping_proc proc)100 gs_setundercolorremoval(gs_state * pgs, gs_mapping_proc proc)
101 {
102 return gs_setundercolorremoval_remap(pgs, proc, true);
103 }
104 int
gs_setundercolorremoval_remap(gs_state * pgs,gs_mapping_proc proc,bool remap)105 gs_setundercolorremoval_remap(gs_state * pgs, gs_mapping_proc proc, bool remap)
106 {
107 rc_unshare_struct(pgs->undercolor_removal, gx_transfer_map,
108 &st_transfer_map, pgs->memory,
109 return_error(gs_error_VMerror),
110 "gs_setundercolorremoval");
111 pgs->undercolor_removal->proc = proc;
112 pgs->undercolor_removal->id = gs_next_ids(pgs->memory, 1);
113 if (remap) {
114 load_transfer_map(pgs, pgs->undercolor_removal, -1.0);
115 gx_unset_dev_color(pgs);
116 }
117 return 0;
118 }
119
120 /* currentundercolorremoval */
121 gs_mapping_proc
gs_currentundercolorremoval(const gs_state * pgs)122 gs_currentundercolorremoval(const gs_state * pgs)
123 {
124 return pgs->undercolor_removal->proc;
125 }
126
127 /* setcolortransfer */
128 /* Remap=0 is used by the interpreter. */
129 int
gs_setcolortransfer_remap(gs_state * pgs,gs_mapping_proc red_proc,gs_mapping_proc green_proc,gs_mapping_proc blue_proc,gs_mapping_proc gray_proc,bool remap)130 gs_setcolortransfer_remap(gs_state * pgs, gs_mapping_proc red_proc,
131 gs_mapping_proc green_proc,
132 gs_mapping_proc blue_proc,
133 gs_mapping_proc gray_proc, bool remap)
134 {
135 gx_transfer *ptran = &pgs->set_transfer;
136 gx_transfer old;
137 gs_id new_ids = gs_next_ids(pgs->memory, 4);
138 gx_device * dev = pgs->device;
139
140 old = *ptran;
141 rc_unshare_struct(ptran->gray, gx_transfer_map, &st_transfer_map,
142 pgs->memory, goto fgray, "gs_setcolortransfer");
143 rc_unshare_struct(ptran->red, gx_transfer_map, &st_transfer_map,
144 pgs->memory, goto fred, "gs_setcolortransfer");
145 rc_unshare_struct(ptran->green, gx_transfer_map, &st_transfer_map,
146 pgs->memory, goto fgreen, "gs_setcolortransfer");
147 rc_unshare_struct(ptran->blue, gx_transfer_map, &st_transfer_map,
148 pgs->memory, goto fblue, "gs_setcolortransfer");
149 ptran->gray->proc = gray_proc;
150 ptran->gray->id = new_ids;
151 ptran->red->proc = red_proc;
152 ptran->red->id = new_ids + 1;
153 ptran->green->proc = green_proc;
154 ptran->green->id = new_ids + 2;
155 ptran->blue->proc = blue_proc;
156 ptran->blue->id = new_ids + 3;
157 ptran->red_component_num =
158 gs_color_name_component_number(dev, "Red", 3, ht_type_colorscreen);
159 ptran->green_component_num =
160 gs_color_name_component_number(dev, "Green", 5, ht_type_colorscreen);
161 ptran->blue_component_num =
162 gs_color_name_component_number(dev, "Blue", 4, ht_type_colorscreen);
163 ptran->gray_component_num =
164 gs_color_name_component_number(dev, "Gray", 4, ht_type_colorscreen);
165 if (remap) {
166 load_transfer_map(pgs, ptran->red, 0.0);
167 load_transfer_map(pgs, ptran->green, 0.0);
168 load_transfer_map(pgs, ptran->blue, 0.0);
169 load_transfer_map(pgs, ptran->gray, 0.0);
170 gx_set_effective_transfer(pgs);
171 gx_unset_dev_color(pgs);
172 } else
173 gx_set_effective_transfer(pgs);
174 return 0;
175 fblue:
176 rc_assign(ptran->green, old.green, "setcolortransfer");
177 fgreen:
178 rc_assign(ptran->red, old.red, "setcolortransfer");
179 fred:
180 rc_assign(ptran->gray, old.gray, "setcolortransfer");
181 fgray:
182 return_error(gs_error_VMerror);
183 }
184 int
gs_setcolortransfer(gs_state * pgs,gs_mapping_proc red_proc,gs_mapping_proc green_proc,gs_mapping_proc blue_proc,gs_mapping_proc gray_proc)185 gs_setcolortransfer(gs_state * pgs, gs_mapping_proc red_proc,
186 gs_mapping_proc green_proc, gs_mapping_proc blue_proc,
187 gs_mapping_proc gray_proc)
188 {
189 return gs_setcolortransfer_remap(pgs, red_proc, green_proc,
190 blue_proc, gray_proc, true);
191 }
192
193 /* currentcolortransfer */
194 void
gs_currentcolortransfer(const gs_state * pgs,gs_mapping_proc procs[4])195 gs_currentcolortransfer(const gs_state * pgs, gs_mapping_proc procs[4])
196 {
197 const gx_transfer *ptran = &pgs->set_transfer;
198
199 procs[0] = ptran->red->proc;
200 procs[1] = ptran->green->proc;
201 procs[2] = ptran->blue->proc;
202 procs[3] = ptran->gray->proc;
203 }
204