~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to psi/zcie.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
14
/* $Id: zcie.c 9043 2008-08-28 22:48:19Z giles $ */
 
15
/* CIE color operators */
 
16
#include "math_.h"
 
17
#include "memory_.h"
 
18
#include "ghost.h"
 
19
#include "oper.h"
 
20
#include "gsstruct.h"
 
21
#include "gxcspace.h"           /* gscolor2.h requires gscspace.h */
 
22
#include "gscolor2.h"
 
23
#include "gscie.h"
 
24
#include "estack.h"
 
25
#include "ialloc.h"
 
26
#include "idict.h"
 
27
#include "idparam.h"
 
28
#include "igstate.h"
 
29
#include "icie.h"
 
30
#include "isave.h"
 
31
#include "ivmspace.h"
 
32
#include "store.h"              /* for make_null */
 
33
#include "zcie.h"
 
34
 
 
35
/* Empty procedures */
 
36
static const ref empty_procs[4] =
 
37
{
 
38
    empty_ref_data(t_array, a_readonly | a_executable),
 
39
    empty_ref_data(t_array, a_readonly | a_executable),
 
40
    empty_ref_data(t_array, a_readonly | a_executable),
 
41
    empty_ref_data(t_array, a_readonly | a_executable)
 
42
};
 
43
 
 
44
/* ------ Parameter extraction utilities ------ */
 
45
 
 
46
/* Get a range array parameter from a dictionary. */
 
47
/* We know that count <= 4. */
 
48
int
 
49
dict_ranges_param(const gs_memory_t *mem,
 
50
                  const ref * pdref, const char *kstr, int count,
 
51
                  gs_range * prange)
 
52
{
 
53
    int code = dict_floats_param(mem, pdref, kstr, count * 2,
 
54
                                 (float *)prange, NULL);
 
55
 
 
56
    if (code < 0)
 
57
        return code;
 
58
    else if (code == 0)
 
59
        memcpy(prange, Range4_default.ranges, count * sizeof(gs_range));
 
60
    return 0;
 
61
}
 
62
 
 
63
/* Get an array of procedures from a dictionary. */
 
64
/* We know count <= countof(empty_procs). */
 
65
int
 
66
dict_proc_array_param(const gs_memory_t *mem,
 
67
                      const ref *pdict, const char *kstr,
 
68
                      uint count, ref *pparray)
 
69
{
 
70
    ref *pvalue;
 
71
 
 
72
    if (dict_find_string(pdict, kstr, &pvalue) > 0) {
 
73
        uint i;
 
74
 
 
75
        check_array_only(*pvalue);
 
76
        if (r_size(pvalue) != count)
 
77
            return_error(e_rangecheck);
 
78
        for (i = 0; i < count; i++) {
 
79
            ref proc;
 
80
 
 
81
            array_get(mem, pvalue, (long)i, &proc);
 
82
            check_proc_only(proc);
 
83
        }
 
84
        *pparray = *pvalue;
 
85
        return 0;
 
86
    } else {
 
87
        make_const_array(pparray, a_readonly | avm_foreign,
 
88
                         count, &empty_procs[0]);
 
89
        return 1;
 
90
    }
 
91
}
 
92
 
 
93
/* Get 3 ranges from a dictionary. */
 
94
int
 
95
dict_range3_param(const gs_memory_t *mem,
 
96
                  const ref *pdref, const char *kstr, 
 
97
                  gs_range3 *prange3)
 
98
{
 
99
    return dict_ranges_param(mem, pdref, kstr, 3, prange3->ranges);
 
100
}
 
101
 
 
102
/* Get a 3x3 matrix from a dictionary. */
 
103
int
 
104
dict_matrix3_param(const gs_memory_t *mem,
 
105
                   const ref *pdref, const char *kstr, gs_matrix3 *pmat3)
 
