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) 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: gscrd.c,v 1.6 2004/08/04 19:36:12 stefan Exp $ */
18
/* CIE color rendering dictionary creation */
19
#include "math_.h"
20
#include "memory_.h"
21
#include "string_.h"
22
#include "gx.h"
23
#include "gscdefs.h"		/* for gs_lib_device_list */
24
#include "gsdevice.h"
25
#include "gserrors.h"
26
#include "gsmatrix.h"		/* for gscolor2.h */
27
#include "gsparam.h"
28
#include "gsstruct.h"
29
#include "gsutil.h"
30
#include "gxcspace.h"
31
#include "gscolor2.h"		/* for gs_set/currentcolorrendering */
32
#include "gscrd.h"
33
 
34
/* Import gs_lib_device_list() */
35
extern_gs_lib_device_list();
36
 
37
/* Allocator structure type */
38
public_st_cie_render1();
39
private 
40
ENUM_PTRS_WITH(cie_render1_enum_ptrs, gs_cie_render *pcrd) return 0;
41
case 0: return ENUM_OBJ(pcrd->client_data);
42
case 1: return ENUM_OBJ(pcrd->RenderTable.lookup.table);
43
case 2: return (pcrd->RenderTable.lookup.table ?
44
		ENUM_CONST_STRING(&pcrd->TransformPQR.proc_data) :
45
		0);
46
ENUM_PTRS_END
47
private RELOC_PTRS_WITH(cie_render1_reloc_ptrs, gs_cie_render *pcrd);
48
RELOC_OBJ_VAR(pcrd->client_data);
49
if (pcrd->RenderTable.lookup.table)
50
{
51
RELOC_OBJ_VAR(pcrd->RenderTable.lookup.table);
52
RELOC_CONST_STRING_VAR(pcrd->TransformPQR.proc_data);
53
}
54
RELOC_PTRS_END
55
 
56
/* Default CRD procedures. */
57
 
58
private int
59
tpqr_identity(int index, floatp in, const gs_cie_wbsd * pwbsd,
60
	      gs_cie_render * pcrd, float *out)
61
{
62
    *out = in;
63
    return 0;
64
}
65
 
66
private int
67
tpqr_from_cache(int index, floatp in, const gs_cie_wbsd * pwbsd,
68
		gs_cie_render * pcrd, float *out)
69
{
70
    /*
71
     * Since the TransformPQR cache is in the joint caches, not in the
72
     * CRD cache, we can't actually implement this procedure.
73
     * Instead, the place that calls it checks for it specially.
74
     */
75
    *out = in;
76
    return 0;
77
}
78
 
79
private float
80
render_identity(floatp in, const gs_cie_render * pcrd)
81
{
82
    return in;
83
}
84
private frac
85
render_table_identity(byte in, const gs_cie_render * pcrd)
86
{
87
    return byte2frac(in);
88
}
89
 
90
/* Transformation procedures that just consult the cache. */
91
 
92
private float
93
EncodeABC_cached_A(floatp in, const gs_cie_render * pcrd)
94
{
95
    return gs_cie_cached_value(in, &pcrd->caches.EncodeABC[0].floats);
96
}
97
private float
98
EncodeABC_cached_B(floatp in, const gs_cie_render * pcrd)
99
{
100
    return gs_cie_cached_value(in, &pcrd->caches.EncodeABC[1].floats);
101
}
102
private float
103
EncodeABC_cached_C(floatp in, const gs_cie_render * pcrd)
104
{
105
    return gs_cie_cached_value(in, &pcrd->caches.EncodeABC[2].floats);
106
}
107
private float
108
EncodeLMN_cached_L(floatp in, const gs_cie_render * pcrd)
109
{
110
    return gs_cie_cached_value(in, &pcrd->caches.EncodeLMN.caches[0].floats);
111
}
112
private float
113
EncodeLMN_cached_M(floatp in, const gs_cie_render * pcrd)
114
{
115
    return gs_cie_cached_value(in, &pcrd->caches.EncodeLMN.caches[1].floats);
116
}
117
private float
118
EncodeLMN_cached_N(floatp in, const gs_cie_render * pcrd)
119
{
120
    return gs_cie_cached_value(in, &pcrd->caches.EncodeLMN.caches[2].floats);
121
}
122
 
