Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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: gscolor.c,v 1.14 2004/08/04 19:36:12 stefan Exp $ */
18
/* Color and halftone 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 "gscolor2.h"
29
#include "gzstate.h"
30
 
31
/* Imported from gsht.c */
32
void gx_set_effective_transfer(gs_state *);
33
 
34
/* Structure descriptors */
35
public_st_client_color();
36
public_st_transfer_map();
37
 
38
/* GC procedures */
39
private 
40
ENUM_PTRS_WITH(transfer_map_enum_ptrs, gx_transfer_map *mptr) return 0;
41
case 0: ENUM_RETURN((mptr->proc == 0 ? mptr->closure.data : 0));
42
ENUM_PTRS_END
43
private RELOC_PTRS_WITH(transfer_map_reloc_ptrs, gx_transfer_map *mptr)
44
{
45
    if (mptr->proc == 0)
46
	RELOC_PTR(gx_transfer_map, closure.data);
47
}
48
RELOC_PTRS_END
49
 
50
/* Initialize colors with 1, or 3, or 4 paint components. */
51
/* (These are only used by setcolorspace.) */
52
void
53
gx_init_paint_1(gs_client_color * pcc, const gs_color_space * pcs)
54
{
55
    pcc->paint.values[0] = 0.0;
56
}
57
void
58
gx_init_paint_3(gs_client_color * pcc, const gs_color_space * pcs)
59
{
60
    pcc->paint.values[2] = 0.0;
61
    pcc->paint.values[1] = 0.0;
62
    pcc->paint.values[0] = 0.0;
63
}
64
void
65
gx_init_paint_4(gs_client_color * pcc, const gs_color_space * pcs)
66
{
67
    /* DeviceCMYK and CIEBasedDEFG spaces initialize to 0,0,0,1. */
68
    pcc->paint.values[3] = 1.0;
69
    gx_init_paint_3(pcc, pcs);
70
}
71
 
72
/* Force a value into the range [0.0..1.0]. */
73
#define FORCE_UNIT(p) (p <= 0.0 ? 0.0 : p >= 1.0 ? 1.0 : p)
74
 
75
/* Restrict colors with 1, 3, or 4 components to the range (0,1). */
76
void
77
gx_restrict01_paint_1(gs_client_color * pcc, const gs_color_space * pcs)
78
{
79
    pcc->paint.values[0] = FORCE_UNIT(pcc->paint.values[0]);
80
}
81
void
82
gx_restrict01_paint_3(gs_client_color * pcc, const gs_color_space * pcs)
83
{
84
    pcc->paint.values[2] = FORCE_UNIT(pcc->paint.values[2]);
85
    pcc->paint.values[1] = FORCE_UNIT(pcc->paint.values[1]);
86
    pcc->paint.values[0] = FORCE_UNIT(pcc->paint.values[0]);
87
}
88
void
89
gx_restrict01_paint_4(gs_client_color * pcc, const gs_color_space * pcs)
90
{
91
    pcc->paint.values[3] = FORCE_UNIT(pcc->paint.values[3]);
92
    gx_restrict01_paint_3(pcc, pcs);
93
}
94
 
95
/* Null reference count adjustment procedure. */
96
void
97
gx_no_adjust_color_count(const gs_client_color * pcc,
98
			 const gs_color_space * pcs, int delta)
99
{
100
}
101
 
102
/* Forward declarations */
103
void load_transfer_map(gs_state *, gx_transfer_map *, floatp);
104
 
105
/* setgray */
106
int
107
gs_setgray(gs_state * pgs, floatp gray)
108
{
109
    gs_color_space      cs;
110
    int                 code;
111
 
112
    gs_cspace_init_DeviceGray(pgs->memory, &cs);
113
    if ((code = gs_setcolorspace(pgs, &cs)) >= 0) {
114
        gs_client_color *   pcc = pgs->ccolor;
115
 
116
        cs_adjust_color_count(pgs, -1); /* not strictly necessary */
117
        pcc->paint.values[0] = FORCE_UNIT(gray);
118
        pcc->pattern = 0;		/* for GC */
119
        gx_unset_dev_color(pgs);
120
    }
121
    return code;
122
}
123
 
124
/* setrgbcolor */
125
int
126
gs_setrgbcolor(gs_state * pgs, floatp r, floatp g, floatp b)
127
{
128
    gs_color_space      cs;
129
    int                 code;
130
 
131
    gs_cspace_init_DeviceRGB(pgs->memory, &cs);
132
    if ((code = gs_setcolorspace(pgs, &cs)) >= 0) {
133
       gs_client_color *    pcc = pgs->ccolor;
134
 
135
        cs_adjust_color_count(pgs, -1); /* not strictly necessary */
136
        pcc->paint.values[0] = FORCE_UNIT(r);
137
        pcc->paint.values[1] = FORCE_UNIT(g);
138
        pcc->paint.values[2] = FORCE_UNIT(b);
139
        pcc->pattern = 0;		/* for GC */
140
        gx_unset_dev_color(pgs);
141
    }
142
    return code;
143
}
144
 