106
{
 
107
    /*
 
108
     * We can't simply call dict_float_array_param with the matrix
 
109
     * cast to a 9-element float array, because compilers may insert
 
110
     * padding elements after each of the vectors.  However, we can be
 
111
     * confident that there is no padding within a single vector.
 
112
     */
 
113
    float values[9], defaults[9];
 
114
    int code;
 
115
 
 
116
    memcpy(&defaults[0], &Matrix3_default.cu, 3 * sizeof(float));
 
117
    memcpy(&defaults[3], &Matrix3_default.cv, 3 * sizeof(float));
 
118
    memcpy(&defaults[6], &Matrix3_default.cw, 3 * sizeof(float));
 
119
    code = dict_floats_param(mem, pdref, kstr, 9, values, defaults);
 
120
    if (code < 0)
 
121
        return code;
 
122
    memcpy(&pmat3->cu, &values[0], 3 * sizeof(float));
 
123
    memcpy(&pmat3->cv, &values[3], 3 * sizeof(float));
 
124
    memcpy(&pmat3->cw, &values[6], 3 * sizeof(float));
 
125
    return 0;
 
126
}
 
127
 
 
128
/* Get 3 procedures from a dictionary. */
 
129
int
 
130
dict_proc3_param(const gs_memory_t *mem, const ref *pdref, const char *kstr, ref proc3[3])
 
131
{
 
132
    return dict_proc_array_param(mem, pdref, kstr, 3, proc3);
 
133
}
 
134
 
 
135
/* Get WhitePoint and BlackPoint values. */
 
136
int
 
137
cie_points_param(const gs_memory_t *mem, 
 
138
                 const ref * pdref, gs_cie_wb * pwb)
 
139
{
 
140
    int code;
 
141
 
 
142
    if ((code = dict_floats_param(mem, pdref, "WhitePoint", 3, (float *)&pwb->WhitePoint, NULL)) < 0 ||
 
143
        (code = dict_floats_param(mem, pdref, "BlackPoint", 3, (float *)&pwb->BlackPoint, (const float *)&BlackPoint_default)) < 0
 
144
        )
 
145
        return code;
 
146
    if (pwb->WhitePoint.u <= 0 ||
 
147
        pwb->WhitePoint.v != 1 ||
 
148
        pwb->WhitePoint.w <= 0 ||
 
149
        pwb->BlackPoint.u < 0 ||
 
150
        pwb->BlackPoint.v < 0 ||
 
151
        pwb->BlackPoint.w < 0
 
152
        )
 
153
        return_error(e_rangecheck);
 
154
    return 0;
 
155
}
 
156
 
 
157
/* Process a 3- or 4-dimensional lookup table from a dictionary. */
 
158
/* The caller has set pclt->n and pclt->m. */
 
159
/* ptref is known to be a readable array of size at least n+1. */
 
160
static int cie_3d_table_param(const ref * ptable, uint count, uint nbytes,
 
161
                               gs_const_string * strings);
 
162
int
 
163
cie_table_param(const ref * ptref, gx_color_lookup_table * pclt,
 
164
                gs_memory_t * mem)
 
165
{
 
166
    int n = pclt->n, m = pclt->m;
 
167
    const ref *pta = ptref->value.const_refs;
 
168
    int i;
 
169
    uint nbytes;
 
170
    int code;
 
171
    gs_const_string *table;
 
172
 
 
173
    for (i = 0; i < n; ++i) {
 
174
        check_type_only(pta[i], t_integer);
 
175
        if (pta[i].value.intval <= 1 || pta[i].value.intval > max_ushort)
 
176
            return_error(e_rangecheck);
 
177
        pclt->dims[i] = (int)pta[i].value.intval;
 
178
    }
 
179
    nbytes = m * pclt->dims[n - 2] * pclt->dims[n - 1];
 
180
    if (n == 3) {
 
181
        table =
 
182
            gs_alloc_struct_array(mem, pclt->dims[0], gs_const_string,
 
183
                                  &st_const_string_element, "cie_table_param");
 
184
        if (table == 0)
 
185
            return_error(e_VMerror);
 
186
        code = cie_3d_table_param(pta + 3, pclt->dims[0], nbytes, table);
 
187
    } else {                    /* n == 4 */
 
188
        int d0 = pclt->dims[0], d1 = pclt->dims[1];
 
189
        uint ntables = d0 * d1;
 
190
        const ref *psuba;
 
191
 
 
192
        check_read_type(pta[4], t_array);
 
193
        if (r_size(pta + 4) != d0)
 
194
            return_error(e_rangecheck);
 
195
        table =
 
196
            gs_alloc_struct_array(mem, ntables, gs_const_string,
 
197
                                  &st_const_string_element, "cie_table_param");
 
198
        if (table == 0)
 
199
            return_error(e_VMerror);
 
200
        psuba = pta[4].value.const_refs;
 
201
        /*
 
202
         * We know that d0 > 0, so code will always be set in the loop:
 
203
         * we initialize code to 0 here solely to pacify stupid compilers.
 
204
         */
 
205
        for (code = 0, i = 0; i < d0; ++i) {
 
206
            code = cie_3d_table_param(psuba + i, d1, nbytes, table + d1 * i);
 
207
            if (code < 0)
 
208
                break;
 
209
        }
 
210
    }
 
211
    if (code < 0) {
 
212
        gs_free_object(mem, table, "cie_table_param");
 
213
        return code;
 
214
    }
 
215
    pclt->table = table;
 
216
    return 0;
 
217
}
 
