1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 /* $Id: gdevdcrd.c 8250 2007-09-25 13:31:24Z giles $ */
14 /* Create a sample device CRD */
15 #include "math_.h"
16 #include "memory_.h"
17 #include "string_.h"
18 #include "gx.h"
19 #include "gserrors.h"
20 #include "gsparam.h"
21 #include "gscspace.h"		/* for gscie.h */
22 #include "gscrd.h"
23 #include "gscrdp.h"
24 #include "gxdevcli.h"
25 #include "gdevdcrd.h"
26 
27 /*
28  * The parameters in this driver CRD are the default PostScript values,
29  * except for the optional 'dented' procedures.
30  */
31 #define DENT(v, f)\
32   (v <= 0.5 ? v * f : (v - 0.5) * (1 - (0.5 * f)) / 0.5 + 0.5 * f)
33 static const gs_vector3 bit_WhitePoint = {(float)0.9505, 1, (float)1.0890};
34 static const gs_range3 bit_RangePQR = {
35     {{0, (float)0.9505}, {0, 1}, {0, (float)1.0890}}
36 };
37 static const float dent_PQR = 1.0;
38 static int
bit_TransformPQR_proc(int index,floatp in,const gs_cie_wbsd * pwbsd,gs_cie_render * pcrd,float * out)39 bit_TransformPQR_proc(int index, floatp in, const gs_cie_wbsd * pwbsd,
40 		      gs_cie_render * pcrd, float *out)
41 {
42     *out = DENT(in, dent_PQR);
43     return 0;
44 }
45 static const gs_cie_transform_proc3 bit_TransformPQR = {
46     bit_TransformPQR_proc, "bitTPQRDefault", {0, 0}, 0
47 };
48 static const float dent_LMN = 1.0;
49 static float
bit_EncodeLMN_proc(floatp in,const gs_cie_render * pcrd)50 bit_EncodeLMN_proc(floatp in, const gs_cie_render * pcrd)
51 {
52     return DENT(in, dent_LMN);
53 }
54 static const gs_cie_render_proc3 bit_EncodeLMN = { /* dummy */
55     {bit_EncodeLMN_proc, bit_EncodeLMN_proc, bit_EncodeLMN_proc}
56 };
57 static const gs_range3 bit_RangeLMN = {
58     {{0, (float)0.9505}, {0, 1}, {0, (float)1.0890}}
59 };
60 static const gs_matrix3 bit_MatrixABC = {
61     {(float) 3.24063, (float)-0.96893, (float) 0.05571},
62     {(float)-1.53721, (float) 1.87576, (float)-0.20402},
63     {(float)-0.49863, (float) 0.04152, (float) 1.05700}
64 };
65 static float
bit_EncodeABC_proc(floatp in,const gs_cie_render * pcrd)66 bit_EncodeABC_proc(floatp in, const gs_cie_render * pcrd)
67 {
68     return pow(max(in, 0.0), 0.45);
69 }
70 static const gs_cie_render_proc3 bit_EncodeABC = {
71     {bit_EncodeABC_proc, bit_EncodeABC_proc, bit_EncodeABC_proc}
72 };
73 /* These RenderTables are no-ops. */
74 static const byte bit_rtt0[2*2*3] = {
75     /*0,0,0*/ 0,0,0,
76     /*0,0,1*/ 0,0,255,
77     /*0,1,0*/ 0,255,0,
78     /*0,1,1*/ 0,255,255
79 };
80 static const byte bit_rtt1[2*2*3] = {
81     /*1,0,0*/ 255,0,0,
82     /*1,0,1*/ 255,0,255,
83     /*1,1,0*/ 255,255,0,
84     /*1,1,1*/ 255,255,255
85 };
86 static const gs_const_string bit_rt_data[2] = {
87     {bit_rtt0, 2*2*3}, {bit_rtt1, 2*2*3}
88 };
89 static frac
bit_rt_proc(byte in,const gs_cie_render * pcrd)90 bit_rt_proc(byte in, const gs_cie_render *pcrd)
91 {
92     return frac_1 * in / 255;
93 }
94 static const gs_cie_render_table_t bit_RenderTable = {	/* dummy */
95     {3, {2, 2, 2}, 3, bit_rt_data},
96     {{bit_rt_proc, bit_rt_proc, bit_rt_proc}}
97 };
98 
99 /*
100  * Implement get_params for a sample device CRD.  A useful convention,
101  * for devices that can provide more than one CRD, is to have a settable
102  * parameter CRDName, which gives the name of the CRD in use.  This sample
103  * code provides a constant CRDName: making it settable is left as an
104  * exercise to the reader.
105  */
106 int
sample_device_crd_get_params(gx_device * pdev,gs_param_list * plist,const char * crd_param_name)107 sample_device_crd_get_params(gx_device *pdev, gs_param_list *plist,
108 			     const char *crd_param_name)
109 {
110     int ecode = 0;
111 
112     if (param_requested(plist, "CRDName") > 0) {
113 	gs_param_string cns;
114 	int code;
115 
116 	cns.data = (const byte *)crd_param_name;
117 	cns.size = strlen(crd_param_name);
118 	cns.persistent = true;
119 	code = param_write_string(plist, "CRDName", &cns);
120 	if (code < 0)
121 	    ecode = code;
122     }
123     if (param_requested(plist, crd_param_name) > 0) {
124 	gs_cie_render *pcrd;
125 	int code = gs_cie_render1_build(&pcrd, pdev->memory,
126 					"sample_device_crd_get_params");
127 	if (code >= 0) {
128 	    gs_cie_transform_proc3 tpqr;
129 
130 	    tpqr = bit_TransformPQR;
131 	    tpqr.driver_name = pdev->dname;
132 	    code = gs_cie_render1_initialize(pdev->memory, pcrd, NULL,
133 			&bit_WhitePoint, NULL /*BlackPoint*/,
134 			NULL /*MatrixPQR*/, &bit_RangePQR, &tpqr,
135 			NULL /*MatrixLMN*/, &bit_EncodeLMN, &bit_RangeLMN,
136 			&bit_MatrixABC, &bit_EncodeABC, NULL /*RangeABC*/,
137 			&bit_RenderTable);
138 	    if (code >= 0) {
139 		code = param_write_cie_render1(plist, crd_param_name, pcrd,
140 					       pdev->memory);
141 	    }
142 	    rc_decrement(pcrd, "sample_device_crd_get_params"); /* release */
143 	}
144 	if (code < 0)
145 	    ecode = code;
146     }
147     if (param_requested(plist, bit_TransformPQR.proc_name) > 0) {
148 	/*
149 	 * We definitely do not recommend the following use of a static
150 	 * to hold the address: this is a shortcut.
151 	 */
152 	gs_cie_transform_proc my_proc = bit_TransformPQR_proc;
153 	byte *my_addr = gs_alloc_string(pdev->memory, sizeof(my_proc),
154 					"sd_crd_get_params(proc)");
155 	int code;
156 
157 	if (my_addr == 0)
158 	    code = gs_note_error(gs_error_VMerror);
159 	else {
160 	    gs_param_string as;
161 
162 	    memcpy(my_addr, &my_proc, sizeof(my_proc));
163 	    as.data = my_addr;
164 	    as.size = sizeof(my_proc);
165 	    as.persistent = true;
166 	    code = param_write_string(plist, bit_TransformPQR.proc_name, &as);
167 	}
168 	if (code < 0)
169 	    ecode = code;
170     }
171     return ecode;
172 }
173