/* Copyright (C) 1992, 1995, 1997, 1998, 1999 artofcode LLC. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA, 02111-1307. */ /*$Id: gscie.h,v 1.3.2.1.2.1 2003/01/17 00:49:02 giles Exp $ */ /* Structures for CIE color algorithms */ /* (requires gscspace.h, gscolor2.h) */ #ifndef gscie_INCLUDED # define gscie_INCLUDED #include "gconfigv.h" /* for USE_FPU */ #include "gsrefct.h" #include "gsstype.h" /* for extern_st */ #include "gxctable.h" /* ---------------- Configuration parameters ---------------- */ /* Define the size of the Encode/Decode/Transform procedure value caches. */ /* With the current design, these caches must all have the same size. */ #ifndef CIE_LOG2_CACHE_SIZE # define CIE_LOG2_CACHE_SIZE 9 #endif /* Define whether to use fixed- or floating-point values in the caches. */ /*#define CIE_CACHE_USE_FIXED */ #if USE_FPU < 0 # define CIE_CACHE_USE_FIXED #endif /* If we are using fixed-point values, define the number of fraction bits. */ #define CIE_FIXED_FRACTION_BITS 12 /* Define whether to interpolate between cached values. */ #define CIE_CACHE_INTERPOLATE /* Define whether to interpolate at all intermediate lookup steps. */ /* This is computationally expensive and doesn't seem to improve */ /* the accuracy of the result. */ /*#define CIE_INTERPOLATE_INTERMEDIATE */ /* Define whether to interpolate in the RenderTable. */ /* This is computationally very expensive, so it is normally disabled. */ #define CIE_RENDER_TABLE_INTERPOLATE /* ------ Derived values ------ */ /* from CIE_LOG2_CACHE_SIZE */ #define gx_cie_log2_cache_size CIE_LOG2_CACHE_SIZE #define gx_cie_cache_size (1 << gx_cie_log2_cache_size) /* From CIE_FIXED_FRACTION_BITS 12 */ #ifndef CIE_FIXED_FRACTION_BITS /* Take as many bits as we can without having to multiply in two pieces. */ # define CIE_FIXED_FRACTION_BITS\ ((arch_sizeof_long * 8 - gx_cie_log2_cache_size) / 2 - 1) #endif /* From CIE_RENDER_TABLE_INTERPOLATE */ #ifdef CIE_RENDER_TABLE_INTERPOLATE # define CIE_CACHE_INTERPOLATE #endif #define float_lshift(v, nb) ((v) * (1L << (nb))) #define float_rshift(v, nb) ((v) * (1.0 / (1L << (nb)))) #ifdef CIE_CACHE_INTERPOLATE /* We have to have room for both a cache index and the interpolation bits */ /* in a positive int (i.e., leaving 1 bit for the sign), plus a little slop. */ /* The values for interpolation are cie_cached_values by default. */ # define _cie_interpolate_bits\ min(arch_sizeof_int * 8 - gx_cie_log2_cache_size - 2, 10) # define _cix(i) ((i) >> _cie_interpolate_bits) # define _cif(i) ((int)(i) & ((1 << _cie_interpolate_bits) - 1)) # define cie_interpolate_between(v0, v1, i)\ ((v0) + cie_cached_rshift(((v1) - (v0)) * _cif(i) +\ (1 << (_cie_interpolate_bits - 1)),\ _cie_interpolate_bits)) # define cie_interpolate(p, i)\ cie_interpolate_between((p)[_cix(i)], (p)[_cix(i) + 1], i) # define cie_interpolate_fracs(p, i)\ ((p)[_cix(i)] +\ (frac)arith_rshift((long)((p)[_cix(i) + 1] - (p)[_cix(i)]) * _cif(i), _cie_interpolate_bits)) #else # define _cie_interpolate_bits 0 # define cie_interpolate_between(v0, v1, i) (v0) # define cie_interpolate(p, i) ((p)[i]) # define cie_interpolate_fracs(p, i) ((p)[i]) #endif #ifdef CIE_CACHE_USE_FIXED typedef long cie_cached_value; # define _cie_fixed_shift CIE_FIXED_FRACTION_BITS # define float2cie_cached(v)\ ((cie_cached_value)float_lshift(v, _cie_fixed_shift)) # define cie_cached2float(v)\ float_rshift(v, _cie_fixed_shift) # define cie_cached2int(v, fbits)\ arith_rshift(v, _cie_fixed_shift - (fbits)) /* We are multiplying two cie_cached_values to produce a result that */ /* lies between 0 and gx_cie_cache_size - 1. If the intermediate result */ /* might overflow, compute it in pieces (being a little sloppy). */ # define _cie_product_excess_bits\ (_cie_fixed_shift * 2 + gx_cie_log2_cache_size - (arch_sizeof_long * 8 - 1)) # define cie_cached_product2int(v, factor, fbits)\ (_cie_product_excess_bits > 0 ?\ arith_rshift( (v) * arith_rshift(factor, _cie_product_excess_bits) +\ arith_rshift(v, _cie_product_excess_bits) *\ ((factor) & ((1 << _cie_product_excess_bits) - 1)),\ _cie_fixed_shift * 2 - _cie_product_excess_bits - (fbits)) :\ arith_rshift((v) * (factor), _cie_fixed_shift * 2 - (fbits))) # define cie_cached_rshift(v, n) arith_rshift(v, n) #else typedef float cie_cached_value; # define float2cie_cached(v) (v) # define cie_cached2float(v) (v) # define cie_cached2int(v, fbits)\ ((int)float_lshift(v, fbits)) # define cie_cached_product2int(v, factor, fbits)\ ((int)float_lshift((v) * (factor), fbits)) # define cie_cached_rshift(v, n) float_rshift(v, n) #endif /* ---------------- Structures ---------------- */ #ifndef gs_cie_render_DEFINED # define gs_cie_render_DEFINED typedef struct gs_cie_render_s gs_cie_render; #endif /* ------ Common definitions ------ */ /* * For the purposes of the CIE routines, we consider that all the vectors * are column vectors, that the matrices are specified in column order * (e.g., the matrix * [ A B C ] * [ D E F ] * [ G H I ] * is represented as [A D G B E H C F I]), and that to transform a vector * V by a matrix M, we compute M * V to produce another column vector. * Note in particular that in order to produce a matrix M that is * equivalent to transforming by M1 and then by M2, we must compute * M = M2 * M1. */ /* A 3-element vector. */ typedef struct gs_vector3_s { float u, v, w; } gs_vector3; /* A 3x3 matrix, stored in column order. */ typedef struct gs_matrix3_s { gs_vector3 cu, cv, cw; bool is_identity; } gs_matrix3; /* 3- and 4-element vectors of ranges. */ typedef struct gs_range_s { float rmin, rmax; } gs_range; typedef struct gs_range3_s { gs_range ranges[3]; } gs_range3; typedef struct gs_range4_s { gs_range ranges[4]; } gs_range4; /* Client-supplied transformation procedures. */ typedef struct gs_cie_common_s gs_cie_common; typedef struct gs_cie_wbsd_s gs_cie_wbsd; typedef float (*gs_cie_a_proc) (P2(floatp, const gs_cie_a *)); typedef float (*gs_cie_abc_proc) (P2(floatp, const gs_cie_abc *)); typedef struct gs_cie_abc_proc3_s { gs_cie_abc_proc procs[3]; } gs_cie_abc_proc3; typedef float (*gs_cie_def_proc) (P2(floatp, const gs_cie_def *)); typedef struct gs_cie_def_proc3_s { gs_cie_def_proc procs[3]; } gs_cie_def_proc3; typedef float (*gs_cie_defg_proc) (P2(floatp, const gs_cie_defg *)); typedef struct gs_cie_defg_proc4_s { gs_cie_defg_proc procs[4]; } gs_cie_defg_proc4; typedef float (*gs_cie_common_proc) (P2(floatp, const gs_cie_common *)); typedef struct gs_cie_common_proc3_s { gs_cie_common_proc procs[3]; } gs_cie_common_proc3; typedef float (*gs_cie_render_proc) (P2(floatp, const gs_cie_render *)); typedef struct gs_cie_render_proc3_s { gs_cie_render_proc procs[3]; } gs_cie_render_proc3; /* * The TransformPQR procedure depends on both the color space and the * CRD, so we can't simply pass it through the band list as a table of * sampled values, even though such a table exists as part of an * internal cache. Instead, we use two different approaches. The * graphics library knows that the cache must be reloaded whenever the * color space or CRD changes, so we can simply transmit the cached * values through the band list whenever this occurs. However, this * still leaves the issue of how to represent the procedure in the CRD * per se: such a representation is required in order for * currentcolorrendering and setcolorrendering to work. For this * purpose, we provide a procedure name and procedure data, which * drivers can supply with their default CRDs; the driver must also be * prepared to map the procedure name back to an actual set of * procedures. * * To simplify the driver-provided CRD machinery, we define TransformPQR as * a single procedure taking an integer that specifies the component number, * rather than an array of procedures. Note that if proc_name != 0, * proc is irrelevant -- the driver will provide it by looking up proc_name. * For this reason, the last argument of TransformPQR must be writable. * Note also that since TransformPQR can fail (if the driver doesn't * recognize the proc_name), it must return a failure code. */ typedef int (*gs_cie_transform_proc)(P5(int, floatp, const gs_cie_wbsd *, gs_cie_render *, float *)); typedef struct gs_cie_transform_proc3_s { gs_cie_transform_proc proc; const char *proc_name; gs_const_string proc_data; const char *driver_name; /* for mapping proc_name back to procs */ } gs_cie_transform_proc3; typedef frac(*gs_cie_render_table_proc) (P2(byte, const gs_cie_render *)); typedef struct gs_cie_render_table_procs_s { gs_cie_render_table_proc procs[4]; } gs_cie_render_table_procs; /* CIE white and black points. */ typedef struct gs_cie_wb_s { gs_vector3 WhitePoint; gs_vector3 BlackPoint; } gs_cie_wb; /* ------ Caches ------ */ /* * Given that all the client-supplied procedures involved in CIE color * mapping and rendering are monotonic, and given that we can determine * the minimum and maximum input values for them, we can cache their values. * This takes quite a lot of space, but eliminates the need for callbacks * deep in the graphics code (particularly the image operator). * * The procedures, and how we determine their domains, are as follows: Stage Name Domain determination ----- ---- -------------------- pre-decode DecodeDEF RangeDEF pre-decode DecodeDEFG RangeDEFG color space DecodeA RangeA color space DecodeABC RangeABC color space DecodeLMN RangeLMN rendering TransformPQR RangePQR (but depends on color space White/BlackPoints) rendering EncodeLMN RangePQR transformed by the inverse of MatrixPQR and then by MatrixLMN rendering EncodeABC RangeLMN transformed by MatrixABC rendering RenderTable.T [0..1]*m * Note that we can mostly cache the results of the color space procedures * without knowing the color rendering parameters, and vice versa, * because of the range parameters supplied in the dictionaries. * Unfortunately, TransformPQR is an exception. */ /* * The index into a cache is (value - base) * factor, where * factor is computed as (cie_cache_size - 1) / (rmax - rmin). */ /* * We have two kinds of caches: ordinary caches, where each value is * a scalar, and vector caches, where each value is a gs_cached_vector3. * The latter allow us to pre-multiply the values by one column of * a gs_matrix3, avoiding multiplications at lookup time. * * If the function being cached is simply a linear transformation, * f(x) = scale * x + origin, then we can fold it into a following or * preceding matrix. */ typedef struct cie_linear_params_s { bool is_linear; float scale, origin; } cie_linear_params_t; typedef struct cie_cache_params_s { bool is_identity; /* must come first */ float base, factor; cie_linear_params_t linear; /* only used in vector_cache.floats? */ } cie_cache_params; typedef struct cie_cache_floats_s { cie_cache_params params; float values[gx_cie_cache_size]; } cie_cache_floats; typedef struct cie_cache_fracs_s { cie_cache_params params; frac values[gx_cie_cache_size]; } cie_cache_fracs; typedef struct cie_cache_ints_s { cie_cache_params params; int values[gx_cie_cache_size]; } cie_cache_ints; typedef union gx_cie_scalar_cache_s { cie_cache_floats floats; cie_cache_fracs fracs; cie_cache_ints ints; } gx_cie_scalar_cache; typedef struct cie_cached_vector3_s { cie_cached_value u, v, w; } cie_cached_vector3; typedef struct cie_vector_cache_params_s { cie_cached_value base, factor, limit; } cie_vector_cache_params; typedef struct cie_cache_vectors_s { cie_vector_cache_params params; cie_cached_vector3 values[gx_cie_cache_size]; } cie_cache_vectors; typedef struct gx_cie_vector_cache_s { cie_cache_floats floats; cie_cache_vectors vecs; } gx_cie_vector_cache; /* ------ Color space dictionaries ------ */ /* Elements common to all CIE color space dictionaries. */ struct gs_cie_common_s { int (*install_cspace)(P2(const gs_color_space *, gs_state *)); void *client_data; gs_range3 RangeLMN; gs_cie_common_proc3 DecodeLMN; gs_matrix3 MatrixLMN; gs_cie_wb points; /* Following are computed when structure is initialized. */ struct { gx_cie_scalar_cache DecodeLMN[3]; } caches; }; /* st_cie_common and st_cie_common_elements_t are exported for gsicc.c */ #define public_st_cie_common() /* in gscscie.c */\ gs_public_st_ptrs1(st_cie_common, gs_cie_common, "gs_cie_common",\ cie_common_enum_ptrs, cie_common_reloc_ptrs, client_data) /* extern_st(st_cie_common); */ /* in gxcie.h */ #define gs_cie_common_elements\ gs_cie_common common; /* must be first */\ rc_header rc typedef struct gs_cie_common_elements_s { gs_cie_common_elements; } gs_cie_common_elements_t; #define public_st_cie_common_elements() /* in gscscie.c */ \ gs_public_st_suffix_add0_local( st_cie_common_elements_t,\ gs_cie_common_elements_t,\ "gs_cie_common_elements_t",\ cie_common_enum_ptrs,\ cie_common_reloc_ptrs,\ st_cie_common) /* extern_st(st_cie_common_elements_t); */ /* in gxcie.h */ /* A CIEBasedA dictionary. */ struct gs_cie_a_s { gs_cie_common_elements; /* must be first */ gs_range RangeA; gs_cie_a_proc DecodeA; gs_vector3 MatrixA; /* Following are computed when structure is initialized. */ struct { gx_cie_vector_cache DecodeA; /* mult. by MatrixA */ } caches; }; #define private_st_cie_a() /* in gscscie.c */\ gs_private_st_suffix_add0_local(st_cie_a, gs_cie_a, "gs_cie_a",\ cie_common_enum_ptrs,\ cie_common_reloc_ptrs,\ st_cie_common_elements_t) /* Common elements for CIEBasedABC, DEF, and DEFG dictionaries. */ #define gs_cie_abc_elements\ gs_cie_common_elements; /* must be first */\ gs_range3 RangeABC;\ gs_cie_abc_proc3 DecodeABC;\ gs_matrix3 MatrixABC;\ /* Following are computed when structure is initialized. */\ struct {\ bool skipABC;\ gx_cie_vector_cache DecodeABC[3]; /* mult. by MatrixABC */\ } caches /* A CIEBasedABC dictionary. */ struct gs_cie_abc_s { gs_cie_abc_elements; }; #define private_st_cie_abc() /* in gscscie.c */\ gs_private_st_suffix_add0_local(st_cie_abc, gs_cie_abc, "gs_cie_abc",\ cie_common_enum_ptrs, cie_common_reloc_ptrs,\ st_cie_common_elements_t) /* A CIEBasedDEF dictionary. */ struct gs_cie_def_s { gs_cie_abc_elements; /* must be first */ gs_range3 RangeDEF; gs_cie_def_proc3 DecodeDEF; gs_range3 RangeHIJ; gx_color_lookup_table Table; /* [NH][NI * NJ * 3] */ struct { gx_cie_scalar_cache DecodeDEF[3]; } caches_def; }; #define private_st_cie_def() /* in gscscie.c */\ gs_private_st_suffix_add1(st_cie_def, gs_cie_def, "gs_cie_def",\ cie_def_enum_ptrs, cie_def_reloc_ptrs,\ st_cie_abc, Table.table) /* A CIEBasedDEFG dictionary. */ struct gs_cie_defg_s { gs_cie_abc_elements; gs_range4 RangeDEFG; gs_cie_defg_proc4 DecodeDEFG; gs_range4 RangeHIJK; gx_color_lookup_table Table; /* [NH * NI][NJ * NK * 3] */ struct { gx_cie_scalar_cache DecodeDEFG[4]; } caches_defg; }; #define private_st_cie_defg() /* in gscscie.c */\ gs_private_st_suffix_add1(st_cie_defg, gs_cie_defg, "gs_cie_defg",\ cie_defg_enum_ptrs, cie_defg_reloc_ptrs,\ st_cie_abc, Table.table) /* * Default values for components. Note that for some components, there are * two sets of default procedures: _default (identity procedures) and * _from_cache (procedures that just return the cached values). */ extern const gs_range3 Range3_default; extern const gs_range4 Range4_default; extern const gs_cie_defg_proc4 DecodeDEFG_default; extern const gs_cie_defg_proc4 DecodeDEFG_from_cache; extern const gs_cie_def_proc3 DecodeDEF_default; extern const gs_cie_def_proc3 DecodeDEF_from_cache; extern const gs_cie_abc_proc3 DecodeABC_default; extern const gs_cie_abc_proc3 DecodeABC_from_cache; extern const gs_cie_common_proc3 DecodeLMN_default; extern const gs_cie_common_proc3 DecodeLMN_from_cache; extern const gs_matrix3 Matrix3_default; extern const gs_range RangeA_default; extern const gs_cie_a_proc DecodeA_default; extern const gs_cie_a_proc DecodeA_from_cache; extern const gs_vector3 MatrixA_default; extern const gs_vector3 BlackPoint_default; extern const gs_cie_render_proc3 Encode_default; extern const gs_cie_render_proc3 EncodeLMN_from_cache; extern const gs_cie_render_proc3 EncodeABC_from_cache; extern const gs_cie_transform_proc3 TransformPQR_default; extern const gs_cie_transform_proc3 TransformPQR_from_cache; extern const gs_cie_transform_proc TransformPQR_lookup_proc_name; extern const gs_cie_render_table_procs RenderTableT_default; extern const gs_cie_render_table_procs RenderTableT_from_cache; /* ------ Rendering dictionaries ------ */ struct gs_cie_wbsd_s { struct { gs_vector3 xyz, pqr; } ws, bs, wd, bd; }; typedef struct gs_cie_render_table_s { /* * If lookup.table == 0, the other members (of both lookup and T) are * not set. If not 0, lookup.table points to an array of * st_const_string_elements. */ gx_color_lookup_table lookup; gs_cie_render_table_procs T; } gs_cie_render_table_t; typedef enum { CIE_RENDER_STATUS_BUILT, CIE_RENDER_STATUS_INITED, CIE_RENDER_STATUS_SAMPLED, CIE_RENDER_STATUS_COMPLETED } cie_render_status_t; typedef struct gx_cie_float_fixed_cache_s { cie_cache_floats floats; union if_ { cie_cache_fracs fracs; cie_cache_ints ints; } fixeds; } gx_cie_float_fixed_cache; /* The main dictionary */ struct gs_cie_render_s { cie_render_status_t status; rc_header rc; gs_id id; void *client_data; gs_cie_wb points; gs_matrix3 MatrixPQR; gs_range3 RangePQR; gs_cie_transform_proc3 TransformPQR; gs_matrix3 MatrixLMN; gs_cie_render_proc3 EncodeLMN; gs_range3 RangeLMN; gs_matrix3 MatrixABC; gs_cie_render_proc3 EncodeABC; gs_range3 RangeABC; gs_cie_render_table_t RenderTable; /* Following are computed when structure is initialized. */ gs_range3 DomainLMN; gs_range3 DomainABC; gs_matrix3 MatrixABCEncode; cie_cached_value EncodeABC_base[3]; gs_matrix3 MatrixPQR_inverse_LMN; gs_vector3 wdpqr, bdpqr; struct { gx_cie_vector_cache EncodeLMN[3]; /* mult. by M'ABCEncode */ gx_cie_float_fixed_cache EncodeABC[3]; gx_cie_scalar_cache RenderTableT[4]; bool RenderTableT_is_identity; } caches; }; /* The CRD type is public only for a type test in zcrd.c. */ extern_st(st_cie_render1); #define public_st_cie_render1() /* in gscrd.c */\ gs_public_st_composite(st_cie_render1, gs_cie_render, "gs_cie_render",\ cie_render1_enum_ptrs, cie_render1_reloc_ptrs) /* ------ Joint caches ------ */ /* This cache depends on both the color space and the rendering */ /* dictionary -- see above. */ typedef enum { CIE_JC_STATUS_BUILT, CIE_JC_STATUS_INITED, CIE_JC_STATUS_COMPLETED } cie_joint_caches_status_t; typedef struct gx_cie_joint_caches_s { /* * The first 4 members are the "key" in the cache. They behave as * follows: * * If id_status = COMPLETED, the cache is valid with respect to the * color space and CRD identified by cspace_id and render_id. * * If status = COMPLETED, then id_status = COMPLETED also, and for * every gstate pgs that references this cache, pgs->color_space->id = * cspace_id and pgs->cie_render->id = render_id; hence the cache is * valid with respect to that gstate. * * This invariant is maintained because the PostScript CRD-setting * operators, the library's CRD-setting procedure, and the library's * procedures for setting CIE color spaces all unshare the joint caches * and set status in the new copy to something other than COMPLETED. * * The only reason for id_status is that certain client code often * resets the CRD and/or color space and then sets it back to its * original value, and we want to detect that and not invalidate the * caches. If it weren't for that, setcolorspace and setcolorrendering * could simply invalidate the caches. */ gs_id cspace_id; gs_id render_id; cie_joint_caches_status_t id_status; cie_joint_caches_status_t status; rc_header rc; bool skipDecodeABC; bool skipDecodeLMN; gx_cie_vector_cache DecodeLMN[3]; /* mult. by dLMN_PQR */ gs_cie_wbsd points_sd; bool skipPQR; gx_cie_vector_cache TransformPQR[3]; /* mult. by PQR_inverse_LMN */ bool skipEncodeLMN; } gx_cie_joint_caches; #define private_st_joint_caches() /* in gscie.c */\ gs_private_st_simple(st_joint_caches, gx_cie_joint_caches,\ "gx_cie_joint_caches") /* ------ Internal procedures ------ */ typedef struct gs_for_loop_params_s { double init, step, limit; } gs_for_loop_params; void gs_cie_cache_init(P4(cie_cache_params *, gs_for_loop_params *, const gs_range *, client_name_t)); void gs_cie_cache_to_fracs(P2(const cie_cache_floats *, cie_cache_fracs *)); void gs_cie_defg_complete(P1(gs_cie_defg *)); void gs_cie_def_complete(P1(gs_cie_def *)); void gs_cie_abc_complete(P1(gs_cie_abc *)); void gs_cie_a_complete(P1(gs_cie_a *)); gx_cie_joint_caches *gx_currentciecaches(P1(gs_state *)); const gs_cie_common *gs_cie_cs_common(P1(const gs_state *)); int gs_cie_cs_complete(P2(gs_state *, bool)); int gs_cie_jc_complete(P2(const gs_imager_state *, const gs_color_space *pcs)); float gs_cie_cached_value(P2(floatp, const cie_cache_floats *)); #define CIE_CLAMP_INDEX(index)\ index = (index < 0 ? 0 :\ index >= gx_cie_cache_size ? gx_cie_cache_size - 1 : index) /* * Compute the source and destination WhitePoint and BlackPoint for * the TransformPQR procedure. */ int gs_cie_compute_points_sd(P3(gx_cie_joint_caches *pjc, const gs_cie_common * pcie, const gs_cie_render * pcrd)); /* * Compute the derived values in a CRD that don't involve the cached * procedure values, moving the CRD from "built" to "inited" status. * If the CRD is already in "inited" or a later status, do nothing. */ int gs_cie_render_init(P1(gs_cie_render *)); /* * Sample the EncodeLMN, EncodeABC, and RenderTableT CRD procedures, and * load the caches, moving the CRD from "inited" to "sampled" status. * If the CRD is already in "sampled" or a later status, do nothing; * otherwise, if the CRD is not in "inited" status, return an error. */ int gs_cie_render_sample(P1(gs_cie_render *)); /* * Finish preparing a CRD for installation, by restricting and/or * transforming the cached procedure values, moving the CRD from "sampled" * to "completed" status. If the CRD is already in "completed" status, do * nothing; otherwise, if the CRD is not in "sampled" status, return an * error. */ int gs_cie_render_complete(P1(gs_cie_render *)); /* ---------------- Procedures ---------------- */ /* ------ Constructors ------ */ /* * Note that these procedures take a client_data pointer as an operand. The * client is responsible for allocating and deleting this object; the * color space machinery does not take ownership of it. * * Note that these procedures set the reference count of the (large) * parameter structures to 1, not 0. gs_setcolorspace will increment * the reference count again, so unless you want the parameter structures * to stay allocated permanently (or until a garbage collection), * you should call cs_adjust_count(pcspace, -1). THIS IS A BUG IN THE API. */ extern int gs_cspace_build_CIEA(P3(gs_color_space ** ppcspace, void *client_data, gs_memory_t * pmem)), gs_cspace_build_CIEABC(P3(gs_color_space ** ppcspace, void *client_data, gs_memory_t * pmem)), gs_cspace_build_CIEDEF(P3(gs_color_space ** ppcspace, void *client_data, gs_memory_t * pmem)), gs_cspace_build_CIEDEFG(P3(gs_color_space ** ppcspace, void *client_data, gs_memory_t * pmem)); /* ------ Accessors ------ */ /* * Note that the accessors depend heavily on "puns" between the variants * of pcspace->params.{a,abc,def,defg}. */ /* Generic CIE based color space parameters */ #define gs_cie_RangeLMN(pcspace) (&(pcspace)->params.a->common.RangeLMN) #define gs_cie_DecodeLMN(pcspace) (&(pcspace)->params.a->common.DecodeLMN) #define gs_cie_MatrixLMN(pcspace) (&(pcspace)->params.a->common.MatrixLMN) #define gs_cie_WhitePoint(pcspace)\ ((pcspace)->params.a->common.points.WhitePoint) #define gs_cie_BlackPoint(pcspace)\ ((pcspace)->params.a->common.points.BlackPoint) /* CIEBasedA color space */ #define gs_cie_a_RangeA(pcspace) (&(pcspace)->params.a->RangeA) #define gs_cie_a_DecodeA(pcspace) (&(pcspace)->params.a->DecodeA) #define gs_cie_a_MatrixA(pcspace) (&(pcspace)->params.a->MatrixA) #define gs_cie_a_RangeA(pcspace) (&(pcspace)->params.a->RangeA) /* CIEBasedABC color space */ /* Note that these also work for CIEBasedDEF[G] spaces. */ #define gs_cie_abc_RangeABC(pcspace) (&(pcspace)->params.abc->RangeABC) #define gs_cie_abc_DecodeABC(pcspace) (&(pcspace)->params.abc->DecodeABC) #define gs_cie_abc_MatrixABC(pcspace) (&(pcspace)->params.abc->MatrixABC) /* CIDBasedDEF color space */ #define gs_cie_def_RangeDEF(pcspace) (&(pcspace)->params.def->RangeDEF) #define gs_cie_def_DecodeDEF(pcspace) (&(pcspace)->params.def->DecodeDEF) #define gs_cie_def_RangeHIJ(pcspace) (&(pcspace)->params.def->RangeHIJ) /* CIDBasedDEFG color space */ #define gs_cie_defg_RangeDEFG(pcspace) (&(pcspace)->params.defg->RangeDEFG) #define gs_cie_defg_DecodeDEFG(pcspace) (&(pcspace)->params.defg->DecodeDEFG) #define gs_cie_defg_RangeHIJK(pcspace) (&(pcspace)->params.defg->RangeHIJK) /* * The following routine is provided so as to avoid explicitly exporting the * CIEBasedDEF[G] color lookup table structure. It is doubtful any * high-level clients will ever need to get this information. * * The caller must make sure the number of dimensions and strings provided * are the number expected given the number of components in the color space. * The procedure gs_color_space_num_components is available for this purpose. * * For a 3 component color space (CIEBasedDEF), ptable points to an array of * pdims[0] gs_const_string structures, each of which is of length * 3 * pdims[1] * pdims[2]. * * For a 4 component color space (CIEBasedDEFG), ptable points to an array of * pdims[0] * pdims[1] strings, each of which is of length * 3 * pdims[2] * pdims[3]. * * NB: the caller is responsible for deallocating the color table data * when no longer needed. */ extern int gs_cie_defx_set_lookup_table(P3(gs_color_space * pcspace, int *pdims, const gs_const_string * ptable)); #endif /* gscie_INCLUDED */