218
static int
 
219
cie_3d_table_param(const ref * ptable, uint count, uint nbytes,
 
220
                   gs_const_string * strings)
 
221
{
 
222
    const ref *rstrings;
 
223
    uint i;
 
224
 
 
225
    check_read_type(*ptable, t_array);
 
226
    if (r_size(ptable) != count)
 
227
        return_error(e_rangecheck);
 
228
    rstrings = ptable->value.const_refs;
 
229
    for (i = 0; i < count; ++i) {
 
230
        const ref *const prt2 = rstrings + i;
 
231
 
 
232
        check_read_type(*prt2, t_string);
 
233
        if (r_size(prt2) != nbytes)
 
234
            return_error(e_rangecheck);
 
235
        strings[i].data = prt2->value.const_bytes;
 
236
        strings[i].size = nbytes;
 
237
    }
 
238
    return 0;
 
239
}
 
240
 
 
241
/* ------ CIE setcolorspace ------ */
 
242
 
 
243
/* Common code for the CIEBased* cases of setcolorspace. */
 
244
static int
 
245
cie_lmnp_param(const gs_memory_t *mem, const ref * pdref, gs_cie_common * pcie, ref_cie_procs * pcprocs)
 
246
{
 
247
    int code;
 
248
 
 
249
    if ((code = dict_range3_param(mem, pdref, "RangeLMN", &pcie->RangeLMN)) < 0 ||
 
250
        (code = dict_proc3_param(mem, pdref, "DecodeLMN", &pcprocs->DecodeLMN)) < 0 ||
 
251
        (code = dict_matrix3_param(mem, pdref, "MatrixLMN", &pcie->MatrixLMN)) < 0 ||
 
252
        (code = cie_points_param(mem, pdref, &pcie->points)) < 0
 
253
        )
 
254
        return code;
 
255
    pcie->DecodeLMN = DecodeLMN_default;
 
256
    return 0;
 
257
}
 
258
 
 
259
/* Common code for the CIEBasedABC/DEF[G] cases of setcolorspace. */
 
260
static int
 
261
cie_abc_param(const gs_memory_t *mem, const ref * pdref, gs_cie_abc * pcie, ref_cie_procs * pcprocs)
 
262
{
 
263
    int code;
 
264
 
 
265
    if ((code = dict_range3_param(mem, pdref, "RangeABC", &pcie->RangeABC)) < 0 ||
 
266
        (code = dict_proc3_param(mem, pdref, "DecodeABC", &pcprocs->Decode.ABC)) < 0 ||
 
267
        (code = dict_matrix3_param(mem, pdref, "MatrixABC", &pcie->MatrixABC)) < 0 ||
 
268
        (code = cie_lmnp_param(mem, pdref, &pcie->common, pcprocs)) < 0
 
269
        )
 
270
        return code;
 
271
    pcie->DecodeABC = DecodeABC_default;
 
272
    return 0;
 
273
}
 