123
private frac
124
RTT_cached(byte in, const gs_cie_render * pcrd, int i)
125
{
126
    return pcrd->caches.RenderTableT[i].fracs.values[
127
	in * (gx_cie_cache_size - 1) / 255
128
    ];
129
}
130
private frac
131
RTT_cached_0(byte in, const gs_cie_render * pcrd)
132
{
133
    return RTT_cached(in, pcrd, 0);
134
}
135
private frac
136
RTT_cached_1(byte in, const gs_cie_render * pcrd)
137
{
138
    return RTT_cached(in, pcrd, 1);
139
}
140
private frac
141
RTT_cached_2(byte in, const gs_cie_render * pcrd)
142
{
143
    return RTT_cached(in, pcrd, 2);
144
}
145
private frac
146
RTT_cached_3(byte in, const gs_cie_render * pcrd)
147
{
148
    return RTT_cached(in, pcrd, 3);
149
}
150
 
151
/* Define the TransformPQR trampoline procedure that looks up proc_name. */
152
 
153
private int
154
tpqr_do_lookup(gs_cie_render *pcrd, const gx_device *dev_proto)
155
{
156
    gx_device *dev;
157
    gs_memory_t *mem = pcrd->rc.memory;
158
    gs_c_param_list list;
159
    gs_param_string proc_addr;
160
    int code;
161
 
162
    /* Device prototypes are const, so we must create a copy. */
163
    code = gs_copydevice(&dev, dev_proto, mem);
164
    if (code < 0)
165
	return code;
166
    gs_c_param_list_write(&list, mem);
167
    code = param_request((gs_param_list *)&list,
168
			 pcrd->TransformPQR.proc_name);
169
    if (code >= 0) {
170
	code = gs_getdeviceparams(dev, (gs_param_list *)&list);
171
	if (code >= 0) {
172
	    gs_c_param_list_read(&list);
173
	    code = param_read_string((gs_param_list *)&list,
174
				     pcrd->TransformPQR.proc_name,
175
				     &proc_addr);
176
	    if (code == 0 && proc_addr.size == sizeof(gs_cie_transform_proc)) {
177
		memcpy(&pcrd->TransformPQR.proc, proc_addr.data,
178
		       sizeof(gs_cie_transform_proc));
179
	    } else
180
		code = gs_note_error(gs_error_rangecheck);
181
	}
182
    }
183
    gs_c_param_list_release(&list);
184
    gs_free_object(mem, dev, "tpqr_do_lookup(device)");
185
    return code;
186
}
187
private int
188
tpqr_lookup(int index, floatp in, const gs_cie_wbsd * pwbsd,
189
	    gs_cie_render * pcrd, float *out)
190
{
191
    const gx_device *const *dev_list;
192
    int count = gs_lib_device_list(&dev_list, NULL);
193
    int i;
194
    int code;
195
 
196
    for (i = 0; i < count; ++i)
197
	if (!strcmp(gs_devicename(dev_list[i]),
198
		    pcrd->TransformPQR.driver_name))
199
	    break;
200
    if (i < count)
201
	code = tpqr_do_lookup(pcrd, dev_list[i]);
202
    else
203
	code = gs_note_error(gs_error_undefined);
204
    if (code < 0)
205
	return code;
206
    return pcrd->TransformPQR.proc(index, in, pwbsd, pcrd, out);
207
}
208
 
209
 
