summaryrefslogtreecommitdiff
path: root/pcl/pccrd.c
blob: 019cb160d347a302be37ccb99af3708da2fa2324 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/* Portions Copyright (C) 2001 artofcode LLC.
   Portions Copyright (C) 1996, 2001 Artifex Software Inc.
   Portions Copyright (C) 1988, 2000 Aladdin Enterprises.
   This software is based in part on the work of the Independent JPEG Group.
   All Rights Reserved.

   This software is distributed under license and may not be copied, modified
   or distributed except as expressly authorized under the terms of that
   license.  Refer to licensing information at http://www.artifex.com/ or
   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
   San Rafael, CA  94903, (415)492-9861, for further information. */
/*$Id$ */

/* pccrd.c - PCL interface to the graphic library color rendering dictionary */
#include "string_.h"
#include "gx.h"
#include "gsmatrix.h"
#include "gsmemory.h"
#include "gsstruct.h"
#include "gsrefct.h"
#include "gsparam.h"
#include "gsdevice.h"
#include "gscspace.h"
#include "gscolor2.h"
#include "gscie.h"
#include "gscrd.h"
#include "gscrdp.h"
#include "pcommand.h"
#include "pccrd.h"

/* GC routines */
private_st_crd_t();

/*
 * The default color rendering information. This works for a monitor that
 * uses linear SMPTE-C phosphors. This is almost certainly not the case for
 * any actual printing device, but the approximation will do for now.
 *
 * The following parameters are left at their graphic-library default values:
 *
 *    BlackPoint
 *    MatrixPQR
 *    RangePQR
 *    EncodeLMN
 *    RangeLMN
 *    MatrixABC
 *    EncodeABC
 *    RangeABC
 *    RenderTable
 *
 */
static const gs_vector3    dflt_WhitePoint = { 0.95, 1.0, 1.09 };
static const gs_range3     dflt_RangePQR = {{ {0, 1}, {0, 1}, {0, 1.09} }};
static const gs_matrix3    dflt_MatrixLMN = { {  3.51, -1.07,  0.06 },
                                               { -1.74,  1.98, -0.20 },
                                               { -0.54,  0.04,  1.05 },
                                               false };

/*
 * The TransformPQR structure.
 *
 * Unlike the earlier impelementations, there is now just a single procedure,
 * which accepts the the component index as an operand. Rather than returning
 * the mapped value, the location pointed to by pnew_val is used to hold the
 * result and a success (0) or error (< 0) indication is returned.
 */
  static int
dflt_TransformPQR_proc(
    int                 cmp_indx,
    floatp              val,
    const gs_cie_wbsd * cs_wbsd,
    gs_cie_render *     pcrd,
    float *             pnew_val
)
{
    const float *       pcrd_wht = (float *)&(cs_wbsd->wd.pqr);
    const float *       pcs_wht = (float *)&(cs_wbsd->ws.pqr);

    *pnew_val = val * pcrd_wht[cmp_indx] / pcs_wht[cmp_indx];
    return 0;
}

static const gs_cie_transform_proc3    dflt_TransformPQR_proto = {
    dflt_TransformPQR_proc,
    NULL,
    { NULL, 0 },
    NULL
};

/*
 * Free a PCL color rendering dictionary structure.
 */
void
free_crd(
    gs_memory_t *   pmem,
    void *          pvcrd,
    client_name_t   cname
)
{
    pcl_crd_t *     pcrd = (pcl_crd_t *)pvcrd;

    if (pcrd->pgscrd != 0)
        rc_decrement(pcrd->pgscrd, cname);
    gs_free_object(pmem, pvcrd, cname);
}

/*
 * Allocate a PCL color rendering dictionary structure.
 */
  static int
alloc_crd(
    pcl_crd_t **    ppcrd,
    gs_memory_t *   pmem
)
{
    pcl_crd_t *     pcrd = 0;
    int             code = 0;

    rc_alloc_struct_1( pcrd,
                       pcl_crd_t,
                       &st_crd_t,
                       pmem,
                       return e_Memory,
                       "pcl allocate CRD"
                       );
    pcrd->rc.free = free_crd;
    pcrd->is_dflt_illum = true;
    pcrd->pgscrd = 0;

    code = gs_cie_render1_build(&(pcrd->pgscrd), pmem, "pcl allocate CRD");
    if (code >= 0)
        *ppcrd = pcrd;
    else
        free_crd(pmem, pcrd, "pcl allocate CRD");
    return code;
}

#ifdef READ_DEVICE_CRD
/*
 * See if the default CRD is specified by the device.
 *
 * To simplify selection of more than one default CRD, this code allows more
 * than one CRD to be included in the parameters associated with a device,
 * and uses the device parameter "CRDName" to select the one that is to be
 * used as a default.
 *
 * Returns 
 */
  static bool