274
 
 
275
/* Finish setting a CIE space (successful or not). */
 
276
int
 
277
cie_set_finish(i_ctx_t *i_ctx_p, gs_color_space * pcs,
 
278
               const ref_cie_procs * pcprocs, int edepth, int code)
 
279
{
 
280
    if (code >= 0)
 
281
        code = gs_setcolorspace(igs, pcs);
 
282
    /* Delete the extra reference to the parameter tables. */
 
283
    rc_decrement_only(pcs, "cie_set_finish");
 
284
    if (code < 0) {
 
285
        ref_stack_pop_to(&e_stack, edepth);
 
286
        return code;
 
287
    }
 
288
    istate->colorspace.procs.cie = *pcprocs;
 
289
    pop(1);
 
290
    return (ref_stack_count(&e_stack) == edepth ? 0 : o_push_estack);
 
291
}
 
292
 
 
293
/* Forward references */
 
294
static int cache_common(i_ctx_t *, gs_cie_common *, const ref_cie_procs *,
 
295
                         void *, gs_ref_memory_t *);
 
296
static int cache_abc_common(i_ctx_t *, gs_cie_abc *, const ref_cie_procs *,
 
297
                             void *, gs_ref_memory_t *);
 
298
 
 
299
static int cie_defg_finish(i_ctx_t *);
 
300
int
 
301
ciedefgspace(i_ctx_t *i_ctx_p, ref *CIEDict)
 
302
{
 
303
    os_ptr op = osp;
 
304
    int edepth = ref_stack_count(&e_stack);
 
305
    gs_memory_t *mem = gs_state_memory(igs);
 
306
    gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
 
307
    gs_color_space *pcs;
 
308
    ref_cie_procs procs;
 
309
    gs_cie_defg *pcie;
 
310
    int code;
 
311
    ref *ptref;
 
312
 
 
313
    push(1);
 
314
    if ((code = dict_find_string(CIEDict, "Table", &ptref)) <= 0)
 
315
        return (code < 0 ? code : gs_note_error(e_rangecheck));
 
316
    check_read_type(*ptref, t_array);
 
317
    if (r_size(ptref) != 5)
 
318
        return_error(e_rangecheck);
 
319
    procs = istate->colorspace.procs.cie;
 
320
    code = gs_cspace_build_CIEDEFG(&pcs, NULL, mem);
 
321
    if (code < 0)
 
322
        return code;
 
323
    pcie = pcs->params.defg;
 
324
    pcie->Table.n = 4;
 
325
    pcie->Table.m = 3;
 
326
    if ((code = dict_ranges_param(mem, CIEDict, "RangeDEFG", 4, pcie->RangeDEFG.ranges)) < 0 ||
 
327
        (code = dict_proc_array_param(mem, CIEDict, "DecodeDEFG", 4, &procs.PreDecode.DEFG)) < 0 ||
 
328
        (code = dict_ranges_param(mem, CIEDict, "RangeHIJK", 4, pcie->RangeHIJK.ranges)) < 0 ||
 
329
        (code = cie_table_param(ptref, &pcie->Table, mem)) < 0 ||
 
330
        (code = cie_abc_param(imemory, CIEDict, (gs_cie_abc *) pcie, &procs)) < 0 ||
 
331
        (code = cie_cache_joint(i_ctx_p, &istate->colorrendering.procs, (gs_cie_common *)pcie, igs)) < 0 ||     /* do this last */
 
332
        (code = cie_cache_push_finish(i_ctx_p, cie_defg_finish, imem, pcie)) < 0 ||
 
333
        (code = cie_prepare_cache4(i_ctx_p, &pcie->RangeDEFG,
 
334
                                   procs.PreDecode.DEFG.value.const_refs,
 
335
                                   &pcie->caches_defg.DecodeDEFG[0],
 
336
                                   pcie, imem, "Decode.DEFG")) < 0 ||
 
337
        (code = cache_abc_common(i_ctx_p, (gs_cie_abc *)pcie, &procs, pcie, imem)) < 0
 
338
        )
 
339
        DO_NOTHING;
 
340
    return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code);
 
