1 /* Copyright (C) 1998, 1999 artofcode LLC. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2 of the License, or (at your
6 option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16
17 */
18
19 /*$Id: gscrdp.c,v 1.2.6.1.2.1 2003/01/17 00:49:02 giles Exp $ */
20 /* CIE color rendering dictionary creation */
21 #include "math_.h"
22 #include "memory_.h"
23 #include "string_.h"
24 #include "gx.h"
25 #include "gsdevice.h"
26 #include "gserrors.h"
27 #include "gsmatrix.h" /* for gscolor2.h */
28 #include "gsstruct.h"
29 #include "gxcspace.h"
30 #include "gscolor2.h" /* for gs_set/currentcolorrendering */
31 #include "gscrdp.h"
32 #include "gxarith.h"
33
34 /* ---------------- Writing ---------------- */
35
36 /* Internal procedures for writing parameter values. */
37 private void
store_vector3(float * p,const gs_vector3 * pvec)38 store_vector3(float *p, const gs_vector3 * pvec)
39 {
40 p[0] = pvec->u, p[1] = pvec->v, p[2] = pvec->w;
41 }
42 private int
write_floats(gs_param_list * plist,gs_param_name key,const float * values,int size,gs_memory_t * mem)43 write_floats(gs_param_list * plist, gs_param_name key,
44 const float *values, int size, gs_memory_t * mem)
45 {
46 float *p = (float *)
47 gs_alloc_byte_array(mem, size, sizeof(float), "write_floats");
48 gs_param_float_array fa;
49
50 if (p == 0)
51 return_error(gs_error_VMerror);
52 memcpy(p, values, size * sizeof(float));
53
54 fa.data = p;
55 fa.size = size;
56 fa.persistent = true;
57 return param_write_float_array(plist, key, &fa);
58 }
59 private int
write_vector3(gs_param_list * plist,gs_param_name key,const gs_vector3 * pvec,gs_memory_t * mem)60 write_vector3(gs_param_list * plist, gs_param_name key,
61 const gs_vector3 * pvec, gs_memory_t * mem)
62 {
63 float values[3];
64
65 store_vector3(values, pvec);
66 return write_floats(plist, key, values, 3, mem);
67 }
68 private int
write_matrix3(gs_param_list * plist,gs_param_name key,const gs_matrix3 * pmat,gs_memory_t * mem)69 write_matrix3(gs_param_list * plist, gs_param_name key,
70 const gs_matrix3 * pmat, gs_memory_t * mem)
71 {
72 float values[9];
73
74 if (!memcmp(pmat, &Matrix3_default, sizeof(*pmat)))
75 return 0;
76 store_vector3(values, &pmat->cu);
77 store_vector3(values + 3, &pmat->cv);
78 store_vector3(values + 6, &pmat->cw);
79 return write_floats(plist, key, values, 9, mem);
80 }
81 private int
write_range3(gs_param_list * plist,gs_param_name key,const gs_range3 * prange,gs_memory_t * mem)82 write_range3(gs_param_list * plist, gs_param_name key,
83 const gs_range3 * prange, gs_memory_t * mem)
84 {
85 float values[6];
86
87 if (!memcmp(prange, &Range3_default, sizeof(*prange)))
88 return 0;
89 values[0] = prange->ranges[0].rmin, values[1] = prange->ranges[0].rmax;
90 values[2] = prange->ranges[1].rmin, values[3] = prange->ranges[1].rmax;
91 values[4] = prange->ranges[2].rmin, values[5] = prange->ranges[2].rmax;
92 return write_floats(plist, key, values, 6, mem);
93 }
94 private int
write_proc3(gs_param_list * plist,gs_param_name key,const gs_cie_render * pcrd,const gs_cie_render_proc3 * procs,const gs_range3 * domain,gs_memory_t * mem)95 write_proc3(gs_param_list * plist, gs_param_name key,
96 const gs_cie_render * pcrd, const gs_cie_render_proc3 * procs,
97 const gs_range3 * domain, gs_memory_t * mem)
98 {
99 float *values;
100 uint size = gx_cie_cache_size;
101 gs_param_float_array fa;
102 int i;
103
104 if (!memcmp(procs, &Encode_default, sizeof(*procs)))
105 return 0;
106 values = (float *)gs_alloc_byte_array(mem, size * 3, sizeof(float),
107 "write_proc3");
108
109 if (values == 0)
110 return_error(gs_error_VMerror);
111 for (i = 0; i < 3; ++i) {
112 double base = domain->ranges[i].rmin;
113 double scale = (domain->ranges[i].rmax - base) / (size - 1);
114 int j;
115
116 for (j = 0; j < size; ++j)
117 values[i * size + j] =
118 (*procs->procs[i]) (j * scale + base, pcrd);
119 }
120 fa.data = values;
121 fa.size = size * 3;
122 fa.persistent = true;
123 return param_write_float_array(plist, key, &fa);
124 }
125
126 /* Write a CRD as a device parameter. */
127 int
param_write_cie_render1(gs_param_list * plist,gs_param_name key,gs_cie_render * pcrd,gs_memory_t * mem)128 param_write_cie_render1(gs_param_list * plist, gs_param_name key,
129 gs_cie_render * pcrd, gs_memory_t * mem)
130 {
131 gs_param_dict dict;
132 int code, dcode;
133
134 dict.size = 20;
135 if ((code = param_begin_write_dict(plist, key, &dict, false)) < 0)
136 return code;
137 code = param_put_cie_render1(dict.list, pcrd, mem);
138 dcode = param_end_write_dict(plist, key, &dict);
139 return (code < 0 ? code : dcode);
140 }
141
142 /* Write a CRD directly to a parameter list. */
143 int
param_put_cie_render1(gs_param_list * plist,gs_cie_render * pcrd,gs_memory_t * mem)144 param_put_cie_render1(gs_param_list * plist, gs_cie_render * pcrd,
145 gs_memory_t * mem)
146 {
147 int crd_type = GX_DEVICE_CRD1_TYPE;
148 int code = gs_cie_render_sample(pcrd); /* we need RenderTableT_is_id' */
149
150 if (code < 0)
151 return code;
152 if (pcrd->TransformPQR.proc_name) {
153 gs_param_string pn, pd;
154
155 param_string_from_string(pn, pcrd->TransformPQR.proc_name);
156 pn.size++; /* include terminating null */
157 pd.data = pcrd->TransformPQR.proc_data.data;
158 pd.size = pcrd->TransformPQR.proc_data.size;
159 pd.persistent = true; /****** WRONG ******/
160 if ((code = param_write_name(plist, "TransformPQRName", &pn)) < 0 ||
161 (code = param_write_string(plist, "TransformPQRData", &pd)) < 0
162 )
163 return code;
164 }
165 else if (pcrd->TransformPQR.proc != TransformPQR_default.proc) {
166 /* We have no way to represent the procedure, so return an error. */
167 return_error(gs_error_rangecheck);
168 }
169 if ((code = param_write_int(plist, "ColorRenderingType", &crd_type)) < 0 ||
170 (code = write_vector3(plist, "WhitePoint", &pcrd->points.WhitePoint, mem)) < 0
171 )
172 return code;
173 if (memcmp(&pcrd->points.BlackPoint, &BlackPoint_default,
174 sizeof(pcrd->points.BlackPoint))) {
175 if ((code = write_vector3(plist, "BlackPoint", &pcrd->points.BlackPoint, mem)) < 0)
176 return code;
177 }
178 if ((code = write_matrix3(plist, "MatrixPQR", &pcrd->MatrixPQR, mem)) < 0 ||
179 (code = write_range3(plist, "RangePQR", &pcrd->RangePQR, mem)) < 0 ||
180 /* TransformPQR is handled separately */
181 (code = write_matrix3(plist, "MatrixLMN", &pcrd->MatrixLMN, mem)) < 0 ||
182 (code = write_proc3(plist, "EncodeLMNValues", pcrd,
183 &pcrd->EncodeLMN, &pcrd->DomainLMN, mem)) < 0 ||
184 (code = write_range3(plist, "RangeLMN", &pcrd->RangeLMN, mem)) < 0 ||
185 (code = write_matrix3(plist, "MatrixABC", &pcrd->MatrixABC, mem)) < 0 ||
186 (code = write_proc3(plist, "EncodeABCValues", pcrd,
187 &pcrd->EncodeABC, &pcrd->DomainABC, mem)) < 0 ||
188 (code = write_range3(plist, "RangeABC", &pcrd->RangeABC, mem)) < 0
189 )
190 return code;
191 if (pcrd->RenderTable.lookup.table) {
192 int n = pcrd->RenderTable.lookup.n;
193 int m = pcrd->RenderTable.lookup.m;
194 int na = pcrd->RenderTable.lookup.dims[0];
195 int *size = (int *)
196 gs_alloc_byte_array(mem, n + 1, sizeof(int), "RenderTableSize");
197
198 /*
199 * In principle, we should use gs_alloc_struct_array with a
200 * type descriptor for gs_param_string. However, it is widely
201 * assumed that parameter lists are transient, and don't require
202 * accurate GC information; so we can get away with allocating
203 * the string table as bytes.
204 */
205 gs_param_string *table =
206 (gs_param_string *)
207 gs_alloc_byte_array(mem, na, sizeof(gs_param_string),
208 "RenderTableTable");
209 gs_param_int_array ia;
210
211 if (size == 0 || table == 0)
212 code = gs_note_error(gs_error_VMerror);
213 else {
214 memcpy(size, pcrd->RenderTable.lookup.dims, sizeof(int) * n);
215
216 size[n] = m;
217 ia.data = size;
218 ia.size = n + 1;
219 ia.persistent = true;
220 code = param_write_int_array(plist, "RenderTableSize", &ia);
221 }
222 if (code >= 0) {
223 gs_param_string_array sa;
224 int a;
225
226 for (a = 0; a < na; ++a)
227 table[a].data = pcrd->RenderTable.lookup.table[a].data,
228 table[a].size = pcrd->RenderTable.lookup.table[a].size,
229 table[a].persistent = true;
230 sa.data = table;
231 sa.size = na;
232 sa.persistent = true;
233 code = param_write_string_array(plist, "RenderTableTable", &sa);
234 if (code >= 0 && !pcrd->caches.RenderTableT_is_identity) {
235 /****** WRITE RenderTableTValues LIKE write_proc3 ******/
236 uint size = gx_cie_cache_size;
237 float *values =
238 (float *)gs_alloc_byte_array(mem, size * m,
239 sizeof(float),
240 "write_proc3");
241 gs_param_float_array fa;
242 int i;
243
244 if (values == 0)
245 return_error(gs_error_VMerror);
246 for (i = 0; i < m; ++i) {
247 double scale = 255.0 / (size - 1);
248 int j;
249
250 for (j = 0; j < size; ++j)
251 values[i * size + j] =
252 frac2float((*pcrd->RenderTable.T.procs[i])
253 (j * scale, pcrd));
254 }
255 fa.data = values;
256 fa.size = size * m;
257 fa.persistent = true;
258 code = param_write_float_array(plist, "RenderTableTValues",
259 &fa);
260 }
261 }
262 if (code < 0) {
263 gs_free_object(mem, table, "RenderTableTable");
264 gs_free_object(mem, size, "RenderTableSize");
265 return code;
266 }
267 }
268 return code;
269 }
270
271 /* ---------------- Reading ---------------- */
272
273 /* Internal procedures for reading parameter values. */
274 private void
load_vector3(gs_vector3 * pvec,const float * p)275 load_vector3(gs_vector3 * pvec, const float *p)
276 {
277 pvec->u = p[0], pvec->v = p[1], pvec->w = p[2];
278 }
279 private int
read_floats(gs_param_list * plist,gs_param_name key,float * values,int count)280 read_floats(gs_param_list * plist, gs_param_name key, float *values, int count)
281 {
282 gs_param_float_array fa;
283 int code = param_read_float_array(plist, key, &fa);
284
285 if (code)
286 return code;
287 if (fa.size != count)
288 return_error(gs_error_rangecheck);
289 memcpy(values, fa.data, sizeof(float) * count);
290
291 return 0;
292 }
293 private int
read_vector3(gs_param_list * plist,gs_param_name key,gs_vector3 * pvec,const gs_vector3 * dflt)294 read_vector3(gs_param_list * plist, gs_param_name key,
295 gs_vector3 * pvec, const gs_vector3 * dflt)
296 {
297 float values[3];
298 int code = read_floats(plist, key, values, 3);
299
300 switch (code) {
301 case 1: /* not defined */
302 if (dflt)
303 *pvec = *dflt;
304 break;
305 case 0:
306 load_vector3(pvec, values);
307 default: /* error */
308 break;
309 }
310 return code;
311 }
312 private int
read_matrix3(gs_param_list * plist,gs_param_name key,gs_matrix3 * pmat)313 read_matrix3(gs_param_list * plist, gs_param_name key, gs_matrix3 * pmat)
314 {
315 float values[9];
316 int code = read_floats(plist, key, values, 9);
317
318 switch (code) {
319 case 1: /* not defined */
320 *pmat = Matrix3_default;
321 break;
322 case 0:
323 load_vector3(&pmat->cu, values);
324 load_vector3(&pmat->cv, values + 3);
325 load_vector3(&pmat->cw, values + 6);
326 default: /* error */
327 break;
328 }
329 return code;
330 }
331 private int
read_range3(gs_param_list * plist,gs_param_name key,gs_range3 * prange)332 read_range3(gs_param_list * plist, gs_param_name key, gs_range3 * prange)
333 {
334 float values[6];
335 int code = read_floats(plist, key, values, 6);
336
337 switch (code) {
338 case 1: /* not defined */
339 *prange = Range3_default;
340 break;
341 case 0:
342 prange->ranges[0].rmin = values[0];
343 prange->ranges[0].rmax = values[1];
344 prange->ranges[1].rmin = values[2];
345 prange->ranges[1].rmax = values[3];
346 prange->ranges[2].rmin = values[4];
347 prange->ranges[2].rmax = values[5];
348 default: /* error */
349 break;
350 }
351 return code;
352 }
353 private int
read_proc3(gs_param_list * plist,gs_param_name key,float values[gx_cie_cache_size * 3])354 read_proc3(gs_param_list * plist, gs_param_name key,
355 float values[gx_cie_cache_size * 3])
356 {
357 return read_floats(plist, key, values, gx_cie_cache_size * 3);
358 }
359
360 /* Read a CRD from a device parameter. */
361 int
gs_cie_render1_param_initialize(gs_cie_render * pcrd,gs_param_list * plist,gs_param_name key,gx_device * dev)362 gs_cie_render1_param_initialize(gs_cie_render * pcrd, gs_param_list * plist,
363 gs_param_name key, gx_device * dev)
364 {
365 gs_param_dict dict;
366 int code = param_begin_read_dict(plist, key, &dict, false);
367 int dcode;
368
369 if (code < 0)
370 return code;
371 code = param_get_cie_render1(pcrd, dict.list, dev);
372 dcode = param_end_read_dict(plist, key, &dict);
373 if (code < 0)
374 return code;
375 if (dcode < 0)
376 return dcode;
377 gs_cie_render_init(pcrd);
378 gs_cie_render_sample(pcrd);
379 return gs_cie_render_complete(pcrd);
380 }
381
382 /* Define the structure for passing Encode values as "client data". */
383 typedef struct encode_data_s {
384 float lmn[gx_cie_cache_size * 3]; /* EncodeLMN */
385 float abc[gx_cie_cache_size * 3]; /* EncodeABC */
386 float t[gx_cie_cache_size * 4]; /* RenderTable.T */
387 } encode_data_t;
388
389 /* Define procedures that retrieve the Encode values read from the list. */
390 private float
encode_from_data(floatp v,const float values[gx_cie_cache_size],const gs_range * range)391 encode_from_data(floatp v, const float values[gx_cie_cache_size],
392 const gs_range * range)
393 {
394 return (v <= range->rmin ? values[0] :
395 v >= range->rmax ? values[gx_cie_cache_size - 1] :
396 values[(int)((v - range->rmin) / (range->rmax - range->rmin) *
397 (gx_cie_cache_size - 1) + 0.5)]);
398 }
399 /*
400 * The repetitive boilerplate in the next 10 procedures really sticks in
401 * my craw, but I've got a mandate not to use macros....
402 */
403 private float
encode_lmn_0_from_data(floatp v,const gs_cie_render * pcrd)404 encode_lmn_0_from_data(floatp v, const gs_cie_render * pcrd)
405 {
406 const encode_data_t *data = pcrd->client_data;
407
408 return encode_from_data(v, &data->lmn[0],
409 &pcrd->DomainLMN.ranges[0]);
410 }
411 private float
encode_lmn_1_from_data(floatp v,const gs_cie_render * pcrd)412 encode_lmn_1_from_data(floatp v, const gs_cie_render * pcrd)
413 {
414 const encode_data_t *data = pcrd->client_data;
415
416 return encode_from_data(v, &data->lmn[gx_cie_cache_size],
417 &pcrd->DomainLMN.ranges[1]);
418 }
419 private float
encode_lmn_2_from_data(floatp v,const gs_cie_render * pcrd)420 encode_lmn_2_from_data(floatp v, const gs_cie_render * pcrd)
421 {
422 const encode_data_t *data = pcrd->client_data;
423
424 return encode_from_data(v, &data->lmn[gx_cie_cache_size * 2],
425 &pcrd->DomainLMN.ranges[2]);
426 }
427 private float
encode_abc_0_from_data(floatp v,const gs_cie_render * pcrd)428 encode_abc_0_from_data(floatp v, const gs_cie_render * pcrd)
429 {
430 const encode_data_t *data = pcrd->client_data;
431
432 return encode_from_data(v, &data->abc[0],
433 &pcrd->DomainABC.ranges[0]);
434 }
435 private float
encode_abc_1_from_data(floatp v,const gs_cie_render * pcrd)436 encode_abc_1_from_data(floatp v, const gs_cie_render * pcrd)
437 {
438 const encode_data_t *data = pcrd->client_data;
439
440 return encode_from_data(v, &data->abc[gx_cie_cache_size],
441 &pcrd->DomainABC.ranges[1]);
442 }
443 private float
encode_abc_2_from_data(floatp v,const gs_cie_render * pcrd)444 encode_abc_2_from_data(floatp v, const gs_cie_render * pcrd)
445 {
446 const encode_data_t *data = pcrd->client_data;
447
448 return encode_from_data(v, &data->abc[gx_cie_cache_size * 2],
449 &pcrd->DomainABC.ranges[2]);
450 }
451 private frac
render_table_t_0_from_data(byte v,const gs_cie_render * pcrd)452 render_table_t_0_from_data(byte v, const gs_cie_render * pcrd)
453 {
454 const encode_data_t *data = pcrd->client_data;
455
456 return float2frac(encode_from_data(v / 255.0,
457 &data->t[0],
458 &Range3_default.ranges[0]));
459 }
460 private frac
render_table_t_1_from_data(byte v,const gs_cie_render * pcrd)461 render_table_t_1_from_data(byte v, const gs_cie_render * pcrd)
462 {
463 const encode_data_t *data = pcrd->client_data;
464
465 return float2frac(encode_from_data(v / 255.0,
466 &data->t[gx_cie_cache_size],
467 &Range3_default.ranges[0]));
468 }
469 private frac
render_table_t_2_from_data(byte v,const gs_cie_render * pcrd)470 render_table_t_2_from_data(byte v, const gs_cie_render * pcrd)
471 {
472 const encode_data_t *data = pcrd->client_data;
473
474 return float2frac(encode_from_data(v / 255.0,
475 &data->t[gx_cie_cache_size * 2],
476 &Range3_default.ranges[0]));
477 }
478 private frac
render_table_t_3_from_data(byte v,const gs_cie_render * pcrd)479 render_table_t_3_from_data(byte v, const gs_cie_render * pcrd)
480 {
481 const encode_data_t *data = pcrd->client_data;
482
483 return float2frac(encode_from_data(v / 255.0,
484 &data->t[gx_cie_cache_size * 3],
485 &Range3_default.ranges[0]));
486 }
487 private const gs_cie_render_proc3 EncodeLMN_from_data = {
488 {encode_lmn_0_from_data, encode_lmn_1_from_data, encode_lmn_2_from_data}
489 };
490 private const gs_cie_render_proc3 EncodeABC_from_data = {
491 {encode_abc_0_from_data, encode_abc_1_from_data, encode_abc_2_from_data}
492 };
493 private const gs_cie_render_table_procs RenderTableT_from_data = {
494 {render_table_t_0_from_data, render_table_t_1_from_data,
495 render_table_t_2_from_data, render_table_t_3_from_data
496 }
497 };
498
499 /* Read a CRD directly from a parameter list. */
500 int
param_get_cie_render1(gs_cie_render * pcrd,gs_param_list * plist,gx_device * dev)501 param_get_cie_render1(gs_cie_render * pcrd, gs_param_list * plist,
502 gx_device * dev)
503 {
504 encode_data_t data;
505 gs_param_int_array rt_size;
506 int crd_type;
507 int code, code_lmn, code_abc, code_rt, code_t;
508 gs_param_string pname, pdata;
509
510 /* Reset the status to invalidate cached information. */
511 pcrd->status = CIE_RENDER_STATUS_BUILT;
512 if ((code = param_read_int(plist, "ColorRenderingType", &crd_type)) < 0 ||
513 crd_type != GX_DEVICE_CRD1_TYPE ||
514 (code = read_vector3(plist, "WhitePoint", &pcrd->points.WhitePoint,
515 NULL)) < 0 ||
516 (code = read_vector3(plist, "BlackPoint", &pcrd->points.BlackPoint,
517 &BlackPoint_default)) < 0 ||
518 (code = read_matrix3(plist, "MatrixPQR", &pcrd->MatrixPQR)) < 0 ||
519 (code = read_range3(plist, "RangePQR", &pcrd->RangePQR)) < 0 ||
520 /* TransformPQR is handled specially below. */
521 (code = read_matrix3(plist, "MatrixLMN", &pcrd->MatrixLMN)) < 0 ||
522 (code_lmn = code =
523 read_proc3(plist, "EncodeLMNValues", data.lmn)) < 0 ||
524 (code = read_range3(plist, "RangeLMN", &pcrd->RangeLMN)) < 0 ||
525 (code = read_matrix3(plist, "MatrixABC", &pcrd->MatrixABC)) < 0 ||
526 (code_abc = code =
527 read_proc3(plist, "EncodeABCValues", data.abc)) < 0 ||
528 (code = read_range3(plist, "RangeABC", &pcrd->RangeABC)) < 0
529 )
530 return code;
531 /* Handle the sampled functions. */
532 switch (code = param_read_string(plist, "TransformPQRName", &pname)) {
533 default: /* error */
534 return code;
535 case 1: /* missing */
536 pcrd->TransformPQR = TransformPQR_default;
537 break;
538 case 0: /* specified */
539 /* The procedure name must be null-terminated: */
540 /* see param_put_cie_render1 above. */
541 if (pname.size < 1 || pname.data[pname.size - 1] != 0)
542 return_error(gs_error_rangecheck);
543 pcrd->TransformPQR.proc = TransformPQR_lookup_proc_name;
544 pcrd->TransformPQR.proc_name = (char *)pname.data;
545 switch (code = param_read_string(plist, "TransformPQRData", &pdata)) {
546 default: /* error */
547 return code;
548 case 1: /* missing */
549 pcrd->TransformPQR.proc_data.data = 0;
550 pcrd->TransformPQR.proc_data.size = 0;
551 break;
552 case 0:
553 pcrd->TransformPQR.proc_data.data = pdata.data;
554 pcrd->TransformPQR.proc_data.size = pdata.size;
555 }
556 pcrd->TransformPQR.driver_name = gs_devicename(dev);
557 break;
558 }
559 pcrd->client_data = &data;
560 if (code_lmn > 0)
561 pcrd->EncodeLMN = Encode_default;
562 else
563 pcrd->EncodeLMN = EncodeLMN_from_data;
564 if (code_abc > 0)
565 pcrd->EncodeABC = Encode_default;
566 else
567 pcrd->EncodeABC = EncodeABC_from_data;
568 code_rt = code = param_read_int_array(plist, "RenderTableSize", &rt_size);
569 if (code == 1) {
570 if (pcrd->RenderTable.lookup.table) {
571 gs_free_object(pcrd->rc.memory,
572 (void *)pcrd->RenderTable.lookup.table, /* break const */
573 "param_get_cie_render1(RenderTable)");
574 pcrd->RenderTable.lookup.table = 0;
575 }
576 pcrd->RenderTable.T = RenderTableT_default;
577 code_t = 1;
578 } else if (code < 0)
579 return code;
580 else if (rt_size.size != 4)
581 return_error(gs_error_rangecheck);
582 else {
583 gs_param_string_array rt_values;
584 gs_const_string *table;
585 int n, m, j;
586
587 for (j = 0; j < rt_size.size; ++j)
588 if (rt_size.data[j] < 1)
589 return_error(gs_error_rangecheck);
590 code = param_read_string_array(plist, "RenderTableTable", &rt_values);
591 if (code < 0)
592 return code;
593 if (code > 0 || rt_values.size != rt_size.data[0])
594 return_error(gs_error_rangecheck);
595 /* Note: currently n = 3 (rt_size.size = 4) always. */
596 for (j = 0; j < rt_values.size; ++j)
597 if (rt_values.data[j].size !=
598 rt_size.data[1] * rt_size.data[2] * rt_size.data[3])
599 return_error(gs_error_rangecheck);
600 pcrd->RenderTable.lookup.n = n = rt_size.size - 1;
601 pcrd->RenderTable.lookup.m = m = rt_size.data[n];
602 if (n > 4 || m > 4)
603 return_error(gs_error_rangecheck);
604 memcpy(pcrd->RenderTable.lookup.dims, rt_size.data, n * sizeof(int));
605 table =
606 gs_alloc_struct_array(pcrd->rc.memory,
607 pcrd->RenderTable.lookup.dims[0],
608 gs_const_string, &st_const_string_element,
609 "RenderTable table");
610 if (table == 0)
611 return_error(gs_error_VMerror);
612 for (j = 0; j < pcrd->RenderTable.lookup.dims[0]; ++j) {
613 table[j].data = rt_values.data[j].data;
614 table[j].size = rt_values.data[j].size;
615 }
616 pcrd->RenderTable.lookup.table = table;
617 pcrd->RenderTable.T = RenderTableT_from_data;
618 code_t = code = read_floats(plist, "RenderTableTValues", data.t,
619 gx_cie_cache_size * m);
620 if (code > 0)
621 pcrd->RenderTable.T = RenderTableT_default;
622 else if (code == 0)
623 pcrd->RenderTable.T = RenderTableT_from_data;
624 }
625 if ((code = gs_cie_render_init(pcrd)) >= 0 &&
626 (code = gs_cie_render_sample(pcrd)) >= 0
627 )
628 code = gs_cie_render_complete(pcrd);
629 /* Clean up before exiting. */
630 pcrd->client_data = 0;
631 if (code_lmn == 0)
632 pcrd->EncodeLMN = EncodeLMN_from_cache;
633 if (code_abc == 0)
634 pcrd->EncodeABC = EncodeABC_from_cache;
635 if (code_t == 0)
636 pcrd->RenderTable.T = RenderTableT_from_cache;
637 return code;
638 }
639