145
 
146
/* setnullcolor */
147
int
148
gs_setnullcolor(gs_state * pgs)
149
{
150
    if (pgs->in_cachedevice)
151
	return_error(gs_error_undefined);
152
    gs_setgray(pgs, 0.0);	/* set color space to something harmless */
153
    color_set_null(pgs->dev_color);
154
    return 0;
155
}
156
 
157
/* settransfer */
158
/* Remap=0 is used by the interpreter. */
159
int
160
gs_settransfer(gs_state * pgs, gs_mapping_proc tproc)
161
{
162
    return gs_settransfer_remap(pgs, tproc, true);
163
}
164
int
165
gs_settransfer_remap(gs_state * pgs, gs_mapping_proc tproc, bool remap)
166
{
167
    gx_transfer *ptran = &pgs->set_transfer;
168
 
169
    /*
170
     * We can safely decrement the reference counts
171
     * of the non-default transfer maps, because
172
     * if any of them get freed, the rc_unshare can't fail.
173
     */
174
    rc_decrement(ptran->red, "gs_settransfer");
175
    rc_decrement(ptran->green, "gs_settransfer");
176
    rc_decrement(ptran->blue, "gs_settransfer");
177
    rc_unshare_struct(ptran->gray, gx_transfer_map, &st_transfer_map,
178
		      pgs->memory, goto fail, "gs_settransfer");
179
    ptran->gray->proc = tproc;
180
    ptran->gray->id = gs_next_ids(pgs->memory, 1);
181
    ptran->red = 0;
182
    ptran->green = 0;
183
    ptran->blue = 0;
184
    if (remap) {
185
	load_transfer_map(pgs, ptran->gray, 0.0);
186
	gx_set_effective_transfer(pgs);
187
	gx_unset_dev_color(pgs);
188
    } else
189
	gx_set_effective_transfer(pgs);
190
    return 0;
191
  fail:
192
    rc_increment(ptran->red);
193
    rc_increment(ptran->green);
194
    rc_increment(ptran->blue);
195
    rc_increment(ptran->gray);
196
    return_error(gs_error_VMerror);
197
}
198
 
199
/* currenttransfer */
200
gs_mapping_proc
201
gs_currenttransfer(const gs_state * pgs)
202
{
203
    return pgs->set_transfer.gray->proc;
204
}
205
 
206
/* ------ Non-operator routines ------ */
207
 
208
/* Set device color = 1 for writing into the character cache. */
209
void
210
gx_set_device_color_1(gs_state * pgs)
211
{
212
    gs_color_space  cs;
213
 
214
    gs_setoverprint(pgs, false);
215
    gs_setoverprintmode(pgs, 0);
216
    gs_cspace_init_DeviceGray(pgs->memory, &cs);
217
    gs_setcolorspace(pgs, &cs);
218
    set_nonclient_dev_color(pgs->dev_color, 1);
219
    pgs->log_op = lop_default;
220
    /*
221
     * In the unlikely event that  overprint mode is in effect,
222
     * update the overprint information.
223
     */
224
    if (pgs->effective_overprint_mode == 1)
225
	(void)gs_do_set_overprint(pgs);
226
 
227
}
228
 
229
/* ------ Internal routines ------ */
230
 
231
/*
232
 * Load one cached transfer map.  We export this for gscolor1.c.
233
 * Note that we must deal with both old (proc) and new (closure) maps.
234
 */
235
private float
236
transfer_use_proc(floatp value, const gx_transfer_map * pmap,
237
		  const void *ignore_proc_data)
238
{
239
    return (*pmap->proc) (value, pmap);
240
}
241
void
242
load_transfer_map(gs_state * pgs, gx_transfer_map * pmap, floatp min_value)
243
{
244
    gs_mapping_closure_proc_t proc;
245
    const void *proc_data;
246
    frac *values = pmap->values;
247
    frac fmin = float2frac(min_value);
248
    int i;
249
 
250
    if (pmap->proc == 0)	/* use closure */
251
	proc = pmap->closure.proc, proc_data = pmap->closure.data;
252
    else			/* use proc */
253
	proc = transfer_use_proc, proc_data = 0 /* not used */;
254
    for (i = 0; i < transfer_map_size; i++) {
255
	float fval =
256
	(*proc) ((float)i / (transfer_map_size - 1), pmap, proc_data);
257
 
258
	values[i] =
259
	    (fval < min_value ? fmin :
260
	     fval >= 1.0 ? frac_1 :
261
	     float2frac(fval));
262
    }
263
}