341
}
 
342
static int
 
343
cie_defg_finish(i_ctx_t *i_ctx_p)
 
344
{
 
345
    os_ptr op = osp;
 
346
    gs_cie_defg *pcie = r_ptr(op, gs_cie_defg);
 
347
 
 
348
    pcie->DecodeDEFG = DecodeDEFG_from_cache;
 
349
    pcie->DecodeABC = DecodeABC_from_cache;
 
350
    pcie->common.DecodeLMN = DecodeLMN_from_cache;
 
351
    gs_cie_defg_complete(pcie);
 
352
    pop(1);
 
353
    return 0;
 
354
}
 
355
 
 
356
static int cie_def_finish(i_ctx_t *);
 
357
int
 
358
ciedefspace(i_ctx_t *i_ctx_p, ref *CIEDict)
 
359
{
 
360
    os_ptr op = osp;
 
361
    int edepth = ref_stack_count(&e_stack);
 
362
    gs_memory_t *mem = gs_state_memory(igs);
 
363
    gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
 
364
    gs_color_space *pcs;
 
365
    ref_cie_procs procs;
 
366
    gs_cie_def *pcie;
 
367
    int code;
 
368
    ref *ptref;
 
369
 
 
370
    push(1);
 
371
    if ((code = dict_find_string(CIEDict, "Table", &ptref)) <= 0)
 
372
        return (code < 0 ? code : gs_note_error(e_rangecheck));
 
373
    check_read_type(*ptref, t_array);
 
374
    if (r_size(ptref) != 4)
 
375
        return_error(e_rangecheck);
 
376
    procs = istate->colorspace.procs.cie;
 
377
    code = gs_cspace_build_CIEDEF(&pcs, NULL, mem);
 
378
    if (code < 0)
 
379
        return code;
 
380
    pcie = pcs->params.def;
 
381
    pcie->Table.n = 3;
 
382
    pcie->Table.m = 3;
 
383
    if ((code = dict_range3_param(mem, CIEDict, "RangeDEF", &pcie->RangeDEF)) < 0 ||
 
384
        (code = dict_proc3_param(mem, CIEDict, "DecodeDEF", &procs.PreDecode.DEF)) < 0 ||
 
385
        (code = dict_range3_param(mem, CIEDict, "RangeHIJ", &pcie->RangeHIJ)) < 0 ||
 
386
        (code = cie_table_param(ptref, &pcie->Table, mem)) < 0 ||
 
387
        (code = cie_abc_param(imemory, CIEDict, (gs_cie_abc *) pcie, &procs)) < 0 ||
 
388
        (code = cie_cache_joint(i_ctx_p, &istate->colorrendering.procs, (gs_cie_common *)pcie, igs)) < 0 ||     /* do this last */
 
389
        (code = cie_cache_push_finish(i_ctx_p, cie_def_finish, imem, pcie)) < 0 ||
 
390
        (code = cie_prepare_cache3(i_ctx_p, &pcie->RangeDEF,
 
391
                                   procs.PreDecode.DEF.value.const_refs,
 
392
                                   &pcie->caches_def.DecodeDEF[0],
 
393
                                   pcie, imem, "Decode.DEF")) < 0 ||
 
394
        (code = cache_abc_common(i_ctx_p, (gs_cie_abc *)pcie, &procs, pcie, imem)) < 0
 
395
        )
 
396
        DO_NOTHING;
 
397
    return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code);
 
398
}
 
399
static int
 
400
cie_def_finish(i_ctx_t *i_ctx_p)
 
401
{
 
402
    os_ptr op = osp;
 
403
    gs_cie_def *pcie = r_ptr(op, gs_cie_def);
 
404
 
 
405
    pcie->DecodeDEF = DecodeDEF_from_cache;
 
406
    pcie->DecodeABC = DecodeABC_from_cache;
 
407
    pcie->common.DecodeLMN = DecodeLMN_from_cache;
 
408
    gs_cie_def_complete(pcie);
 
409
    pop(1);
 
410
    return 0;
 
411
}
 
412
 
 
413
static int cie_abc_finish(i_ctx_t *);
 
