xref: /plan9/sys/src/cmd/gs/src/gscolor1.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1989, 1992, 1993, 1994, 1996, 1997, 1998, 1999 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: gscolor1.c,v 1.11 2004/08/04 19:36:12 stefan Exp $ */
18 /* Level 1 extended color operators for Ghostscript library */
19 #include "gx.h"
20 #include "gserrors.h"
21 #include "gsstruct.h"
22 #include "gsutil.h"		/* for gs_next_ids */
23 #include "gsccolor.h"
24 #include "gxcspace.h"
25 #include "gxdcconv.h"
26 #include "gxdevice.h"		/* for gx_color_index */
27 #include "gxcmap.h"
28 #include "gzstate.h"
29 #include "gscolor1.h"
30 #include "gscolor2.h"
31 #include "gxhttype.h"
32 #include "gzht.h"
33 
34 /* Imports from gscolor.c */
35 void load_transfer_map(gs_state *, gx_transfer_map *, floatp);
36 
37 /* Imported from gsht.c */
38 void gx_set_effective_transfer(gs_state *);
39 
40 /* Force a parameter into the range [0.0..1.0]. */
41 #define FORCE_UNIT(p) (p < 0.0 ? 0.0 : p > 1.0 ? 1.0 : p)
42 
43 /* setcmykcolor */
44 int
gs_setcmykcolor(gs_state * pgs,floatp c,floatp m,floatp y,floatp k)45 gs_setcmykcolor(gs_state * pgs, floatp c, floatp m, floatp y, floatp k)
46 {
47     gs_color_space      cs;
48     int                 code;
49 
50     gs_cspace_init_DeviceCMYK(pgs->memory, &cs);
51     if ((code = gs_setcolorspace(pgs, &cs)) >= 0) {
52        gs_client_color *    pcc = pgs->ccolor;
53 
54         cs_adjust_color_count(pgs, -1); /* not strictly necessary */
55         pcc->paint.values[0] = FORCE_UNIT(c);
56         pcc->paint.values[1] = FORCE_UNIT(m);
57         pcc->paint.values[2] = FORCE_UNIT(y);
58         pcc->paint.values[3] = FORCE_UNIT(k);
59         pcc->pattern = 0;		/* for GC */
60         gx_unset_dev_color(pgs);
61     }
62     return code;
63 }
64 
65 
66 /* setblackgeneration */
67 /* Remap=0 is used by the interpreter. */
68 int
gs_setblackgeneration(gs_state * pgs,gs_mapping_proc proc)69 gs_setblackgeneration(gs_state * pgs, gs_mapping_proc proc)
70 {
71     return gs_setblackgeneration_remap(pgs, proc, true);
72 }
73 int
gs_setblackgeneration_remap(gs_state * pgs,gs_mapping_proc proc,bool remap)74 gs_setblackgeneration_remap(gs_state * pgs, gs_mapping_proc proc, bool remap)
75 {
76     rc_unshare_struct(pgs->black_generation, gx_transfer_map,
77 		      &st_transfer_map, pgs->memory,
78 		      return_error(gs_error_VMerror),
79 		      "gs_setblackgeneration");
80     pgs->black_generation->proc = proc;
81     pgs->black_generation->id = gs_next_ids(pgs->memory, 1);
82     if (remap) {
83 	load_transfer_map(pgs, pgs->black_generation, 0.0);
84 	gx_unset_dev_color(pgs);
85     }
86     return 0;
87 }
88 
89 /* currentblackgeneration */
90 gs_mapping_proc
gs_currentblackgeneration(const gs_state * pgs)91 gs_currentblackgeneration(const gs_state * pgs)
92 {
93     return pgs->black_generation->proc;
94 }
95 
96 /* setundercolorremoval */
97 /* Remap=0 is used by the interpreter. */
98 int
gs_setundercolorremoval(gs_state * pgs,gs_mapping_proc proc)99 gs_setundercolorremoval(gs_state * pgs, gs_mapping_proc proc)
100 {
101     return gs_setundercolorremoval_remap(pgs, proc, true);
102 }
103 int
gs_setundercolorremoval_remap(gs_state * pgs,gs_mapping_proc proc,bool remap)104 gs_setundercolorremoval_remap(gs_state * pgs, gs_mapping_proc proc, bool remap)
105 {
106     rc_unshare_struct(pgs->undercolor_removal, gx_transfer_map,
107 		      &st_transfer_map, pgs->memory,
108 		      return_error(gs_error_VMerror),
109 		      "gs_setundercolorremoval");
110     pgs->undercolor_removal->proc = proc;
111     pgs->undercolor_removal->id = gs_next_ids(pgs->memory, 1);
112     if (remap) {
113 	load_transfer_map(pgs, pgs->undercolor_removal, -1.0);
114 	gx_unset_dev_color(pgs);
115     }
116     return 0;
117 }
118 
119 /* currentundercolorremoval */
120 gs_mapping_proc
gs_currentundercolorremoval(const gs_state * pgs)121 gs_currentundercolorremoval(const gs_state * pgs)
122 {
123     return pgs->undercolor_removal->proc;
124 }
125 
126 /* setcolortransfer */
127 /* Remap=0 is used by the interpreter. */
128 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)129 gs_setcolortransfer_remap(gs_state * pgs, gs_mapping_proc red_proc,
130 			  gs_mapping_proc green_proc,
131 			  gs_mapping_proc blue_proc,
132 			  gs_mapping_proc gray_proc, bool remap)
133 {
134     gx_transfer *ptran = &pgs->set_transfer;
135     gx_transfer old;
136     gs_id new_ids = gs_next_ids(pgs->memory, 4);
137     gx_device * dev = pgs->device;
138 
139     old = *ptran;
140     rc_unshare_struct(ptran->gray, gx_transfer_map, &st_transfer_map,
141 		      pgs->memory, goto fgray, "gs_setcolortransfer");
142     rc_unshare_struct(ptran->red, gx_transfer_map, &st_transfer_map,
143 		      pgs->memory, goto fred, "gs_setcolortransfer");
144     rc_unshare_struct(ptran->green, gx_transfer_map, &st_transfer_map,
145 		      pgs->memory, goto fgreen, "gs_setcolortransfer");
146     rc_unshare_struct(ptran->blue, gx_transfer_map, &st_transfer_map,
147 		      pgs->memory, goto fblue, "gs_setcolortransfer");
148     ptran->gray->proc = gray_proc;
149     ptran->gray->id = new_ids;
150     ptran->red->proc = red_proc;
151     ptran->red->id = new_ids + 1;
152     ptran->green->proc = green_proc;
153     ptran->green->id = new_ids + 2;
154     ptran->blue->proc = blue_proc;
155     ptran->blue->id = new_ids + 3;
156     ptran->red_component_num =
157         gs_color_name_component_number(dev, "Red", 3, ht_type_colorscreen);
158     ptran->green_component_num =
159         gs_color_name_component_number(dev, "Green", 5, ht_type_colorscreen);
160     ptran->blue_component_num =
161         gs_color_name_component_number(dev, "Blue", 4, ht_type_colorscreen);
162     ptran->gray_component_num =
163         gs_color_name_component_number(dev, "Gray", 4, ht_type_colorscreen);
164     if (remap) {
165 	load_transfer_map(pgs, ptran->red, 0.0);
166 	load_transfer_map(pgs, ptran->green, 0.0);
167 	load_transfer_map(pgs, ptran->blue, 0.0);
168 	load_transfer_map(pgs, ptran->gray, 0.0);
169 	gx_set_effective_transfer(pgs);
170 	gx_unset_dev_color(pgs);
171     } else
172 	gx_set_effective_transfer(pgs);
173     return 0;
174   fblue:
175     rc_assign(ptran->green, old.green, "setcolortransfer");
176   fgreen:
177     rc_assign(ptran->red, old.red, "setcolortransfer");
178   fred:
179     rc_assign(ptran->gray, old.gray, "setcolortransfer");
180   fgray:
181     return_error(gs_error_VMerror);
182 }
183 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)184 gs_setcolortransfer(gs_state * pgs, gs_mapping_proc red_proc,
185 		    gs_mapping_proc green_proc, gs_mapping_proc blue_proc,
186 		    gs_mapping_proc gray_proc)
187 {
188     return gs_setcolortransfer_remap(pgs, red_proc, green_proc,
189 				     blue_proc, gray_proc, true);
190 }
191 
192 /* currentcolortransfer */
193 void
gs_currentcolortransfer(const gs_state * pgs,gs_mapping_proc procs[4])194 gs_currentcolortransfer(const gs_state * pgs, gs_mapping_proc procs[4])
195 {
196     const gx_transfer *ptran = &pgs->set_transfer;
197 
198     procs[0] = ptran->red->proc;
199     procs[1] = ptran->green->proc;
200     procs[2] = ptran->blue->proc;
201     procs[3] = ptran->gray->proc;
202 }
203