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