414
 
 
415
int
 
416
cieabcspace(i_ctx_t *i_ctx_p, ref *CIEDict)
 
417
{
 
418
    os_ptr op = osp;
 
419
    int edepth = ref_stack_count(&e_stack);
 
420
    gs_memory_t *mem = gs_state_memory(igs);
 
421
    gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
 
422
    gs_color_space *pcs;
 
423
    ref_cie_procs procs;
 
424
    gs_cie_abc *pcie;
 
425
    int code;
 
426
 
 
427
    push(1); /* Sacrificial */
 
428
    procs = istate->colorspace.procs.cie;
 
429
    code = gs_cspace_build_CIEABC(&pcs, NULL, mem);
 
430
    if (code < 0)
 
431
        return code;
 
432
    pcie = pcs->params.abc;
 
433
    code = cie_abc_param(imemory, CIEDict, pcie, &procs);
 
434
    if (code < 0 ||
 
435
        (code = cie_cache_joint(i_ctx_p, &istate->colorrendering.procs, (gs_cie_common *)pcie, igs)) < 0 ||     /* do this last */
 
436
        (code = cie_cache_push_finish(i_ctx_p, cie_abc_finish, imem, pcie)) < 0 ||
 
437
        (code = cache_abc_common(i_ctx_p, pcie, &procs, pcie, imem)) < 0
 
438
        )
 
439
        DO_NOTHING;
 
440
    return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code);
 
441
}
 
442
static int
 
443
cie_abc_finish(i_ctx_t *i_ctx_p)
 
444
{
 
445
    os_ptr op = osp;
 
446
    gs_cie_abc *pcie = r_ptr(op, gs_cie_abc);
 
447
 
 
448
    pcie->DecodeABC = DecodeABC_from_cache;
 
449
    pcie->common.DecodeLMN = DecodeLMN_from_cache;
 
450
    gs_cie_abc_complete(pcie);
 
451
    pop(1);
 
452
    return 0;
 
453
}
 
454
 
 
455
static int cie_a_finish(i_ctx_t *);
 
456
 
 
457
int
 
458
cieaspace(i_ctx_t *i_ctx_p, ref *CIEdict)
 
459
{
 
460
    os_ptr op = osp;
 
461
    int edepth = ref_stack_count(&e_stack);
 
462
    gs_memory_t *mem = gs_state_memory(igs);
 
463
    gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
 
464
    gs_color_space *pcs;
 
465
    ref_cie_procs procs;
 
466
    gs_cie_a *pcie;
 
467
    int code;
 
468
 
 
469
    push(1); /* Sacrificial. cie_a_finish does a pop... */
 
470
    procs = istate->colorspace.procs.cie;
 
471
    if ((code = dict_proc_param(CIEdict, "DecodeA", &procs.Decode.A, true)) < 0)
 
472
        return code;
 
473
    code = gs_cspace_build_CIEA(&pcs, NULL, mem);
 
474
    if (code < 0)
 
475
        return code;
 
476
    pcie = pcs->params.a;
 
477
    if ((code = dict_floats_param(imemory, CIEdict, "RangeA", 2, (float *)&pcie->RangeA, (const float *)&RangeA_default)) < 0 ||
 
478
        (code = dict_floats_param(imemory, CIEdict, "MatrixA", 3, (float *)&pcie->MatrixA, (const float *)&MatrixA_default)) < 0 ||
 
479
        (code = cie_lmnp_param(imemory, CIEdict, &pcie->common, &procs)) < 0 ||
 
480
        (code = cie_cache_joint(i_ctx_p, &istate->colorrendering.procs, (gs_cie_common *)pcie, igs)) < 0 ||     /* do this last */
 
481
        (code = cie_cache_push_finish(i_ctx_p, cie_a_finish, imem, pcie)) < 0 ||
 
482
        (code = cie_prepare_cache(i_ctx_p, &pcie->RangeA, &procs.Decode.A, &pcie->caches.DecodeA.floats, pcie, imem, "Decode.A")) < 0 ||
 
483
        (code = cache_common(i_ctx_p, &pcie->common, &procs, pcie, imem)) < 0
 
484
        )
 
485
        DO_NOTHING;
 
486
    pcie->DecodeA = DecodeA_default;
 
487
    return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code);
 