read_device_CRD(
    pcl_crd_t *     pcrd,
    pcl_state_t *   pcs
)
{
    gx_device *     pdev = gs_currentdevice(pcs->pgs);
    gs_c_param_list list;
    gs_param_string dstring;
    char            nbuff[64];  /* ample size */
    int             code = 0;

    /*get the CRDName parameter from the device */
    gs_c_param_list_write(&list, pcs->memory);
    if (param_request((gs_param_list *)&list, "CRDName") < 0)
        return false;

    if ((code = gs_getdeviceparams(pdev, (gs_param_list *)&list)) >= 0) {
        gs_c_param_list_read(&list);
        if ( (code = param_read_string( (gs_param_list *)&list,
                                        "CRDName",
                                        &dstring
                                        )) == 0 ) {
            if (dstring.size > sizeof(nbuff) - 1)
                code = 1;
            else {
                strncpy(nbuff, (char *)dstring.data, dstring.size);
                nbuff[dstring.size] = '\0';
            }
        }
    }
    gs_c_param_list_release(&list);
    if (code != 0)
        return false;

    gs_c_param_list_write(&list, pcs->memory);
    if (param_request((gs_param_list *)&list, nbuff) < 0)
        return false;
    if ((code = gs_getdeviceparams(pdev, (gs_param_list *)&list)) >= 0) {
        gs_param_dict   dict;

        gs_c_param_list_read(&list);
        if ( (code = param_begin_read_dict( (gs_param_list *)&list,
                                            nbuff,
                                            &dict,
                                            false
                                            )) == 0 ) {
            code = param_get_cie_render1(pcrd->pgscrd, dict.list, pdev);
            param_end_read_dict((gs_param_list *)&list, nbuff, &dict);
            if (code > 0)
                code = 0;
        }
    }
    gs_c_param_list_release(&list);
    return (code == 0);
}
#endif

/*
 * Build the default color rendering dictionary.
 *
 * This routine should be called only once, and then only when there is no
 * current CRD.
 *
 * Returns 0 on success, < 0 in the event of an error.
 */
  int
pcl_crd_build_default_crd(
    pcl_state_t *   pcs
)
{
    pcl_crd_t *     pcrd = pcs->pcl_default_crd;
    int             code = 0;

    /* must not be a current CRD */
    if (pcrd != 0)
        return e_Range;

    /* allocate the CRD structure */
    if ((code = alloc_crd(&pcrd, pcs->memory)) < 0)
        return code;
    pcs->pcl_default_crd = pcrd;

    pcs->dflt_TransformPQR = dflt_TransformPQR_proto;
    return gs_cie_render1_initialize( pcs->memory,
                                      pcrd->pgscrd,
                                      NULL,
                                      &dflt_WhitePoint,
                                      NULL,
                                      NULL,
                                      &dflt_RangePQR,
                                      &pcs->dflt_TransformPQR,
                                      &dflt_MatrixLMN,
                                      NULL,
                                      NULL,
                                      NULL,
                                      NULL,
                                      NULL,
                                      NULL
                                      );

}

/*
 * Set the viewing illuminant.
 *
 * Though this code goes through the motions of an "unshare" operation, it
 * will almost always allocate a new structure, as the CRD will be referred
 * to both by the palette and the graphic state.
 *
 * Returns 0 on success, < 0 in the event of an error.
 */
  int
pcl_crd_set_view_illuminant(
    pcl_state_t *       pcs,
    pcl_crd_t **        ppcrd,
    const gs_vector3 *  pwht_pt
)
{
    pcl_crd_t *         pcrd = *ppcrd;
    pcl_crd_t *         pold = pcrd;
    int                 code = 0;

    if (pcrd->rc.ref_count > 1) {
        if ((code = alloc_crd(ppcrd, pcrd->rc.memory)) < 0)
            return code;
        pcrd = *ppcrd;
    }
    pcrd->is_dflt_illum = false;

    /* if no previous CRD, use the default settings */
    if (pold == 0) {
        pcs->dflt_TransformPQR = dflt_TransformPQR_proto;
        return  gs_cie_render1_initialize( pcs->memory,
					   pcrd->pgscrd,
                                           NULL,
                                           pwht_pt,
                                           NULL,
                                           NULL,
                                           NULL,
                                           &pcs->dflt_TransformPQR,
                                           &dflt_MatrixLMN,
                                           NULL,
                                           NULL,
                                           NULL,
                                           NULL,
                                           NULL,
                                           NULL
                                           );
    }
    code = gs_cie_render1_init_from( pcs->memory,
				     pcrd->pgscrd,
                                     NULL,     /* for now */
				     pold->pgscrd,
                                     pwht_pt,
                                     &(pold->pgscrd->points.BlackPoint),
                                     &(pold->pgscrd->MatrixPQR),
                                     &(pold->pgscrd->RangePQR),
                                     &(pold->pgscrd->TransformPQR),
                                     &(pold->pgscrd->MatrixLMN),
                                     &(pold->pgscrd->EncodeLMN),
                                     &(pold->pgscrd->RangeLMN),
                                     &(pold->pgscrd->MatrixABC),
                                     &(pold->pgscrd->EncodeABC),
                                     &(pold->pgscrd->RangeABC),
                                     &(pold->pgscrd->RenderTable)
                                     );

    if (pcrd != pold)
	rc_decrement(pold, "pcl set viewing illuminant");
    return code;
}

/*
 * Set a color rendering dictionary into the graphic state. If the rendering
 * dictionary does not yet exist, create a default color rendering dictionary.
 *
 * Returns 0 on success, < 0 in the event of an error.
 */
  int
pcl_crd_set_crd(
    pcl_crd_t **    ppcrd,
    pcl_state_t *   pcs
)
{
    pcl_crd_t *     pcrd = *ppcrd;
    int             code = 0;

    if (pcrd == 0) {
        if ( (pcs->pcl_default_crd == 0) &&
             ((code = pcl_crd_build_default_crd(pcs)) < 0)  )
            return code;
        pcrd = pcs->pcl_default_crd;
        pcl_crd_init_from(*ppcrd, pcrd);
    }

    /* see if there is anything to do */
    if (pcs->pids->pcrd == pcrd)
        return 0;

    if ((code = gs_setcolorrendering(pcs->pgs, pcrd->pgscrd)) >= 0)
        pcl_crd_copy_from(pcs->pids->pcrd, pcrd);
    return code;
}