210
/* Default vectors. */
211
const gs_cie_transform_proc3 TransformPQR_default = {
212
    tpqr_identity,
213
    0,				/* proc_name */
214
    {0, 0},			/* proc_data */
215
 
216
};
217
const gs_cie_transform_proc3 TransformPQR_from_cache = {
218
    tpqr_from_cache,
219
    0,				/* proc_name */
220
    {0, 0},			/* proc_data */
221
 
222
};
223
const gs_cie_transform_proc TransformPQR_lookup_proc_name = tpqr_lookup;
224
const gs_cie_render_proc3 Encode_default = {
225
    {render_identity, render_identity, render_identity}
226
};
227
const gs_cie_render_proc3 EncodeLMN_from_cache = {
228
    {EncodeLMN_cached_L, EncodeLMN_cached_M, EncodeLMN_cached_N}
229
};
230
const gs_cie_render_proc3 EncodeABC_from_cache = {
231
    {EncodeABC_cached_A, EncodeABC_cached_B, EncodeABC_cached_C}
232
};
233
const gs_cie_render_table_procs RenderTableT_default = {
234
    {render_table_identity, render_table_identity, render_table_identity,
235
     render_table_identity
236
    }
237
};
238
const gs_cie_render_table_procs RenderTableT_from_cache = {
239
    {RTT_cached_0, RTT_cached_1, RTT_cached_2, RTT_cached_3}
240
};
241
 
242
/*
243
 * Allocate and minimally initialize a CRD.  Note that this procedure sets
244
 * the reference count of the structure to 1, not 0.  gs_setcolorrendering
245
 * will increment the reference count again, so unless you want the
246
 * structure to stay allocated permanently (or until a garbage collection),
247
 * you should call rc_decrement(pcrd, "client name") *after* calling
248
 * gs_setcolorrendering.
249
 */
250
int
251
gs_cie_render1_build(gs_cie_render ** ppcrd, gs_memory_t * mem,
252
		     client_name_t cname)
253
{
254
    gs_cie_render *pcrd;
255
 
256
    rc_alloc_struct_1(pcrd, gs_cie_render, &st_cie_render1, mem,
257
		      return_error(gs_error_VMerror), cname);
258
    pcrd->id = gs_next_ids(mem, 1);
259
    /* Initialize pointers for the GC. */
260
    pcrd->client_data = 0;
261
    pcrd->RenderTable.lookup.table = 0;
262
    pcrd->status = CIE_RENDER_STATUS_BUILT;
263
    *ppcrd = pcrd;
264
    return 0;
265
}
266
 
267
/*
268
 * Initialize a CRD given all of the relevant parameters.
269
 * Any of the pointers except WhitePoint may be zero, meaning
270
 * use the default values.
271
 *
272
 * The actual point, matrix, range, and procedure values are copied into the
273
 * CRD, but only the pointer to the color lookup table is copied.
274
 *
275
 * If pfrom_crd is not NULL, then if the EncodeLMN, EncodeABC, or
276
 * RenderTable.T procedures indicate that the values exist only in the
277
 * cache, the corresponding values will be copied from pfrom_crd.
278
 * Note that NULL values for the individual pointers still represent
279
 * default values.
280
 */
281
int
282
gs_cie_render1_init_from(const gs_memory_t *mem,
283
			 gs_cie_render * pcrd, 
284
			 void *client_data,
285
			 const gs_cie_render * pfrom_crd,
286
			 const gs_vector3 * WhitePoint,
287
			 const gs_vector3 * BlackPoint,
288
			 const gs_matrix3 * MatrixPQR,
289
			 const gs_range3 * RangePQR,
290
			 const gs_cie_transform_proc3 * TransformPQR,
291
			 const gs_matrix3 * MatrixLMN,
292
			 const gs_cie_render_proc3 * EncodeLMN,
293
			 const gs_range3 * RangeLMN,
294
			 const gs_matrix3 * MatrixABC,
295
			 const gs_cie_render_proc3 * EncodeABC,
296
			 const gs_range3 * RangeABC,
297
			 const gs_cie_render_table_t * RenderTable)