488
}
 
489
static int
 
490
cie_a_finish(i_ctx_t *i_ctx_p)
 
491
{
 
492
    os_ptr op = osp;
 
493
    gs_cie_a *pcie = r_ptr(op, gs_cie_a);
 
494
 
 
495
    pcie->DecodeA = DecodeA_from_cache;
 
496
    pcie->common.DecodeLMN = DecodeLMN_from_cache;
 
497
    gs_cie_a_complete(pcie);
 
498
    pop(1);
 
499
    return 0;
 
500
}
 
501
 
 
502
/* Common cache code */
 
503
 
 
504
static int
 
505
cache_abc_common(i_ctx_t *i_ctx_p, gs_cie_abc * pcie,
 
506
                 const ref_cie_procs * pcprocs,
 
507
                 void *container, gs_ref_memory_t * imem)
 
508
{
 
509
    int code =
 
510
        cie_prepare_cache3(i_ctx_p, &pcie->RangeABC,
 
511
                           pcprocs->Decode.ABC.value.const_refs,
 
512
                           pcie->caches.DecodeABC.caches, pcie, imem,
 
513
                           "Decode.ABC");
 
514
 
 
515
    return (code < 0 ? code :
 
516
            cache_common(i_ctx_p, &pcie->common, pcprocs, pcie, imem));
 
517
}
 
518
 
 
519
static int
 
520
cache_common(i_ctx_t *i_ctx_p, gs_cie_common * pcie,
 
521
             const ref_cie_procs * pcprocs,
 
522
             void *container, gs_ref_memory_t * imem)
 
523
{
 
524
    return cie_prepare_cache3(i_ctx_p, &pcie->RangeLMN,
 
525
                              pcprocs->DecodeLMN.value.const_refs,
 
526
                              &pcie->caches.DecodeLMN[0], container, imem,
 
527
                              "Decode.LMN");
 
528
}
 
529
 
 
530
/* ------ Internal routines ------ */
 
531
 
 
532
/* Prepare to cache the values for one or more procedures. */
 
533
static int cie_cache_finish1(i_ctx_t *);
 
534
static int cie_cache_finish(i_ctx_t *);
 
535
int
 
536
cie_prepare_cache(i_ctx_t *i_ctx_p, const gs_range * domain, const ref * proc,
 
537
                  cie_cache_floats * pcache, void *container,
 
538
                  gs_ref_memory_t * imem, client_name_t cname)
 
539
{
 
540
    int space = imemory_space(imem);
 
541
    gs_sample_loop_params_t lp;
 
542
    es_ptr ep;
 
543
 
 
544
    gs_cie_cache_init(&pcache->params, &lp, domain, cname);
 
545
    pcache->params.is_identity = r_size(proc) == 0;
 
546
    check_estack(9);
 
547
    ep = esp;
 
548
    make_real(ep + 9, lp.A);
 
549
    make_int(ep + 8, lp.N);
 
550
    make_real(ep + 7, lp.B);
 
551
    ep[6] = *proc;
 
552
    r_clear_attrs(ep + 6, a_executable);
 
553
    make_op_estack(ep + 5, zcvx);
 
554
    make_op_estack(ep + 4, zfor_samples);
 
555
    make_op_estack(ep + 3, cie_cache_finish);
 
556
    esp += 9;
 
557
    /*
 
558
     * The caches are embedded in the middle of other
 
559
     * structures, so we represent the pointer to the cache
 
560
     * as a pointer to the container plus an offset.
 
561
     */
 
562
    make_int(ep + 2, (char *)pcache - (char *)container);
 
563
    make_struct(ep + 1, space, container);
 
564
    return o_push_estack;
 
565
}
 
566
/* Note that pc3 may be 0, indicating that there are only 3 caches to load. */
 
567
int
 
