xref: /plan9/sys/src/cmd/gs/src/gscie.h (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1992, 1995, 1997, 1998, 1999, 2001 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: gscie.h,v 1.14 2005/05/05 05:35:22 dan Exp $ */
18 /* Structures for CIE color algorithms */
19 /* (requires gscspace.h, gscolor2.h) */
20 
21 #ifndef gscie_INCLUDED
22 #  define gscie_INCLUDED
23 
24 #include "gconfigv.h"		/* for USE_FPU */
25 #include "gsrefct.h"
26 #include "gsstype.h"		/* for extern_st */
27 #include "gstypes.h"		/* for gs_range_t */
28 #include "gxctable.h"
29 
30 /* ---------------- Configuration parameters ---------------- */
31 
32 /* Define the size of the Encode/Decode/Transform procedure value caches. */
33 /* With the current design, these caches must all have the same size. */
34 #ifndef CIE_LOG2_CACHE_SIZE
35 #  define CIE_LOG2_CACHE_SIZE 9
36 #endif
37 
38 /* Define whether to use fixed- or floating-point values in the caches. */
39 /*#define CIE_CACHE_USE_FIXED */
40 #if USE_FPU < 0
41 #  define CIE_CACHE_USE_FIXED
42 #endif
43 
44 /* If we are using fixed-point values, define the number of fraction bits. */
45 #define CIE_FIXED_FRACTION_BITS 12
46 
47 /*
48  * Interpolation between adjacent cached values is computationally very
49  * expensive, but it is necessary in numerically sensitive areas.  We
50  * characterize this by a threshold value V >= 0: we interpolate
51  * between adjacent cache values A = C[i] and B = C[i+1] if |B-A| >= V *
52  * min(|A|,|B|).  V = 0 means always interpolate; if V is undefined,
53  * we never interpolate.
54  */
55 
56 /*
57  * Define whether to interpolate between cached values.
58  */
59 #define CIE_CACHE_INTERPOLATE
60 
61 /*
62  * Define the threshold for interpolating.
63  * This is computationally expensive.
64  */
65 #define CIE_INTERPOLATE_THRESHOLD 0.001
66 
67 /*
68  * Define whether to interpolate in the RenderTable.  Currently this is a
69  * Boolean rather than a threshold.  This is computationally very expensive,
70  * but unfortunately it seems to be necessary.
71  */
72 #define CIE_RENDER_TABLE_INTERPOLATE
73 
74 /* ------ Derived values ------ */
75 
76 /* from CIE_LOG2_CACHE_SIZE */
77 #define gx_cie_log2_cache_size CIE_LOG2_CACHE_SIZE
78 #define gx_cie_cache_size (1 << gx_cie_log2_cache_size)
79 
80 /* From CIE_FIXED_FRACTION_BITS 12 */
81 #ifndef CIE_FIXED_FRACTION_BITS
82 /* Take as many bits as we can without having to multiply in two pieces. */
83 #  define CIE_FIXED_FRACTION_BITS\
84      ((arch_sizeof_long * 8 - gx_cie_log2_cache_size) / 2 - 1)
85 #endif
86 
87 /* From CIE_RENDER_TABLE_INTERPOLATE */
88 #ifdef CIE_RENDER_TABLE_INTERPOLATE
89 #  define CIE_CACHE_INTERPOLATE
90 #endif
91 
92 #define float_lshift(v, nb) ((v) * (1L << (nb)))
93 #define float_rshift(v, nb) ((v) * (1.0 / (1L << (nb))))
94 
95 #ifdef CIE_CACHE_INTERPOLATE
96 /* We have to have room for both a cache index and the interpolation bits */
97 /* in a positive int (i.e., leaving 1 bit for the sign), plus a little slop. */
98 /* The values for interpolation are cie_cached_values by default. */
99 #  define _cie_interpolate_bits\
100      min(arch_sizeof_int * 8 - gx_cie_log2_cache_size - 2, 10)
101 #  define _cix(i) ((i) >> _cie_interpolate_bits)
102 #  define _cif(i) ((int)(i) & ((1 << _cie_interpolate_bits) - 1))
103 #  define cie_interpolate_between(v0, v1, i)\
104      ((v0) + cie_cached_rshift(((v1) - (v0)) * _cif(i) +\
105 			        (1 << (_cie_interpolate_bits - 1)),\
106 			       _cie_interpolate_bits))
107 #  define cie_interpolate(p, i)\
108      cie_interpolate_between((p)[_cix(i)], (p)[_cix(i) + 1], i)
109 #  define cie_interpolate_fracs(p, i)\
110      ((p)[_cix(i)] +\
111       (frac)arith_rshift((long)((p)[_cix(i) + 1] - (p)[_cix(i)]) * _cif(i), _cie_interpolate_bits))
112 #else
113 #  define _cie_interpolate_bits 0
114 #  define cie_interpolate_between(v0, v1, i) (v0)
115 #  define cie_interpolate(p, i) ((p)[i])
116 #  define cie_interpolate_fracs(p, i) ((p)[i])
117 #endif
118 
119 #ifdef CIE_CACHE_USE_FIXED
120 typedef long cie_cached_value;
121 
122 #  define _cie_fixed_shift CIE_FIXED_FRACTION_BITS
123 #  define float2cie_cached(v)\
124      ((cie_cached_value)float_lshift(v, _cie_fixed_shift))
125 #  define cie_cached2float(v)\
126      float_rshift(v, _cie_fixed_shift)
127 #  define cie_cached2int(v, fbits)\
128      arith_rshift(v, _cie_fixed_shift - (fbits))
129 /* We are multiplying two cie_cached_values to produce a result that */
130 /* lies between 0 and gx_cie_cache_size - 1.  If the intermediate result */
131 /* might overflow, compute it in pieces (being a little sloppy). */
132 #  define _cie_product_excess_bits\
133      (_cie_fixed_shift * 2 + gx_cie_log2_cache_size - (arch_sizeof_long * 8 - 1))
134 #  define cie_cached_product2int(v, factor, fbits)\
135      (_cie_product_excess_bits > 0 ?\
136       arith_rshift( (v) * arith_rshift(factor, _cie_product_excess_bits) +\
137 		    arith_rshift(v, _cie_product_excess_bits) *\
138 		     ((factor) & ((1 << _cie_product_excess_bits) - 1)),\
139 		    _cie_fixed_shift * 2 - _cie_product_excess_bits - (fbits)) :\
140       arith_rshift((v) * (factor), _cie_fixed_shift * 2 - (fbits)))
141 #  define cie_cached_rshift(v, n) arith_rshift(v, n)
142 #else
143 typedef float cie_cached_value;
144 #  define float2cie_cached(v) (v)
145 #  define cie_cached2float(v) (v)
146 #  define cie_cached2int(v, fbits)\
147      ((int)float_lshift(v, fbits))
148 #  define cie_cached_product2int(v, factor, fbits)\
149      ((int)float_lshift((v) * (factor), fbits))
150 #  define cie_cached_rshift(v, n) float_rshift(v, n)
151 #endif
152 
153 /* ---------------- Structures ---------------- */
154 
155 #ifndef gs_cie_render_DEFINED
156 #  define gs_cie_render_DEFINED
157 typedef struct gs_cie_render_s gs_cie_render;
158 #endif
159 
160 /* ------ Common definitions ------ */
161 
162 /*
163  * For the purposes of the CIE routines, we consider that all the vectors
164  * are column vectors, that the matrices are specified in column order
165  * (e.g., the matrix
166  *      [ A B C ]
167  *      [ D E F ]
168  *      [ G H I ]
169  * is represented as [A D G B E H C F I]), and that to transform a vector
170  * V by a matrix M, we compute M * V to produce another column vector.
171  * Note in particular that in order to produce a matrix M that is
172  * equivalent to transforming by M1 and then by M2, we must compute
173  * M = M2 * M1.
174  */
175 
176 /* A 3-element vector. */
177 typedef struct gs_vector3_s {
178     float u, v, w;
179 } gs_vector3;
180 
181 /* A 3x3 matrix, stored in column order. */
182 typedef struct gs_matrix3_s {
183     gs_vector3 cu, cv, cw;
184     bool is_identity;
185 } gs_matrix3;
186 
187 /* 3- and 4-element vectors of ranges. */
188 /* NOTE: gs_range is deprecated for new code in favor of gs_range_t. */
189 typedef gs_range_t gs_range;
190 typedef struct gs_range3_s {
191     gs_range ranges[3];
192 } gs_range3;
193 typedef struct gs_range4_s {
194     gs_range ranges[4];
195 } gs_range4;
196 
197 /* Client-supplied transformation procedures. */
198 typedef struct gs_cie_common_s gs_cie_common;
199 typedef struct gs_cie_wbsd_s gs_cie_wbsd;
200 
201 typedef float (*gs_cie_a_proc) (floatp, const gs_cie_a *);
202 
203 typedef float (*gs_cie_abc_proc) (floatp, const gs_cie_abc *);
204 typedef struct gs_cie_abc_proc3_s {
205     gs_cie_abc_proc procs[3];
206 } gs_cie_abc_proc3;
207 
208 typedef float (*gs_cie_def_proc) (floatp, const gs_cie_def *);
209 typedef struct gs_cie_def_proc3_s {
210     gs_cie_def_proc procs[3];
211 } gs_cie_def_proc3;
212 
213 typedef float (*gs_cie_defg_proc) (floatp, const gs_cie_defg *);
214 typedef struct gs_cie_defg_proc4_s {
215     gs_cie_defg_proc procs[4];
216 } gs_cie_defg_proc4;
217 
218 typedef float (*gs_cie_common_proc) (floatp, const gs_cie_common *);
219 typedef struct gs_cie_common_proc3_s {
220     gs_cie_common_proc procs[3];
221 } gs_cie_common_proc3;
222 
223 typedef float (*gs_cie_render_proc) (floatp, const gs_cie_render *);
224 typedef struct gs_cie_render_proc3_s {
225     gs_cie_render_proc procs[3];
226 } gs_cie_render_proc3;
227 
228 /*
229  * The TransformPQR procedure depends on both the color space and the
230  * CRD, so we can't simply pass it through the band list as a table of
231  * sampled values, even though such a table exists as part of an
232  * internal cache.  Instead, we use two different approaches.  The
233  * graphics library knows that the cache must be reloaded whenever the
234  * color space or CRD changes, so we can simply transmit the cached
235  * values through the band list whenever this occurs.  However, this
236  * still leaves the issue of how to represent the procedure in the CRD
237  * per se: such a representation is required in order for
238  * currentcolorrendering and setcolorrendering to work.  For this
239  * purpose, we provide a procedure name and procedure data, which
240  * drivers can supply with their default CRDs; the driver must also be
241  * prepared to map the procedure name back to an actual set of
242  * procedures.
243  *
244  * To simplify the driver-provided CRD machinery, we define TransformPQR as
245  * a single procedure taking an integer that specifies the component number,
246  * rather than an array of procedures.  Note that if proc_name != 0,
247  * proc is irrelevant -- the driver will provide it by looking up proc_name.
248  * For this reason, the last argument of TransformPQR must be writable.
249  * Note also that since TransformPQR can fail (if the driver doesn't
250  * recognize the proc_name), it must return a failure code.
251  */
252 typedef int (*gs_cie_transform_proc)(int, floatp, const gs_cie_wbsd *,
253 				     gs_cie_render *, float *);
254 typedef struct gs_cie_transform_proc3_s {
255     gs_cie_transform_proc proc;
256     const char *proc_name;
257     gs_const_string proc_data;
258     const char *driver_name;	/* for mapping proc_name back to procs */
259 } gs_cie_transform_proc3;
260 
261 typedef frac(*gs_cie_render_table_proc) (byte, const gs_cie_render *);
262 typedef struct gs_cie_render_table_procs_s {
263     gs_cie_render_table_proc procs[4];
264 } gs_cie_render_table_procs;
265 
266 /* CIE white and black points. */
267 typedef struct gs_cie_wb_s {
268     gs_vector3 WhitePoint;
269     gs_vector3 BlackPoint;
270 } gs_cie_wb;
271 
272 /* ------ Caches ------ */
273 
274 /*
275  * Given that all the client-supplied procedures involved in CIE color
276  * mapping and rendering are monotonic, and given that we can determine
277  * the minimum and maximum input values for them, we can cache their values.
278  * This takes quite a lot of space, but eliminates the need for callbacks
279  * deep in the graphics code (particularly the image operator).
280  *
281  * The procedures, and how we determine their domains, are as follows:
282 
283  Stage          Name            Domain determination
284  -----          ----            --------------------
285  pre-decode     DecodeDEF       RangeDEF
286  pre-decode     DecodeDEFG      RangeDEFG
287  color space    DecodeA         RangeA
288  color space    DecodeABC       RangeABC
289  color space    DecodeLMN       RangeLMN
290  rendering      TransformPQR    RangePQR
291  (but depends on color space White/BlackPoints)
292  rendering      EncodeLMN       RangePQR transformed by the inverse of
293 				MatrixPQR and then by MatrixLMN
294  rendering      EncodeABC       RangeLMN transformed by MatrixABC
295  rendering      RenderTable.T   [0..1]*m
296 
297  * Note that we can mostly cache the results of the color space procedures
298  * without knowing the color rendering parameters, and vice versa,
299  * because of the range parameters supplied in the dictionaries.
300  * Unfortunately, TransformPQR is an exception.
301  */
302 /*
303  * The index into a cache is (value - base) * factor, where
304  * factor is computed as (cie_cache_size - 1) / (rmax - rmin).
305  */
306 /*
307  * We have two kinds of caches: ordinary caches, where each value is
308  * a scalar, and vector caches, where each value is a gs_cached_vector3.
309  * The latter allow us to pre-multiply the values by one column of
310  * a gs_matrix3, avoiding multiplications at lookup time.
311  *
312  * If the function being cached is simply a linear transformation,
313  * f(x) = scale * x + origin, then we can fold it into a following or
314  * preceding matrix.
315  */
316 typedef struct cie_linear_params_s {
317     bool is_linear;
318     float scale, origin;	/* if is_linear = true */
319 } cie_linear_params_t;
320 typedef struct cie_cache_params_s {
321     bool is_identity;		/* must come first */
322     double base, factor;
323     cie_linear_params_t linear;	/* only used in vector_cache.floats? */
324 } cie_cache_params;
325 typedef struct cie_cache_floats_s {
326     cie_cache_params params;
327     float values[gx_cie_cache_size];
328 } cie_cache_floats;
329 typedef struct cie_cache_fracs_s {
330     cie_cache_params params;
331     frac values[gx_cie_cache_size];
332 } cie_cache_fracs;
333 typedef struct cie_cache_ints_s {
334     cie_cache_params params;
335     int values[gx_cie_cache_size];
336 } cie_cache_ints;
337 typedef union gx_cie_scalar_cache_s {
338     cie_cache_floats floats;
339     cie_cache_fracs fracs;
340     cie_cache_ints ints;
341 } gx_cie_scalar_cache;
342 
343 typedef struct cie_cached_vector3_s {
344     cie_cached_value u, v, w;
345 } cie_cached_vector3;
346 typedef struct cie_interpolation_range_s {
347     cie_cached_value rmin, rmax;
348 } cie_interpolation_range_t;
349 typedef struct cie_vector_cache_params_s {
350     cie_cached_value base, factor, limit;
351     cie_interpolation_range_t interpolation_ranges[3];  /* if this cache has an interpolation threshold */
352 } cie_vector_cache_params;
353 typedef struct cie_cache_vectors_s {
354     cie_vector_cache_params params;
355     cie_cached_vector3 values[gx_cie_cache_size];
356 } cie_cache_vectors;
357 typedef struct gx_cie_vector_cache_s {
358     cie_cache_floats floats;
359     cie_cache_vectors vecs;
360 } gx_cie_vector_cache;
361 typedef struct gx_cie_vector_cache3_s {
362     gx_cie_vector_cache caches[3];
363     cie_interpolation_range_t interpolation_ranges[3];  /* indexed by output component */
364 } gx_cie_vector_cache3_t;
365 
366 /* ------ Color space dictionaries ------ */
367 
368 /* Elements common to all CIE color space dictionaries. */
369 struct gs_cie_common_s {
370     int (*install_cspace)(const gs_color_space *, gs_state *);
371     void *client_data;
372     gs_range3 RangeLMN;
373     gs_cie_common_proc3 DecodeLMN;
374     gs_matrix3 MatrixLMN;
375     gs_cie_wb points;
376     /* Following are computed when structure is initialized. */
377     struct {
378 	gx_cie_scalar_cache DecodeLMN[3];
379     } caches;
380 };
381 
382 /* st_cie_common and st_cie_common_elements_t are exported for gsicc.c */
383 #define public_st_cie_common()     /* in gscscie.c */\
384   gs_public_st_ptrs1(st_cie_common, gs_cie_common, "gs_cie_common",\
385 		      cie_common_enum_ptrs, cie_common_reloc_ptrs, client_data)
386 
387 /* extern_st(st_cie_common); */ /* in gxcie.h */
388 
389 #define gs_cie_common_elements\
390 	gs_cie_common common;		/* must be first */\
391 	rc_header rc
392 typedef struct gs_cie_common_elements_s {
393     gs_cie_common_elements;
394 } gs_cie_common_elements_t;
395 
396 #define public_st_cie_common_elements() /* in gscscie.c */ \
397   gs_public_st_suffix_add0_local( st_cie_common_elements_t,\
398 				  gs_cie_common_elements_t,\
399 				  "gs_cie_common_elements_t",\
400 				  cie_common_enum_ptrs,\
401 				  cie_common_reloc_ptrs,\
402 				  st_cie_common)
403 
404 /* extern_st(st_cie_common_elements_t); */ /* in gxcie.h */
405 
406 /* A CIEBasedA dictionary. */
407 struct gs_cie_a_s {
408     gs_cie_common_elements;	/* must be first */
409     gs_range RangeA;
410     gs_cie_a_proc DecodeA;
411     gs_vector3 MatrixA;
412     /* Following are computed when structure is initialized. */
413     struct {
414 	gx_cie_vector_cache DecodeA;	/* mult. by MatrixA */
415     } caches;
416 };
417 
418 #define private_st_cie_a()	/* in gscscie.c */\
419   gs_private_st_suffix_add0_local(st_cie_a, gs_cie_a, "gs_cie_a",\
420 				  cie_common_enum_ptrs,\
421 				  cie_common_reloc_ptrs,\
422 				  st_cie_common_elements_t)
423 
424 /* Common elements for CIEBasedABC, DEF, and DEFG dictionaries. */
425 #define gs_cie_abc_elements\
426 	gs_cie_common_elements;		/* must be first */\
427 	gs_range3 RangeABC;\
428 	gs_cie_abc_proc3 DecodeABC;\
429 	gs_matrix3 MatrixABC;\
430 		/* Following are computed when structure is initialized. */\
431 	struct {\
432 		bool skipABC;\
433 		gx_cie_vector_cache3_t DecodeABC;  /* mult. by MatrixABC */\
434 	} caches
435 
436 /* A CIEBasedABC dictionary. */
437 struct gs_cie_abc_s {
438     gs_cie_abc_elements;
439 };
440 
441 #define private_st_cie_abc()	/* in gscscie.c */\
442   gs_private_st_suffix_add0_local(st_cie_abc, gs_cie_abc, "gs_cie_abc",\
443 				  cie_common_enum_ptrs, cie_common_reloc_ptrs,\
444 				  st_cie_common_elements_t)
445 
446 /* A CIEBasedDEF dictionary. */
447 struct gs_cie_def_s {
448     gs_cie_abc_elements;	/* must be first */
449     gs_range3 RangeDEF;
450     gs_cie_def_proc3 DecodeDEF;
451     gs_range3 RangeHIJ;
452     gx_color_lookup_table Table;	/* [NH][NI * NJ * 3] */
453     struct {
454 	gx_cie_scalar_cache DecodeDEF[3];
455     } caches_def;
456 };
457 
458 #define private_st_cie_def()	/* in gscscie.c */\
459   gs_private_st_suffix_add1(st_cie_def, gs_cie_def, "gs_cie_def",\
460                             cie_def_enum_ptrs, cie_def_reloc_ptrs,\
461                             st_cie_abc, Table.table)
462 
463 /* A CIEBasedDEFG dictionary. */
464 struct gs_cie_defg_s {
465     gs_cie_abc_elements;
466     gs_range4 RangeDEFG;
467     gs_cie_defg_proc4 DecodeDEFG;
468     gs_range4 RangeHIJK;
469     gx_color_lookup_table Table;	/* [NH * NI][NJ * NK * 3] */
470     struct {
471 	gx_cie_scalar_cache DecodeDEFG[4];
472     } caches_defg;
473 };
474 
475 #define private_st_cie_defg()	/* in gscscie.c */\
476   gs_private_st_suffix_add1(st_cie_defg, gs_cie_defg, "gs_cie_defg",\
477 			    cie_defg_enum_ptrs, cie_defg_reloc_ptrs,\
478 			    st_cie_abc, Table.table)
479 
480 /*
481  * Default values for components.  Note that for some components, there are
482  * two sets of default procedures: _default (identity procedures) and
483  * _from_cache (procedures that just return the cached values).
484  */
485 extern const gs_range3 Range3_default;
486 extern const gs_range4 Range4_default;
487 extern const gs_cie_defg_proc4 DecodeDEFG_default;
488 extern const gs_cie_defg_proc4 DecodeDEFG_from_cache;
489 extern const gs_cie_def_proc3 DecodeDEF_default;
490 extern const gs_cie_def_proc3 DecodeDEF_from_cache;
491 extern const gs_cie_abc_proc3 DecodeABC_default;
492 extern const gs_cie_abc_proc3 DecodeABC_from_cache;
493 extern const gs_cie_common_proc3 DecodeLMN_default;
494 extern const gs_cie_common_proc3 DecodeLMN_from_cache;
495 extern const gs_matrix3 Matrix3_default;
496 extern const gs_range RangeA_default;
497 extern const gs_cie_a_proc DecodeA_default;
498 extern const gs_cie_a_proc DecodeA_from_cache;
499 extern const gs_vector3 MatrixA_default;
500 extern const gs_vector3 BlackPoint_default;
501 extern const gs_cie_render_proc3 Encode_default;
502 extern const gs_cie_render_proc3 EncodeLMN_from_cache;
503 extern const gs_cie_render_proc3 EncodeABC_from_cache;
504 extern const gs_cie_transform_proc3 TransformPQR_default;
505 extern const gs_cie_transform_proc3 TransformPQR_from_cache;
506 extern const gs_cie_transform_proc TransformPQR_lookup_proc_name;
507 extern const gs_cie_render_table_procs RenderTableT_default;
508 extern const gs_cie_render_table_procs RenderTableT_from_cache;
509 
510 /* ------ Rendering dictionaries ------ */
511 
512 struct gs_cie_wbsd_s {
513     struct {
514 	gs_vector3 xyz, pqr;
515     } ws, bs, wd, bd;
516 };
517 typedef struct gs_cie_render_table_s {
518     /*
519      * If lookup.table == 0, the other members (of both lookup and T) are
520      * not set.  If not 0, lookup.table points to an array of
521      * st_const_string_elements.
522      */
523     gx_color_lookup_table lookup;
524     gs_cie_render_table_procs T;
525 } gs_cie_render_table_t;
526 typedef enum {
527     CIE_RENDER_STATUS_BUILT,
528     CIE_RENDER_STATUS_INITED,
529     CIE_RENDER_STATUS_SAMPLED,
530     CIE_RENDER_STATUS_COMPLETED
531 } cie_render_status_t;
532 
533 typedef struct gx_cie_float_fixed_cache_s {
534     cie_cache_floats floats;
535     union if_ {
536 	cie_cache_fracs fracs;
537 	cie_cache_ints ints;
538     } fixeds;
539 } gx_cie_float_fixed_cache;
540 
541 /* The main dictionary */
542 struct gs_cie_render_s {
543     cie_render_status_t status;
544     rc_header rc;
545     gs_id id;
546     void *client_data;
547     gs_cie_wb points;
548     gs_matrix3 MatrixPQR;
549     gs_range3 RangePQR;
550     gs_cie_transform_proc3 TransformPQR;
551     gs_matrix3 MatrixLMN;
552     gs_cie_render_proc3 EncodeLMN;
553     gs_range3 RangeLMN;
554     gs_matrix3 MatrixABC;
555     gs_cie_render_proc3 EncodeABC;
556     gs_range3 RangeABC;
557     gs_cie_render_table_t RenderTable;
558     /* Following are computed when structure is initialized. */
559     gs_range3 DomainLMN;
560     gs_range3 DomainABC;
561     gs_matrix3 MatrixABCEncode;
562     cie_cached_value EncodeABC_base[3];
563     gs_matrix3 MatrixPQR_inverse_LMN;
564     gs_vector3 wdpqr, bdpqr;
565     struct {
566 	gx_cie_vector_cache3_t EncodeLMN;	/* mult. by M'ABCEncode */
567 	gx_cie_float_fixed_cache EncodeABC[3];
568 	gx_cie_scalar_cache RenderTableT[4];
569 	bool RenderTableT_is_identity;
570     } caches;
571 };
572 
573 /* The CRD type is public only for a type test in zcrd.c. */
574 extern_st(st_cie_render1);
575 #define public_st_cie_render1()	/* in gscrd.c */\
576   gs_public_st_composite(st_cie_render1, gs_cie_render, "gs_cie_render",\
577 			 cie_render1_enum_ptrs, cie_render1_reloc_ptrs)
578 
579 /* ------ Joint caches ------ */
580 
581 /* This cache depends on both the color space and the rendering */
582 /* dictionary -- see above. */
583 typedef enum {
584     CIE_JC_STATUS_BUILT,
585     CIE_JC_STATUS_INITED,
586     CIE_JC_STATUS_COMPLETED
587 } cie_joint_caches_status_t;
588 
589 /*
590  * Define the procedure type for finishing CIE color mapping.  This is
591  * replaced by a special procedure to support CIE->XYZ mapping.
592  * It returns the number of components of the concrete color space
593  * (3 if RGB, 4 if CMYK).
594  */
595 #define GX_CIE_REMAP_FINISH_PROC(proc)\
596   int proc(cie_cached_vector3 vec3, frac *pconc,\
597 	   const gs_imager_state *pis, const gs_color_space *pcs)
598 
599 typedef struct gx_cie_joint_caches_s {
600     /*
601      * The first 4 members are the "key" in the cache.  They behave as
602      * follows:
603      *
604      *    If id_status = COMPLETED, the cache is valid with respect to the
605      *    color space and CRD identified by cspace_id and render_id.
606      *
607      *    If status = COMPLETED, then id_status = COMPLETED also, and for
608      *    every gstate pgs that references this cache, pgs->color_space->id =
609      *    cspace_id and pgs->cie_render->id = render_id; hence the cache is
610      *    valid with respect to that gstate.
611      *
612      * This invariant is maintained because the PostScript CRD-setting
613      * operators, the library's CRD-setting procedure, and the library's
614      * procedures for setting CIE color spaces all unshare the joint caches
615      * and set status in the new copy to something other than COMPLETED.
616      *
617      * The only reason for id_status is that certain client code often
618      * resets the CRD and/or color space and then sets it back to its
619      * original value, and we want to detect that and not invalidate the
620      * caches.  If it weren't for that, setcolorspace and setcolorrendering
621      * could simply invalidate the caches.
622      */
623 
624     gs_id cspace_id;
625     gs_id render_id;
626     cie_joint_caches_status_t id_status;
627     cie_joint_caches_status_t status;
628     rc_header rc;
629     GX_CIE_REMAP_FINISH_PROC((*remap_finish));
630     bool skipDecodeABC;
631     bool skipDecodeLMN;
632     gx_cie_vector_cache3_t DecodeLMN;	/* mult. by dLMN_PQR */
633     gs_cie_wbsd points_sd;
634     bool skipPQR;
635     gx_cie_vector_cache3_t TransformPQR;	/* mult. by PQR_inverse_LMN */
636     bool skipEncodeLMN;
637 } gx_cie_joint_caches;
638 
639 #define private_st_joint_caches() /* in gscie.c */\
640   gs_private_st_simple(st_joint_caches, gx_cie_joint_caches,\
641     "gx_cie_joint_caches")
642 
643 /* ------ Internal procedures ------ */
644 
645 /*
646  * Rather than using the usual PostScript for-loop paradigm, we enumerate
647  * cache key values using the exact computation
648  *	v(i) = ((N - i) * A + i * B) / N
649  * where A and B are the range of the cache and N is the number of entries
650  * (currently always gx_cie_cache_size - 1).
651  * The boilerplate is:
652  *	gs_sample_loop_params_t lp;
653  *	int i;
654  *	gs_cie_cache_init(... &lp ...);
655  *	for (i = 0; i <= lp.N; ++i) {
656  *	    float v = SAMPLE_LOOP_VALUE(i, lp);
657  *	    ...
658  *	}
659  * NOTE: This computation must match zfor_samples and for_samples_continue
660  * in zcontrol.c.
661  */
662 typedef struct gs_sample_loop_params_s {
663     float A, B;
664     int N;
665 } gs_sample_loop_params_t;
666 #define SAMPLE_LOOP_VALUE(i, lp)\
667   ( (((lp).N - (i)) * (lp).A + (i) * (lp).B) / (lp).N )
668 void gs_cie_cache_init(cie_cache_params *, gs_sample_loop_params_t *,
669 		       const gs_range *, client_name_t);
670 
671 void gs_cie_cache_to_fracs(const cie_cache_floats *, cie_cache_fracs *);
672 void gs_cie_defg_complete(gs_cie_defg *);
673 void gs_cie_def_complete(gs_cie_def *);
674 void gs_cie_abc_complete(gs_cie_abc *);
675 void gs_cie_a_complete(gs_cie_a *);
676 gx_cie_joint_caches *gx_currentciecaches(gs_state *);
677 const gs_cie_common *gs_cie_cs_common(const gs_state *);
678 int gs_cie_cs_complete(gs_state *, bool);
679 int gs_cie_jc_complete(const gs_imager_state *, const gs_color_space *pcs);
680 float gs_cie_cached_value(floatp, const cie_cache_floats *);
681 
682 #define CIE_CLAMP_INDEX(index)\
683   index = (index < 0 ? 0 :\
684 	   index >= gx_cie_cache_size ? gx_cie_cache_size - 1 : index)
685 
686 /*
687  * Compute the source and destination WhitePoint and BlackPoint for
688  * the TransformPQR procedure.
689  */
690 int gs_cie_compute_points_sd(gx_cie_joint_caches *pjc,
691 			     const gs_cie_common * pcie,
692 			     const gs_cie_render * pcrd);
693 
694 /*
695  * Compute the derived values in a CRD that don't involve the cached
696  * procedure values, moving the CRD from "built" to "inited" status.
697  * If the CRD is already in "inited" or a later status, do nothing.
698  */
699 int gs_cie_render_init(gs_cie_render *);
700 
701 /*
702  * Sample the EncodeLMN, EncodeABC, and RenderTableT CRD procedures, and
703  * load the caches, moving the CRD from "inited" to "sampled" status.
704  * If the CRD is already in "sampled" or a later status, do nothing;
705  * otherwise, if the CRD is not in "inited" status, return an error.
706  */
707 int gs_cie_render_sample(gs_cie_render *);
708 
709 /*
710  * Finish preparing a CRD for installation, by restricting and/or
711  * transforming the cached procedure values, moving the CRD from "sampled"
712  * to "completed" status.  If the CRD is already in "completed" status, do
713  * nothing; otherwise, if the CRD is not in "sampled" status, return an
714  * error.
715  */
716 int gs_cie_render_complete(gs_cie_render *);
717 
718 /* ---------------- Procedures ---------------- */
719 
720 /* ------ Constructors ------ */
721 
722 /*
723  * Note that these procedures take a client_data pointer as an operand. The
724  * client is responsible for allocating and deleting this object; the
725  * color space machinery does not take ownership of it.
726  *
727  * Note that these procedures set the reference count of the (large)
728  * parameter structures to 1, not 0.  gs_setcolorspace will increment
729  * the reference count again, so unless you want the parameter structures
730  * to stay allocated permanently (or until a garbage collection),
731  * you should call cs_adjust_count(pcspace, -1).  THIS IS A BUG IN THE API.
732  */
733 extern int
734     gs_cspace_build_CIEA(gs_color_space ** ppcspace, void *client_data,
735 			 gs_memory_t * pmem),
736     gs_cspace_build_CIEABC(gs_color_space ** ppcspace, void *client_data,
737 			   gs_memory_t * pmem),
738     gs_cspace_build_CIEDEF(gs_color_space ** ppcspace, void *client_data,
739 			   gs_memory_t * pmem),
740     gs_cspace_build_CIEDEFG(gs_color_space ** ppcspace, void *client_data,
741 			    gs_memory_t * pmem);
742 
743 /* ------ Accessors ------ */
744 
745 /*
746  * Note that the accessors depend heavily on "puns" between the variants
747  * of pcspace->params.{a,abc,def,defg}.
748  */
749 
750 /* Generic CIE based color space parameters */
751 #define gs_cie_RangeLMN(pcspace)  (&(pcspace)->params.a->common.RangeLMN)
752 #define gs_cie_DecodeLMN(pcspace) (&(pcspace)->params.a->common.DecodeLMN)
753 #define gs_cie_MatrixLMN(pcspace) (&(pcspace)->params.a->common.MatrixLMN)
754 #define gs_cie_WhitePoint(pcspace)\
755   ((pcspace)->params.a->common.points.WhitePoint)
756 #define gs_cie_BlackPoint(pcspace)\
757   ((pcspace)->params.a->common.points.BlackPoint)
758 
759 /* CIEBasedA color space */
760 #define gs_cie_a_RangeA(pcspace)      (&(pcspace)->params.a->RangeA)
761 #define gs_cie_a_DecodeA(pcspace)     (&(pcspace)->params.a->DecodeA)
762 #define gs_cie_a_MatrixA(pcspace)     (&(pcspace)->params.a->MatrixA)
763 #define gs_cie_a_RangeA(pcspace)      (&(pcspace)->params.a->RangeA)
764 
765 /* CIEBasedABC color space */
766 /* Note that these also work for CIEBasedDEF[G] spaces. */
767 #define gs_cie_abc_RangeABC(pcspace)    (&(pcspace)->params.abc->RangeABC)
768 #define gs_cie_abc_DecodeABC(pcspace)   (&(pcspace)->params.abc->DecodeABC)
769 #define gs_cie_abc_MatrixABC(pcspace)   (&(pcspace)->params.abc->MatrixABC)
770 
771 /* CIDBasedDEF color space */
772 #define gs_cie_def_RangeDEF(pcspace)    (&(pcspace)->params.def->RangeDEF)
773 #define gs_cie_def_DecodeDEF(pcspace)   (&(pcspace)->params.def->DecodeDEF)
774 #define gs_cie_def_RangeHIJ(pcspace)    (&(pcspace)->params.def->RangeHIJ)
775 
776 /* CIDBasedDEFG color space */
777 #define gs_cie_defg_RangeDEFG(pcspace)  (&(pcspace)->params.defg->RangeDEFG)
778 #define gs_cie_defg_DecodeDEFG(pcspace) (&(pcspace)->params.defg->DecodeDEFG)
779 #define gs_cie_defg_RangeHIJK(pcspace)  (&(pcspace)->params.defg->RangeHIJK)
780 
781 /*
782  * The following routine is provided so as to avoid explicitly exporting the
783  * CIEBasedDEF[G] color lookup table structure. It is doubtful any
784  * high-level clients will ever need to get this information.
785  *
786  * The caller must make sure the number of dimensions and strings provided
787  * are the number expected given the number of components in the color space.
788  * The procedure gs_color_space_num_components is available for this purpose.
789  *
790  * For a 3 component color space (CIEBasedDEF), ptable points to an array of
791  * pdims[0] gs_const_string structures, each of which is of length
792  * 3 * pdims[1] * pdims[2].
793  *
794  * For a 4 component color space (CIEBasedDEFG), ptable points to an array of
795  * pdims[0] * pdims[1] strings, each of which is of length
796  * 3 * pdims[2] * pdims[3].
797  *
798  * NB: the caller is responsible for deallocating the color table data
799  *     when no longer needed.  */
800 extern int
801     gs_cie_defx_set_lookup_table(gs_color_space * pcspace, int *pdims,
802 				 const gs_const_string * ptable);
803 
804 /* Serialize common CIE elements. */
805 int gx_serialize_cie_common_elements(const gs_color_space * pcs, stream * s);
806 
807 #endif /* gscie_INCLUDED */
808