298
{
299
    pcrd->id = gs_next_ids(mem, 1);
300
    pcrd->client_data = client_data;
301
    pcrd->points.WhitePoint = *WhitePoint;
302
    pcrd->points.BlackPoint =
303
	*(BlackPoint ? BlackPoint : &BlackPoint_default);
304
    pcrd->MatrixPQR = *(MatrixPQR ? MatrixPQR : &Matrix3_default);
305
    pcrd->RangePQR = *(RangePQR ? RangePQR : &Range3_default);
306
    pcrd->TransformPQR =
307
	*(TransformPQR ? TransformPQR : &TransformPQR_default);
308
    pcrd->MatrixLMN = *(MatrixLMN ? MatrixLMN : &Matrix3_default);
309
    pcrd->EncodeLMN = *(EncodeLMN ? EncodeLMN : &Encode_default);
310
    if (pfrom_crd &&
311
	!memcmp(&pcrd->EncodeLMN, &EncodeLMN_from_cache,
312
		sizeof(EncodeLMN_from_cache))
313
	)
314
	memcpy(&pcrd->caches.EncodeLMN, &pfrom_crd->caches.EncodeLMN,
315
	       sizeof(pcrd->caches.EncodeLMN));
316
    pcrd->RangeLMN = *(RangeLMN ? RangeLMN : &Range3_default);
317
    pcrd->MatrixABC = *(MatrixABC ? MatrixABC : &Matrix3_default);
318
    pcrd->EncodeABC = *(EncodeABC ? EncodeABC : &Encode_default);
319
    if (pfrom_crd &&
320
	!memcmp(&pcrd->EncodeABC, &EncodeABC_from_cache,
321
		sizeof(EncodeABC_from_cache))
322
	)
323
	memcpy(pcrd->caches.EncodeABC, pfrom_crd->caches.EncodeABC,
324
	       sizeof(pcrd->caches.EncodeABC));
325
    pcrd->RangeABC = *(RangeABC ? RangeABC : &Range3_default);
326
    if (RenderTable) {
327
	pcrd->RenderTable = *RenderTable;
328
	if (pfrom_crd &&
329
	    !memcmp(&pcrd->RenderTable.T, &RenderTableT_from_cache,
330
		    sizeof(RenderTableT_from_cache))
331
	    ) {
332
	    memcpy(pcrd->caches.RenderTableT, pfrom_crd->caches.RenderTableT,
333
		   sizeof(pcrd->caches.RenderTableT));
334
	    pcrd->caches.RenderTableT_is_identity =
335
		pfrom_crd->caches.RenderTableT_is_identity;
336
	}
337
    } else {
338
	pcrd->RenderTable.lookup.table = 0;
339
	pcrd->RenderTable.T = RenderTableT_default;
340
    }
341
    pcrd->status = CIE_RENDER_STATUS_BUILT;
342
    return 0;
343
}
344
/*
345
 * Initialize a CRD without the option of copying cached values.
346
 */
347
int
348
gs_cie_render1_initialize(const gs_memory_t *mem,
349
			  gs_cie_render * pcrd, void *client_data,
350
			  const gs_vector3 * WhitePoint,
351
			  const gs_vector3 * BlackPoint,
352
			  const gs_matrix3 * MatrixPQR,
353
			  const gs_range3 * RangePQR,
354
			  const gs_cie_transform_proc3 * TransformPQR,
355
			  const gs_matrix3 * MatrixLMN,
356
			  const gs_cie_render_proc3 * EncodeLMN,
357
			  const gs_range3 * RangeLMN,
358
			  const gs_matrix3 * MatrixABC,
359
			  const gs_cie_render_proc3 * EncodeABC,
360
			  const gs_range3 * RangeABC,
361
			  const gs_cie_render_table_t * RenderTable)
362
{
363
    return gs_cie_render1_init_from(mem, pcrd, client_data, NULL,
364
				    WhitePoint, BlackPoint,
365
				    MatrixPQR, RangePQR, TransformPQR,
366
				    MatrixLMN, EncodeLMN, RangeLMN,
367
				    MatrixABC, EncodeABC, RangeABC,
368
				    RenderTable);
369
}