568
cie_prepare_caches_4(i_ctx_t *i_ctx_p, const gs_range * domains,
 
569
                     const ref * procs,
 
570
                     cie_cache_floats * pc0, cie_cache_floats * pc1,
 
571
                     cie_cache_floats * pc2, cie_cache_floats * pc3,
 
572
                     void *container,
 
573
                     gs_ref_memory_t * imem, client_name_t cname)
 
574
{
 
575
    cie_cache_floats *pcn[4];
 
576
    int i, n, code = 0;
 
577
 
 
578
    pcn[0] = pc0, pcn[1] = pc1, pcn[2] = pc2;
 
579
    if (pc3 == 0)
 
580
        n = 3;
 
581
    else
 
582
        pcn[3] = pc3, n = 4;
 
583
    for (i = 0; i < n && code >= 0; ++i)
 
584
        code = cie_prepare_cache(i_ctx_p, domains + i, procs + i, pcn[i],
 
585
                                 container, imem, cname);
 
586
    return code;
 
587
}
 
588
 
 
589
/* Store the result of caching one procedure. */
 
590
static int
 
591
cie_cache_finish_store(i_ctx_t *i_ctx_p, bool replicate)
 
592
{
 
593
    os_ptr op = osp;
 
594
    cie_cache_floats *pcache;
 
595
    int code;
 
596
 
 
597
    check_esp(2);
 
598
    /* See above for the container + offset representation of */
 
599
    /* the pointer to the cache. */
 
600
    pcache = (cie_cache_floats *) (r_ptr(esp - 1, char) + esp->value.intval);
 
601
 
 
602
    pcache->params.is_identity = false; /* cache_set_linear computes this */
 
603
    if_debug3('c', "[c]cache 0x%lx base=%g, factor=%g:\n",
 
604
              (ulong) pcache, pcache->params.base, pcache->params.factor);
 
605
    if (replicate ||
 
606
        (code = float_params(op, gx_cie_cache_size, &pcache->values[0])) < 0
 
607
        ) {
 
608
        /* We might have underflowed the current stack block. */
 
609
        /* Handle the parameters one-by-one. */
 
610
        uint i;
 
611
 
 
612
        for (i = 0; i < gx_cie_cache_size; i++) {
 
613
            code = float_param(ref_stack_index(&o_stack,
 
614
                               (replicate ? 0 : gx_cie_cache_size - 1 - i)),
 
615
                               &pcache->values[i]);
 
616
            if (code < 0)
 
617
                return code;
 
618
        }
 
619
    }
 
620
#ifdef DEBUG
 
621
    if (gs_debug_c('c')) {
 
622
        int i;
 
623
 
 
624
        for (i = 0; i < gx_cie_cache_size; i += 4)
 
625
            dlprintf5("[c]  cache[%3d]=%g, %g, %g, %g\n", i,
 
626
                      pcache->values[i], pcache->values[i + 1],
 
627
                      pcache->values[i + 2], pcache->values[i + 3]);
 
628
    }
 
629
#endif
 
630
    ref_stack_pop(&o_stack, (replicate ? 1 : gx_cie_cache_size));
 
631
    esp -= 2;                   /* pop pointer to cache */
 
632
    return o_pop_estack;
 
633
}
 
634
static int
 
635
cie_cache_finish(i_ctx_t *i_ctx_p)
 
636
{
 
637
    return cie_cache_finish_store(i_ctx_p, false);
 
638
}
 
639
static int
 
640
cie_cache_finish1(i_ctx_t *i_ctx_p)
 
641
{
 
642
    return cie_cache_finish_store(i_ctx_p, true);
 
643
}
 
644
 
 
645
/* Push a finishing procedure on the e-stack. */
 
646
/* ptr will be the top element of the o-stack. */
 
647
int
 
648
cie_cache_push_finish(i_ctx_t *i_ctx_p, op_proc_t finish_proc,
 
649
                      gs_ref_memory_t * imem, void *data)
 
650
{
 
651
    check_estack(2);
 
652
    push_op_estack(finish_proc);
 
653
    ++esp;
 
654
    make_struct(esp, imemory_space(imem), data);
 
655
    return o_push_estack;
 
656
}
 
657