Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gscie.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 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,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* CIE color rendering cache management */
18
#include "math_.h"
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsstruct.h"
23
#include "gsmatrix.h"   /* for gscolor2.h */
24
#include "gxcspace.h"   /* for gxcie.c */
25
#include "gscolor2.h"   /* for gs_set/currentcolorrendering */
26
#include "gxarith.h"
27
#include "gxcie.h"
28
#include "gxdevice.h"   /* for gxcmap.h */
29
#include "gxcmap.h"
30
#include "gzstate.h"
31
#include "gsicc.h"
32
33
/*
34
 * Define whether to optimize the CIE mapping process by combining steps.
35
 * This should only be disabled (commented out) for debugging.
36
 */
37
#define OPTIMIZE_CIE_MAPPING
38
39
/* Forward references */
40
static int cie_joint_caches_init(gx_cie_joint_caches *,
41
                                  const gs_cie_common *,
42
                                  gs_cie_render *);
43
static void cie_joint_caches_complete(gx_cie_joint_caches *,
44
                                       const gs_cie_common *,
45
                                       const gs_cie_abc *,
46
                                       const gs_cie_render *);
47
static void cie_cache_restrict(cie_cache_floats *, const gs_range *);
48
static void cie_invert3(const gs_matrix3 *, gs_matrix3 *);
49
static void cie_matrix_init(gs_matrix3 *);
50
51
/* Allocator structure types */
52
private_st_joint_caches();
53
extern_st(st_gs_gstate);
54
55
#define RESTRICTED_INDEX(v, n, itemp)\
56
0
  ((uint)(itemp = (int)(v)) >= (n) ?\
57
0
   (itemp < 0 ? 0 : (n) - 1) : itemp)
58
59
/* Define cache interpolation threshold values. */
60
#ifdef CIE_CACHE_INTERPOLATE
61
#  ifdef CIE_INTERPOLATE_THRESHOLD
62
89.2k
#    define CACHE_THRESHOLD CIE_INTERPOLATE_THRESHOLD
63
#  else
64
#    define CACHE_THRESHOLD 0 /* always interpolate */
65
#  endif
66
#else
67
#  define CACHE_THRESHOLD 1.0e6 /* never interpolate */
68
#endif
69
#ifdef CIE_RENDER_TABLE_INTERPOLATE
70
#  define RENDER_TABLE_THRESHOLD 0
71
#else
72
#  define RENDER_TABLE_THRESHOLD 1.0e6
73
#endif
74
75
/*
76
 * Determine whether a function is a linear transformation of the form
77
 * f(x) = scale * x + origin.
78
 */
79
static bool
80
cache_is_linear(cie_linear_params_t *params, const cie_cache_floats *pcf)
81
0
{
82
0
    double origin = pcf->values[0];
83
0
    double diff = pcf->values[countof(pcf->values) - 1] - origin;
84
0
    double scale = diff / (countof(pcf->values) - 1);
85
0
    int i;
86
0
    double test = origin + scale;
87
88
0
    for (i = 1; i < countof(pcf->values) - 1; ++i, test += scale)
89
0
        if (fabs(pcf->values[i] - test) >= 0.5 / countof(pcf->values))
90
0
            return (params->is_linear = false);
91
0
    params->origin = origin - pcf->params.base;
92
0
    params->scale =
93
0
        diff * pcf->params.factor / (countof(pcf->values) - 1);
94
0
    return (params->is_linear = true);
95
0
}
96
97
static void
98
cache_set_linear(cie_cache_floats *pcf)
99
267k
{
100
267k
        if (pcf->params.is_identity) {
101
267k
            if_debug1('c', "[c]is_linear("PRI_INTPTR") = true (is_identity)\n",
102
267k
                      (intptr_t)pcf);
103
267k
            pcf->params.linear.is_linear = true;
104
267k
            pcf->params.linear.origin = 0;
105
267k
            pcf->params.linear.scale = 1;
106
267k
        } else if (cache_is_linear(&pcf->params.linear, pcf)) {
107
0
            if (pcf->params.linear.origin == 0 &&
108
0
                fabs(pcf->params.linear.scale - 1) < 0.00001)
109
0
                pcf->params.is_identity = true;
110
0
            if_debug4('c',
111
0
                      "[c]is_linear("PRI_INTPTR") = true, origin = %g, scale = %g%s\n",
112
0
                      (intptr_t)pcf, pcf->params.linear.origin,
113
0
                      pcf->params.linear.scale,
114
0
                      (pcf->params.is_identity ? " (=> is_identity)" : ""));
115
0
        }
116
#ifdef DEBUG
117
        else
118
            if_debug1('c', "[c]linear("PRI_INTPTR") = false\n", (intptr_t)pcf);
119
#endif
120
267k
}
121
static void
122
cache3_set_linear(gx_cie_vector_cache3_t *pvc)
123
89.2k
{
124
89.2k
    cache_set_linear(&pvc->caches[0].floats);
125
89.2k
    cache_set_linear(&pvc->caches[1].floats);
126
89.2k
    cache_set_linear(&pvc->caches[2].floats);
127
89.2k
}
128
129
#ifdef DEBUG
130
static void
131
if_debug_vector3(const char *str, const gs_vector3 *vec)
132
{
133
    if_debug4('c', "%s[%g %g %g]\n", str, vec->u, vec->v, vec->w);
134
}
135
static void
136
if_debug_matrix3(const char *str, const gs_matrix3 *mat)
137
{
138
    if_debug10('c', "%s [%g %g %g] [%g %g %g] [%g %g %g]\n", str,
139
               mat->cu.u, mat->cu.v, mat->cu.w,
140
               mat->cv.u, mat->cv.v, mat->cv.w,
141
               mat->cw.u, mat->cw.v, mat->cw.w);
142
}
143
#else
144
892k
#  define if_debug_vector3(str, vec) DO_NOTHING
145
1.16M
#  define if_debug_matrix3(str, mat) DO_NOTHING
146
#endif
147
148
/* ------ Default values for CIE dictionary elements ------ */
149
150
/* Default transformation procedures. */
151
152
float
153
a_identity(double in, const gs_cie_a * pcie)
154
0
{
155
0
    return in;
156
0
}
157
static float
158
a_from_cache(double in, const gs_cie_a * pcie)
159
0
{
160
0
    return gs_cie_cached_value(in, &pcie->caches.DecodeA.floats);
161
0
}
162
163
float
164
abc_identity(double in, const gs_cie_abc * pcie)
165
0
{
166
0
    return in;
167
0
}
168
static float
169
abc_from_cache_0(double in, const gs_cie_abc * pcie)
170
0
{
171
0
    return gs_cie_cached_value(in, &pcie->caches.DecodeABC.caches[0].floats);
172
0
}
173
static float
174
abc_from_cache_1(double in, const gs_cie_abc * pcie)
175
0
{
176
0
    return gs_cie_cached_value(in, &pcie->caches.DecodeABC.caches[1].floats);
177
0
}
178
static float
179
abc_from_cache_2(double in, const gs_cie_abc * pcie)
180
0
{
181
0
    return gs_cie_cached_value(in, &pcie->caches.DecodeABC.caches[2].floats);
182
0
}
183
184
static float
185
def_identity(double in, const gs_cie_def * pcie)
186
0
{
187
0
    return in;
188
0
}
189
static float
190
def_from_cache_0(double in, const gs_cie_def * pcie)
191
0
{
192
0
    return gs_cie_cached_value(in, &pcie->caches_def.DecodeDEF[0].floats);
193
0
}
194
static float
195
def_from_cache_1(double in, const gs_cie_def * pcie)
196
0
{
197
0
    return gs_cie_cached_value(in, &pcie->caches_def.DecodeDEF[1].floats);
198
0
}
199
static float
200
def_from_cache_2(double in, const gs_cie_def * pcie)
201
0
{
202
0
    return gs_cie_cached_value(in, &pcie->caches_def.DecodeDEF[2].floats);
203
0
}
204
205
static float
206
defg_identity(double in, const gs_cie_defg * pcie)
207
0
{
208
0
    return in;
209
0
}
210
static float
211
defg_from_cache_0(double in, const gs_cie_defg * pcie)
212
0
{
213
0
    return gs_cie_cached_value(in, &pcie->caches_defg.DecodeDEFG[0].floats);
214
0
}
215
static float
216
defg_from_cache_1(double in, const gs_cie_defg * pcie)
217
0
{
218
0
    return gs_cie_cached_value(in, &pcie->caches_defg.DecodeDEFG[1].floats);
219
0
}
220
static float
221
defg_from_cache_2(double in, const gs_cie_defg * pcie)
222
0
{
223
0
    return gs_cie_cached_value(in, &pcie->caches_defg.DecodeDEFG[2].floats);
224
0
}
225
static float
226
defg_from_cache_3(double in, const gs_cie_defg * pcie)
227
0
{
228
0
    return gs_cie_cached_value(in, &pcie->caches_defg.DecodeDEFG[3].floats);
229
0
}
230
231
float
232
common_identity(double in, const gs_cie_common * pcie)
233
0
{
234
0
    return in;
235
0
}
236
static float
237
lmn_from_cache_0(double in, const gs_cie_common * pcie)
238
0
{
239
0
    return gs_cie_cached_value(in, &pcie->caches.DecodeLMN[0].floats);
240
0
}
241
static float
242
lmn_from_cache_1(double in, const gs_cie_common * pcie)
243
0
{
244
0
    return gs_cie_cached_value(in, &pcie->caches.DecodeLMN[1].floats);
245
0
}
246
static float
247
lmn_from_cache_2(double in, const gs_cie_common * pcie)
248
0
{
249
0
    return gs_cie_cached_value(in, &pcie->caches.DecodeLMN[2].floats);
250
0
}
251
252
/* Transformation procedures for accessing an already-loaded cache. */
253
254
float
255
gs_cie_cached_value(double in, const cie_cache_floats *pcache)
256
0
{
257
    /*
258
     * We need to get the same results when we sample an already-loaded
259
     * cache, so we need to round the index just a tiny bit.
260
     */
261
0
    int index =
262
0
        (int)((in - pcache->params.base) * pcache->params.factor + 0.0001);
263
264
0
    CIE_CLAMP_INDEX(index);
265
0
    return pcache->values[index];
266
0
}
267
268
/* Default vectors and matrices. */
269
270
const gs_range3 Range3_default = {
271
    { {0, 1}, {0, 1}, {0, 1} }
272
};
273
const gs_range4 Range4_default = {
274
    { {0, 1}, {0, 1}, {0, 1}, {0, 1} }
275
};
276
const gs_cie_defg_proc4 DecodeDEFG_default = {
277
    {defg_identity, defg_identity, defg_identity, defg_identity}
278
};
279
const gs_cie_defg_proc4 DecodeDEFG_from_cache = {
280
    {defg_from_cache_0, defg_from_cache_1, defg_from_cache_2, defg_from_cache_3}
281
};
282
const gs_cie_def_proc3 DecodeDEF_default = {
283
    {def_identity, def_identity, def_identity}
284
};
285
const gs_cie_def_proc3 DecodeDEF_from_cache = {
286
    {def_from_cache_0, def_from_cache_1, def_from_cache_2}
287
};
288
const gs_cie_abc_proc3 DecodeABC_default = {
289
    {abc_identity, abc_identity, abc_identity}
290
};
291
const gs_cie_abc_proc3 DecodeABC_from_cache = {
292
    {abc_from_cache_0, abc_from_cache_1, abc_from_cache_2}
293
};
294
const gs_cie_common_proc3 DecodeLMN_default = {
295
    {common_identity, common_identity, common_identity}
296
};
297
const gs_cie_common_proc3 DecodeLMN_from_cache = {
298
    {lmn_from_cache_0, lmn_from_cache_1, lmn_from_cache_2}
299
};
300
const gs_matrix3 Matrix3_default = {
301
    {1, 0, 0},
302
    {0, 1, 0},
303
    {0, 0, 1},
304
    1 /*true */
305
};
306
const gs_range RangeA_default = {0, 1};
307
const gs_cie_a_proc DecodeA_default = a_identity;
308
const gs_cie_a_proc DecodeA_from_cache = a_from_cache;
309
const gs_vector3 MatrixA_default = {1, 1, 1};
310
const gs_vector3 BlackPoint_default = {0, 0, 0};
311
312
/* Initialize a CIE color. */
313
/* This only happens on setcolorspace. */
314
void
315
gx_init_CIE(gs_client_color * pcc, const gs_color_space * pcs)
316
0
{
317
0
    gx_init_paint_4(pcc, pcs);
318
    /* (0...) may not be within the range of allowable values. */
319
0
    (*pcs->type->restrict_color)(pcc, pcs);
320
0
}
321
322
/* Restrict CIE colors. */
323
324
static inline void
325
cie_restrict(float *pv, const gs_range *range)
326
0
{
327
0
    if (*pv <= range->rmin)
328
0
        *pv = range->rmin;
329
0
    else if (*pv >= range->rmax)
330
0
        *pv = range->rmax;
331
0
}
332
333
void
334
gx_restrict_CIEDEFG(gs_client_color * pcc, const gs_color_space * pcs)
335
0
{
336
0
    const gs_cie_defg *pcie = pcs->params.defg;
337
338
0
    cie_restrict(&pcc->paint.values[0], &pcie->RangeDEFG.ranges[0]);
339
0
    cie_restrict(&pcc->paint.values[1], &pcie->RangeDEFG.ranges[1]);
340
0
    cie_restrict(&pcc->paint.values[2], &pcie->RangeDEFG.ranges[2]);
341
0
    cie_restrict(&pcc->paint.values[3], &pcie->RangeDEFG.ranges[3]);
342
0
}
343
void
344
gx_restrict_CIEDEF(gs_client_color * pcc, const gs_color_space * pcs)
345
0
{
346
0
    const gs_cie_def *pcie = pcs->params.def;
347
348
0
    cie_restrict(&pcc->paint.values[0], &pcie->RangeDEF.ranges[0]);
349
0
    cie_restrict(&pcc->paint.values[1], &pcie->RangeDEF.ranges[1]);
350
0
    cie_restrict(&pcc->paint.values[2], &pcie->RangeDEF.ranges[2]);
351
0
}
352
void
353
gx_restrict_CIEABC(gs_client_color * pcc, const gs_color_space * pcs)
354
0
{
355
0
    const gs_cie_abc *pcie = pcs->params.abc;
356
357
0
    cie_restrict(&pcc->paint.values[0], &pcie->RangeABC.ranges[0]);
358
0
    cie_restrict(&pcc->paint.values[1], &pcie->RangeABC.ranges[1]);
359
0
    cie_restrict(&pcc->paint.values[2], &pcie->RangeABC.ranges[2]);
360
0
}
361
void
362
gx_restrict_CIEA(gs_client_color * pcc, const gs_color_space * pcs)
363
0
{
364
0
    const gs_cie_a *pcie = pcs->params.a;
365
366
0
    cie_restrict(&pcc->paint.values[0], &pcie->RangeA);
367
0
}
368
369
/* ================ Table setup ================ */
370
371
/* ------ Install a CIE color space ------ */
372
373
static void cie_cache_mult(gx_cie_vector_cache *, const gs_vector3 *,
374
                            const cie_cache_floats *, double);
375
static bool cie_cache_mult3(gx_cie_vector_cache3_t *,
376
                             const gs_matrix3 *, double);
377
378
int
379
gx_install_cie_abc(gs_cie_abc *pcie, gs_gstate * pgs)
380
0
{
381
0
    if_debug_matrix3("[c]CIE MatrixABC =", &pcie->MatrixABC);
382
0
    cie_matrix_init(&pcie->MatrixABC);
383
0
    CIE_LOAD_CACHE_BODY(pcie->caches.DecodeABC.caches, pcie->RangeABC.ranges,
384
0
                        &pcie->DecodeABC, DecodeABC_default, pcie,
385
0
                        "DecodeABC");
386
0
    gx_cie_load_common_cache(&pcie->common, pgs);
387
0
    gs_cie_abc_complete(pcie);
388
0
    return gs_cie_cs_complete(pgs, true);
389
0
}
390
391
int
392
gx_install_CIEDEFG(gs_color_space * pcs, gs_gstate * pgs)
393
0
{
394
0
    gs_cie_defg *pcie = pcs->params.defg;
395
396
0
    CIE_LOAD_CACHE_BODY(pcie->caches_defg.DecodeDEFG, pcie->RangeDEFG.ranges,
397
0
                        &pcie->DecodeDEFG, DecodeDEFG_default, pcie,
398
0
                        "DecodeDEFG");
399
0
    return gx_install_cie_abc((gs_cie_abc *)pcie, pgs);
400
0
}
401
402
int
403
gx_install_CIEDEF(gs_color_space * pcs, gs_gstate * pgs)
404
0
{
405
0
    gs_cie_def *pcie = pcs->params.def;
406
407
0
    CIE_LOAD_CACHE_BODY(pcie->caches_def.DecodeDEF, pcie->RangeDEF.ranges,
408
0
                        &pcie->DecodeDEF, DecodeDEF_default, pcie,
409
0
                        "DecodeDEF");
410
0
    return gx_install_cie_abc((gs_cie_abc *)pcie, pgs);
411
0
}
412
413
int
414
gx_install_CIEABC(gs_color_space * pcs, gs_gstate * pgs)
415
0
{
416
0
    return gx_install_cie_abc(pcs->params.abc, pgs);
417
0
}
418
419
int
420
gx_install_CIEA(gs_color_space * pcs, gs_gstate * pgs)
421
0
{
422
0
    gs_cie_a *pcie = pcs->params.a;
423
0
    gs_sample_loop_params_t lp;
424
0
    int i;
425
426
0
    gs_cie_cache_init(&pcie->caches.DecodeA.floats.params, &lp,
427
0
                      &pcie->RangeA, "DecodeA");
428
0
    for (i = 0; i <= lp.N; ++i) {
429
0
        float in = SAMPLE_LOOP_VALUE(i, lp);
430
431
0
        pcie->caches.DecodeA.floats.values[i] = (*pcie->DecodeA)(in, pcie);
432
0
        if_debug3m('C', pgs->memory, "[C]DecodeA[%d] = %g => %g\n",
433
0
                   i, in, pcie->caches.DecodeA.floats.values[i]);
434
0
    }
435
0
    gx_cie_load_common_cache(&pcie->common, pgs);
436
0
    gs_cie_a_complete(pcie);
437
0
    return gs_cie_cs_complete(pgs, true);
438
0
}
439
440
/* Load the common caches when installing the color space. */
441
/* This routine is exported for the benefit of gsicc.c */
442
void
443
gx_cie_load_common_cache(gs_cie_common * pcie, gs_gstate * pgs)
444
0
{
445
0
    if_debug_matrix3("[c]CIE MatrixLMN =", &pcie->MatrixLMN);
446
0
    cie_matrix_init(&pcie->MatrixLMN);
447
0
    CIE_LOAD_CACHE_BODY(pcie->caches.DecodeLMN, pcie->RangeLMN.ranges,
448
0
                        &pcie->DecodeLMN, DecodeLMN_default, pcie,
449
0
                        "DecodeLMN");
450
0
}
451
452
/* Complete loading the common caches. */
453
/* This routine is exported for the benefit of gsicc.c */
454
void
455
gx_cie_common_complete(gs_cie_common *pcie)
456
0
{
457
0
    int i;
458
459
0
    for (i = 0; i < 3; ++i)
460
0
        cache_set_linear(&pcie->caches.DecodeLMN[i].floats);
461
0
}
462
463
/*
464
 * Restrict the DecodeDEF[G] cache according to RangeHIJ[K], and scale to
465
 * the dimensions of Table.
466
 */
467
static void
468
gs_cie_defx_scale(float *values, const gs_range *range, int dim)
469
0
{
470
0
    double scale = (dim - 1.0) / (range->rmax - range->rmin);
471
0
    int i;
472
473
0
    for (i = 0; i < gx_cie_cache_size; ++i) {
474
0
        float value = values[i];
475
476
0
        values[i] =
477
0
            (value <= range->rmin ? 0 :
478
0
             value >= range->rmax ? dim - 1 :
479
0
             (value - range->rmin) * scale);
480
0
    }
481
0
}
482
483
/* Complete loading a CIEBasedDEFG color space. */
484
/* This routine is NOT idempotent. */
485
void
486
gs_cie_defg_complete(gs_cie_defg * pcie)
487
0
{
488
0
    int j;
489
490
0
    for (j = 0; j < 4; ++j)
491
0
        gs_cie_defx_scale(pcie->caches_defg.DecodeDEFG[j].floats.values,
492
0
                          &pcie->RangeHIJK.ranges[j], pcie->Table.dims[j]);
493
0
    gs_cie_abc_complete((gs_cie_abc *)pcie);
494
0
}
495
496
/* Complete loading a CIEBasedDEF color space. */
497
/* This routine is NOT idempotent. */
498
void
499
gs_cie_def_complete(gs_cie_def * pcie)
500
0
{
501
0
    int j;
502
503
0
    for (j = 0; j < 3; ++j)
504
0
        gs_cie_defx_scale(pcie->caches_def.DecodeDEF[j].floats.values,
505
0
                          &pcie->RangeHIJ.ranges[j], pcie->Table.dims[j]);
506
0
    gs_cie_abc_complete((gs_cie_abc *)pcie);
507
0
}
508
509
/* Complete loading a CIEBasedABC color space. */
510
/* This routine is idempotent. */
511
void
512
gs_cie_abc_complete(gs_cie_abc * pcie)
513
0
{
514
0
    cache3_set_linear(&pcie->caches.DecodeABC);
515
0
    pcie->caches.skipABC =
516
0
        cie_cache_mult3(&pcie->caches.DecodeABC, &pcie->MatrixABC,
517
0
                        CACHE_THRESHOLD);
518
0
    gx_cie_common_complete((gs_cie_common *)pcie);
519
0
}
520
521
/* Complete loading a CIEBasedA color space. */
522
/* This routine is idempotent. */
523
void
524
gs_cie_a_complete(gs_cie_a * pcie)
525
0
{
526
0
    cie_cache_mult(&pcie->caches.DecodeA, &pcie->MatrixA,
527
0
                   &pcie->caches.DecodeA.floats,
528
0
                   CACHE_THRESHOLD);
529
0
    cache_set_linear(&pcie->caches.DecodeA.floats);
530
0
    gx_cie_common_complete((gs_cie_common *)pcie);
531
0
}
532
533
/*
534
 * Set the ranges where interpolation is required in a vector cache.
535
 * This procedure is idempotent.
536
 */
537
typedef struct cie_cache_range_temp_s {
538
    cie_cached_value prev;
539
    int imin, imax;
540
} cie_cache_range_temp_t;
541
static inline void
542
check_interpolation_required(cie_cache_range_temp_t *pccr,
543
                             cie_cached_value cur, int i, double threshold)
544
411M
{
545
411M
    cie_cached_value prev = pccr->prev;
546
547
411M
    if (cie_cached_abs(cur - prev) > threshold * min(cie_cached_abs(prev), cie_cached_abs(cur))) {
548
34.9M
        if (i - 1 < pccr->imin)
549
267k
            pccr->imin = i - 1;
550
34.9M
        if (i > pccr->imax)
551
34.9M
            pccr->imax = i;
552
34.9M
    }
553
411M
    pccr->prev = cur;
554
411M
}
555
static void
556
cie_cache_set_interpolation(gx_cie_vector_cache *pcache, double threshold)
557
267k
{
558
267k
    cie_cached_value base = pcache->vecs.params.base;
559
267k
    cie_cached_value factor = pcache->vecs.params.factor;
560
267k
    cie_cache_range_temp_t temp[3];
561
267k
    int i, j;
562
563
1.07M
    for (j = 0; j < 3; ++j)
564
803k
        temp[j].imin = gx_cie_cache_size, temp[j].imax = -1;
565
267k
    temp[0].prev = pcache->vecs.values[0].u;
566
267k
    temp[1].prev = pcache->vecs.values[0].v;
567
267k
    temp[2].prev = pcache->vecs.values[0].w;
568
569
137M
    for (i = 0; i < gx_cie_cache_size; ++i) {
570
137M
        check_interpolation_required(&temp[0], pcache->vecs.values[i].u, i,
571
137M
                                     threshold);
572
137M
        check_interpolation_required(&temp[1], pcache->vecs.values[i].v, i,
573
137M
                                     threshold);
574
137M
        check_interpolation_required(&temp[2], pcache->vecs.values[i].w, i,
575
137M
                                     threshold);
576
137M
    }
577
578
1.07M
    for (j = 0; j < 3; ++j) {
579
803k
        pcache->vecs.params.interpolation_ranges[j].rmin =
580
803k
            base + (cie_cached_value)((double)temp[j].imin / factor);
581
803k
        pcache->vecs.params.interpolation_ranges[j].rmax =
582
803k
            base + (cie_cached_value)((double)temp[j].imax / factor);
583
803k
        if_debug3('c', "[c]interpolation_ranges[%d] = %g, %g\n", j,
584
803k
                  cie_cached2float(pcache->vecs.params.interpolation_ranges[j].rmin),
585
803k
                  cie_cached2float(pcache->vecs.params.interpolation_ranges[j].rmax));
586
803k
    }
587
588
267k
}
589
590
/*
591
 * Convert a scalar cache to a vector cache by multiplying the scalar
592
 * values by a vector.  Also set the range where interpolation is needed.
593
 * This procedure is idempotent.
594
 */
595
static void
596
cie_cache_mult(gx_cie_vector_cache * pcache, const gs_vector3 * pvec,
597
               const cie_cache_floats * pcf, double threshold)
598
267k
{
599
267k
    float u = pvec->u, v = pvec->v, w = pvec->w;
600
267k
    int i;
601
602
267k
    pcache->vecs.params.base = float2cie_cached(pcf->params.base);
603
267k
    pcache->vecs.params.factor = float2cie_cached(pcf->params.factor);
604
267k
    pcache->vecs.params.limit =
605
267k
        float2cie_cached((gx_cie_cache_size - 1) / pcf->params.factor +
606
267k
                         pcf->params.base);
607
137M
    for (i = 0; i < gx_cie_cache_size; ++i) {
608
137M
        float f = pcf->values[i];
609
610
137M
        pcache->vecs.values[i].u = float2cie_cached(f * u);
611
137M
        pcache->vecs.values[i].v = float2cie_cached(f * v);
612
137M
        pcache->vecs.values[i].w = float2cie_cached(f * w);
613
137M
    }
614
267k
    cie_cache_set_interpolation(pcache, threshold);
615
267k
}
616
617
/*
618
 * Set the interpolation ranges in a 3-vector cache, based on the ranges in
619
 * the individual vector caches.  This procedure is idempotent.
620
 */
621
static void
622
cie_cache3_set_interpolation(gx_cie_vector_cache3_t * pvc)
623
89.2k
{
624
89.2k
    int j, k;
625
626
    /* Iterate over output components. */
627
357k
    for (j = 0; j < 3; ++j) {
628
        /* Iterate over sub-caches. */
629
267k
        cie_interpolation_range_t *p =
630
267k
                &pvc->caches[0].vecs.params.interpolation_ranges[j];
631
267k
        cie_cached_value rmin = p->rmin, rmax = p->rmax;
632
633
803k
        for (k = 1; k < 3; ++k) {
634
535k
            p = &pvc->caches[k].vecs.params.interpolation_ranges[j];
635
535k
            rmin = min(rmin, p->rmin), rmax = max(rmax, p->rmax);
636
535k
        }
637
267k
        pvc->interpolation_ranges[j].rmin = rmin;
638
267k
        pvc->interpolation_ranges[j].rmax = rmax;
639
267k
        if_debug3('c', "[c]Merged interpolation_ranges[%d] = %g, %g\n",
640
267k
                  j, rmin, rmax);
641
267k
    }
642
89.2k
}
643
644
/*
645
 * Convert 3 scalar caches to vector caches by multiplying by a matrix.
646
 * Return true iff the resulting cache is an identity transformation.
647
 * This procedure is idempotent.
648
 */
649
static bool
650
cie_cache_mult3(gx_cie_vector_cache3_t * pvc, const gs_matrix3 * pmat,
651
                double threshold)
652
89.2k
{
653
89.2k
    cie_cache_mult(&pvc->caches[0], &pmat->cu, &pvc->caches[0].floats, threshold);
654
89.2k
    cie_cache_mult(&pvc->caches[1], &pmat->cv, &pvc->caches[1].floats, threshold);
655
89.2k
    cie_cache_mult(&pvc->caches[2], &pmat->cw, &pvc->caches[2].floats, threshold);
656
89.2k
    cie_cache3_set_interpolation(pvc);
657
89.2k
    return pmat->is_identity & pvc->caches[0].floats.params.is_identity &
658
89.2k
        pvc->caches[1].floats.params.is_identity &
659
89.2k
        pvc->caches[2].floats.params.is_identity;
660
89.2k
}
661
662
/* ------ Install a rendering dictionary ------ */
663
664
bool
665
vector_equal(const gs_vector3 *p1, const gs_vector3 *p2)
666
0
{
667
0
    if (p1->u != p2->u)
668
0
        return false;
669
0
    if (p1->v != p2->v)
670
0
        return false;
671
0
    if (p1->w != p2->w)
672
0
        return false;
673
0
    return true;
674
0
}
675
676
bool
677
matrix_equal(const gs_matrix3 *p1, const gs_matrix3 *p2)
678
0
{
679
0
    if (p1->is_identity != p2->is_identity)
680
0
        return false;
681
0
    if (!vector_equal(&(p1->cu), &(p2->cu)))
682
0
        return false;
683
0
    if (!vector_equal(&(p1->cv), &(p2->cv)))
684
0
        return false;
685
0
    if (!vector_equal(&(p1->cw), &(p2->cw)))
686
0
        return false;
687
0
    return true;
688
0
}
689
690
static bool
691
transform_equal(const gs_cie_transform_proc3 *p1, const gs_cie_transform_proc3 *p2)
692
0
{
693
0
    if (p1->proc != p2->proc)
694
0
        return false;
695
0
    if (p1->proc_data.size != p2->proc_data.size)
696
0
        return false;
697
0
    if (memcmp(p1->proc_data.data, p2->proc_data.data, p1->proc_data.size) != 0)
698
0
        return false;
699
0
    if (p1->driver_name != p2->driver_name)
700
0
        return false;
701
0
    if (p1->proc_name != p2->proc_name)
702
0
        return false;
703
0
    return true;
704
0
}
705
706
bool
707
range_equal(const gs_range3 *p1, const gs_range3 *p2)
708
0
{
709
0
    int k;
710
711
0
    for (k = 0; k < 3; k++) {
712
0
        if (p1->ranges[k].rmax != p2->ranges[k].rmax)
713
0
            return false;
714
0
        if (p1->ranges[k].rmin != p2->ranges[k].rmin)
715
0
            return false;
716
0
    }
717
0
    return true;
718
0
}
719
720
/* setcolorrendering */
721
int
722
gs_setcolorrendering(gs_gstate * pgs, gs_cie_render * pcrd)
723
89.2k
{
724
89.2k
    int code = gs_cie_render_complete(pcrd);
725
89.2k
    const gs_cie_render *pcrd_old = pgs->cie_render;
726
89.2k
    bool joint_ok;
727
728
89.2k
    if (code < 0)
729
0
        return code;
730
89.2k
    if (pcrd_old != 0 && pcrd->id == pcrd_old->id)
731
0
        return 0;   /* detect needless reselecting */
732
89.2k
    joint_ok =
733
89.2k
        pcrd_old != 0 &&
734
89.2k
        vector_equal(&pcrd->points.WhitePoint, &pcrd_old->points.WhitePoint) &&
735
89.2k
        vector_equal(&pcrd->points.BlackPoint, &pcrd_old->points.BlackPoint) &&
736
89.2k
        matrix_equal(&pcrd->MatrixPQR, &pcrd_old->MatrixPQR) &&
737
89.2k
        range_equal(&pcrd->RangePQR, &pcrd_old->RangePQR) &&
738
89.2k
        transform_equal(&pcrd->TransformPQR, &pcrd_old->TransformPQR);
739
89.2k
    rc_assign(pgs->cie_render, pcrd, "gs_setcolorrendering");
740
    /* Initialize the joint caches if needed. */
741
89.2k
    if (!joint_ok)
742
89.2k
        code = gs_cie_cs_complete(pgs, true);
743
89.2k
    gx_unset_dev_color(pgs);
744
89.2k
    return code;
745
89.2k
}
746
747
/* currentcolorrendering */
748
const gs_cie_render *
749
gs_currentcolorrendering(const gs_gstate * pgs)
750
0
{
751
0
    return pgs->cie_render;
752
0
}
753
754
/* Unshare (allocating if necessary) the joint caches. */
755
gx_cie_joint_caches *
756
gx_unshare_cie_caches(gs_gstate * pgs)
757
89.2k
{
758
89.2k
    gx_cie_joint_caches *pjc = pgs->cie_joint_caches;
759
760
89.2k
    rc_unshare_struct(pgs->cie_joint_caches, gx_cie_joint_caches,
761
89.2k
                      &st_joint_caches, pgs->memory,
762
89.2k
                      return 0, "gx_unshare_cie_caches");
763
89.2k
    if (pgs->cie_joint_caches != pjc) {
764
89.2k
        pjc = pgs->cie_joint_caches;
765
89.2k
        pjc->cspace_id = pjc->render_id = gs_no_id;
766
89.2k
        pjc->id_status = pjc->status = CIE_JC_STATUS_BUILT;
767
89.2k
    }
768
89.2k
    return pjc;
769
89.2k
}
770
771
gx_cie_joint_caches *
772
gx_get_cie_caches_ref(gs_gstate * pgs, gs_memory_t * mem)
773
0
{
774
0
    gx_cie_joint_caches *pjc = pgs->cie_joint_caches;
775
776
    /* Take a reference here, to allow for the one that
777
     * rc_unshare_struct might drop if it has to copy it.
778
     * Whatever happens we will have taken 1 net new
779
     * reference which we return to the caller. */
780
0
    rc_increment(pgs->cie_joint_caches);
781
0
    rc_unshare_struct(pjc, gx_cie_joint_caches,
782
0
                      &st_joint_caches, mem,
783
0
                      return NULL, "gx_unshare_cie_caches");
784
0
    return pjc;
785
0
}
786
787
/* Compute the parameters for loading a cache, setting base and factor. */
788
/* This procedure is idempotent. */
789
void
790
gs_cie_cache_init(cie_cache_params * pcache, gs_sample_loop_params_t * pslp,
791
                  const gs_range * domain, client_name_t cname)
792
535k
{
793
    /*
794
      We need to map the values in the range [domain->rmin..domain->rmax].
795
      However, if rmin < 0 < rmax and the function is non-linear, this can
796
      lead to anomalies at zero, which is the default value for CIE colors.
797
      The "correct" way to approach this is to run the mapping functions on
798
      demand, but we don't want to deal with the complexities of the
799
      callbacks this would involve (especially in the middle of rendering
800
      images); instead, we adjust the range so that zero maps precisely to a
801
      cache slot.  Define:
802
803
      A = domain->rmin;
804
      B = domain->rmax;
805
      N = gx_cie_cache_size - 1;
806
807
      R = B - A;
808
      h(v) = N * (v - A) / R;   // the index of v in the cache
809
      X = h(0).
810
811
      If X is not an integer, we can decrease A and/increase B to make it
812
      one.  Let A' and B' be the adjusted values of A and B respectively,
813
      and let K be the integer derived from X (either floor(X) or ceil(X)).
814
      Define
815
816
      f(K) = (K * B' + (N - K) * A') / N).
817
818
      We want f(K) = 0.  This occurs precisely when, for any real number
819
      C != 0,
820
821
      A' = -K * C;
822
      B' = (N - K) * C.
823
824
      In order to ensure A' <= A and B' >= B, we require
825
826
      C >= -A / K;
827
      C >= B / (N - K).
828
829
      Since A' and B' must be exactly representable as floats, we round C
830
      upward to ensure that it has no more than M mantissa bits, where
831
832
      M = ARCH_FLOAT_MANTISSA_BITS - ceil(log2(N)).
833
    */
834
535k
    float A = domain->rmin, B = domain->rmax;
835
535k
    double R = B - A, delta;
836
2.40M
#define NN (gx_cie_cache_size - 1) /* 'N' is a member name, see end of proc */
837
1.87M
#define N NN
838
535k
#define CEIL_LOG2_N CIE_LOG2_CACHE_SIZE
839
840
    /* Adjust the range if necessary. */
841
535k
    if (A < 0 && B >= 0) {
842
267k
        const double X = -N * A / R; /* know X > 0 */
843
        /* Choose K to minimize range expansion. */
844
267k
        const int K = (int)(A + B < 0 ? floor(X) : ceil(X)); /* know 0 < K < N */
845
267k
        const double Ca = -A / K, Cb = B / (N - K); /* know Ca, Cb > 0 */
846
267k
        double C = max(Ca, Cb); /* know C > 0 */
847
267k
        const int M = ARCH_FLOAT_MANTISSA_BITS - CEIL_LOG2_N;
848
267k
        int cexp;
849
267k
        const double cfrac = frexp(C, &cexp);
850
851
267k
        if_debug4('c', "[c]adjusting cache_init(%8g, %8g), X = %8g, K = %d:\n",
852
267k
                  A, B, X, K);
853
        /* Round C to no more than M significant bits.  See above. */
854
267k
        C = ldexp(ceil(ldexp(cfrac, M)), cexp - M);
855
        /* Finally, compute A' and B'. */
856
267k
        A = -K * C;
857
267k
        B = (N - K) * C;
858
267k
        if_debug2('c', "[c]  => %8g, %8g\n", A, B);
859
267k
        R = B - A;
860
267k
    }
861
535k
    delta = R / N;
862
535k
#ifdef CIE_CACHE_INTERPOLATE
863
535k
    pcache->base = A;   /* no rounding */
864
#else
865
    pcache->base = A - delta / 2; /* so lookup will round */
866
#endif
867
    /*
868
     * If size of the domain is zero, then use 1.0 as the scaling
869
     * factor.  This prevents divide by zero errors in later calculations.
870
     * This should only occurs with zero matrices.  It does occur with
871
     * Genoa test file 050-01.ps.
872
     */
873
535k
    pcache->factor = (any_abs(delta) < 1e-30 ? 1.0 : N / R);
874
535k
    if_debug4('c', "[c]cache %s "PRI_INTPTR" base=%g, factor=%g\n",
875
535k
              (const char *)cname, (intptr_t)pcache,
876
535k
              pcache->base, pcache->factor);
877
535k
    pslp->A = A;
878
535k
    pslp->B = B;
879
535k
#undef N
880
535k
    pslp->N = NN;
881
535k
#undef NN
882
535k
}
883
884
/* ------ Complete a rendering structure ------ */
885
886
/*
887
 * Compute the derived values in a CRD that don't involve the cached
888
 * procedure values.  This procedure is idempotent.
889
 */
890
static void cie_transform_range3(const gs_range3 *, const gs_matrix3 *,
891
                                  gs_range3 *);
892
int
893
gs_cie_render_init(gs_cie_render * pcrd)
894
89.2k
{
895
89.2k
    gs_matrix3 PQR_inverse;
896
897
89.2k
    if (pcrd->status >= CIE_RENDER_STATUS_INITED)
898
0
        return 0;   /* init already done */
899
89.2k
    if_debug_matrix3("[c]CRD MatrixLMN =", &pcrd->MatrixLMN);
900
89.2k
    cie_matrix_init(&pcrd->MatrixLMN);
901
89.2k
    if_debug_matrix3("[c]CRD MatrixABC =", &pcrd->MatrixABC);
902
89.2k
    cie_matrix_init(&pcrd->MatrixABC);
903
89.2k
    if_debug_matrix3("[c]CRD MatrixPQR =", &pcrd->MatrixPQR);
904
89.2k
    cie_matrix_init(&pcrd->MatrixPQR);
905
89.2k
    cie_invert3(&pcrd->MatrixPQR, &PQR_inverse);
906
89.2k
    cie_matrix_mult3(&pcrd->MatrixLMN, &PQR_inverse,
907
89.2k
                     &pcrd->MatrixPQR_inverse_LMN);
908
89.2k
    cie_transform_range3(&pcrd->RangePQR, &pcrd->MatrixPQR_inverse_LMN,
909
89.2k
                         &pcrd->DomainLMN);
910
89.2k
    cie_transform_range3(&pcrd->RangeLMN, &pcrd->MatrixABC,
911
89.2k
                         &pcrd->DomainABC);
912
89.2k
    cie_mult3(&pcrd->points.WhitePoint, &pcrd->MatrixPQR, &pcrd->wdpqr);
913
89.2k
    cie_mult3(&pcrd->points.BlackPoint, &pcrd->MatrixPQR, &pcrd->bdpqr);
914
89.2k
    pcrd->status = CIE_RENDER_STATUS_INITED;
915
89.2k
    return 0;
916
89.2k
}
917
918
/*
919
 * Sample the EncodeLMN, EncodeABC, and RenderTableT CRD procedures, and
920
 * load the caches.  This procedure is idempotent.
921
 */
922
int
923
gs_cie_render_sample(gs_cie_render * pcrd)
924
89.2k
{
925
89.2k
    int code;
926
927
89.2k
    if (pcrd->status >= CIE_RENDER_STATUS_SAMPLED)
928
0
        return 0;   /* sampling already done */
929
89.2k
    code = gs_cie_render_init(pcrd);
930
89.2k
    if (code < 0)
931
0
        return code;
932
89.2k
    CIE_LOAD_CACHE_BODY(pcrd->caches.EncodeLMN.caches, pcrd->DomainLMN.ranges,
933
89.2k
                        &pcrd->EncodeLMN, Encode_default, pcrd, "EncodeLMN");
934
89.2k
    cache3_set_linear(&pcrd->caches.EncodeLMN);
935
89.2k
    CIE_LOAD_CACHE_BODY(pcrd->caches.EncodeABC, pcrd->DomainABC.ranges,
936
89.2k
                        &pcrd->EncodeABC, Encode_default, pcrd, "EncodeABC");
937
89.2k
    if (pcrd->RenderTable.lookup.table != 0) {
938
0
        int i, j, m = pcrd->RenderTable.lookup.m;
939
0
        gs_sample_loop_params_t lp;
940
0
        bool is_identity = true;
941
942
0
        for (j = 0; j < m; j++) {
943
0
            gs_cie_cache_init(&pcrd->caches.RenderTableT[j].fracs.params,
944
0
                              &lp, &Range3_default.ranges[0],
945
0
                              "RenderTableT");
946
0
            is_identity &= pcrd->RenderTable.T.procs[j] ==
947
0
                RenderTableT_default.procs[j];
948
0
        }
949
0
        pcrd->caches.RenderTableT_is_identity = is_identity;
950
        /*
951
         * Unfortunately, we defined the first argument of the RenderTable
952
         * T procedures as being a byte, limiting the number of distinct
953
         * cache entries to 256 rather than gx_cie_cache_size.
954
         * We confine this decision to this loop, rather than propagating
955
         * it to the procedures that use the cached data, so that we can
956
         * change it more easily at some future time.
957
         */
958
0
        for (i = 0; i < gx_cie_cache_size; i++) {
959
0
#if gx_cie_log2_cache_size >= 8
960
0
            byte value = i >> (gx_cie_log2_cache_size - 8);
961
#else
962
            byte value = (i << (8 - gx_cie_log2_cache_size)) +
963
                (i >> (gx_cie_log2_cache_size * 2 - 8));
964
#endif
965
0
            for (j = 0; j < m; j++) {
966
0
                pcrd->caches.RenderTableT[j].fracs.values[i] =
967
0
                    (*pcrd->RenderTable.T.procs[j])(value, pcrd);
968
0
                if_debug3('C', "[C]RenderTableT[%d,%d] = %g\n",
969
0
                          i, j,
970
0
                          frac2float(pcrd->caches.RenderTableT[j].fracs.values[i]));
971
0
            }
972
0
        }
973
0
    }
974
89.2k
    pcrd->status = CIE_RENDER_STATUS_SAMPLED;
975
89.2k
    return 0;
976
89.2k
}
977
978
/* Transform a set of ranges. */
979
static void
980
cie_transform_range(const gs_range3 * in, double mu, double mv, double mw,
981
                    gs_range * out)
982
535k
{
983
535k
    float umin = mu * in->ranges[0].rmin, umax = mu * in->ranges[0].rmax;
984
535k
    float vmin = mv * in->ranges[1].rmin, vmax = mv * in->ranges[1].rmax;
985
535k
    float wmin = mw * in->ranges[2].rmin, wmax = mw * in->ranges[2].rmax;
986
535k
    float temp;
987
988
535k
    if (umin > umax)
989
178k
        temp = umin, umin = umax, umax = temp;
990
535k
    if (vmin > vmax)
991
178k
        temp = vmin, vmin = vmax, vmax = temp;
992
535k
    if (wmin > wmax)
993
178k
        temp = wmin, wmin = wmax, wmax = temp;
994
535k
    out->rmin = umin + vmin + wmin;
995
535k
    out->rmax = umax + vmax + wmax;
996
535k
}
997
static void
998
cie_transform_range3(const gs_range3 * in, const gs_matrix3 * mat,
999
                     gs_range3 * out)
1000
178k
{
1001
178k
    cie_transform_range(in, mat->cu.u, mat->cv.u, mat->cw.u,
1002
178k
                        &out->ranges[0]);
1003
178k
    cie_transform_range(in, mat->cu.v, mat->cv.v, mat->cw.v,
1004
178k
                        &out->ranges[1]);
1005
178k
    cie_transform_range(in, mat->cu.w, mat->cv.w, mat->cw.w,
1006
178k
                        &out->ranges[2]);
1007
178k
}
1008
1009
/*
1010
 * Finish preparing a CRD for installation, by restricting and/or
1011
 * transforming the cached procedure values.
1012
 * This procedure is idempotent.
1013
 */
1014
int
1015
gs_cie_render_complete(gs_cie_render * pcrd)
1016
89.2k
{
1017
89.2k
    int code;
1018
1019
89.2k
    if (pcrd->status >= CIE_RENDER_STATUS_COMPLETED)
1020
0
        return 0;   /* completion already done */
1021
89.2k
    code = gs_cie_render_sample(pcrd);
1022
89.2k
    if (code < 0)
1023
0
        return code;
1024
    /*
1025
     * Since range restriction happens immediately after
1026
     * the cache lookup, we can save a step by restricting
1027
     * the values in the cache entries.
1028
     *
1029
     * If there is no lookup table, we want the final ABC values
1030
     * to be fracs; if there is a table, we want them to be
1031
     * appropriately scaled ints.
1032
     */
1033
89.2k
    pcrd->MatrixABCEncode = pcrd->MatrixABC;
1034
89.2k
    {
1035
89.2k
        int c;
1036
89.2k
        double f;
1037
1038
357k
        for (c = 0; c < 3; c++) {
1039
267k
            gx_cie_float_fixed_cache *pcache = &pcrd->caches.EncodeABC[c];
1040
1041
267k
            cie_cache_restrict(&pcrd->caches.EncodeLMN.caches[c].floats,
1042
267k
                               &pcrd->RangeLMN.ranges[c]);
1043
267k
            cie_cache_restrict(&pcrd->caches.EncodeABC[c].floats,
1044
267k
                               &pcrd->RangeABC.ranges[c]);
1045
267k
            if (pcrd->RenderTable.lookup.table == 0) {
1046
267k
                cie_cache_restrict(&pcache->floats,
1047
267k
                                   &Range3_default.ranges[0]);
1048
267k
                gs_cie_cache_to_fracs(&pcache->floats, &pcache->fixeds.fracs);
1049
267k
                pcache->fixeds.fracs.params.is_identity = false;
1050
267k
            } else {
1051
0
                int i;
1052
0
                int n = pcrd->RenderTable.lookup.dims[c];
1053
1054
0
#ifdef CIE_RENDER_TABLE_INTERPOLATE
1055
0
#  define SCALED_INDEX(f, n, itemp)\
1056
0
     RESTRICTED_INDEX(f * (1 << _cie_interpolate_bits),\
1057
0
                      (n) << _cie_interpolate_bits, itemp)
1058
#else
1059
                int m = pcrd->RenderTable.lookup.m;
1060
                int k =
1061
                    (c == 0 ? 1 : c == 1 ?
1062
                     m * pcrd->RenderTable.lookup.dims[2] : m);
1063
#  define SCALED_INDEX(f, n, itemp)\
1064
     (RESTRICTED_INDEX(f, n, itemp) * k)
1065
#endif
1066
0
                const gs_range *prange = pcrd->RangeABC.ranges + c;
1067
0
                double scale = (n - 1) / (prange->rmax - prange->rmin);
1068
1069
0
                for (i = 0; i < gx_cie_cache_size; ++i) {
1070
0
                    float v =
1071
0
                        (pcache->floats.values[i] - prange->rmin) * scale
1072
#ifndef CIE_RENDER_TABLE_INTERPOLATE
1073
                        + 0.5
1074
#endif
1075
0
                        ;
1076
0
                    int itemp;
1077
1078
0
                    if_debug5('c',
1079
0
                              "[c]cache[%d][%d] = %g => %g => %d\n",
1080
0
                              c, i, pcache->floats.values[i], v,
1081
0
                              SCALED_INDEX(v, n, itemp));
1082
0
                    pcache->fixeds.ints.values[i] =
1083
0
                        SCALED_INDEX(v, n, itemp);
1084
0
                }
1085
0
                pcache->fixeds.ints.params = pcache->floats.params;
1086
0
                pcache->fixeds.ints.params.is_identity = false;
1087
0
#undef SCALED_INDEX
1088
0
            }
1089
267k
        }
1090
        /* Fold the scaling of the EncodeABC cache index */
1091
        /* into MatrixABC. */
1092
89.2k
#define MABC(i, t)\
1093
267k
  f = pcrd->caches.EncodeABC[i].floats.params.factor;\
1094
267k
  pcrd->MatrixABCEncode.cu.t *= f;\
1095
267k
  pcrd->MatrixABCEncode.cv.t *= f;\
1096
267k
  pcrd->MatrixABCEncode.cw.t *= f;\
1097
267k
  pcrd->EncodeABC_base[i] =\
1098
267k
    float2cie_cached(pcrd->caches.EncodeABC[i].floats.params.base * f)
1099
89.2k
        MABC(0, u);
1100
89.2k
        MABC(1, v);
1101
89.2k
        MABC(2, w);
1102
89.2k
#undef MABC
1103
89.2k
        pcrd->MatrixABCEncode.is_identity = 0;
1104
89.2k
    }
1105
89.2k
    cie_cache_mult3(&pcrd->caches.EncodeLMN, &pcrd->MatrixABCEncode,
1106
89.2k
                    CACHE_THRESHOLD);
1107
89.2k
    pcrd->status = CIE_RENDER_STATUS_COMPLETED;
1108
89.2k
    return 0;
1109
89.2k
}
1110
1111
/* Apply a range restriction to a cache. */
1112
static void
1113
cie_cache_restrict(cie_cache_floats * pcache, const gs_range * prange)
1114
803k
{
1115
803k
    int i;
1116
1117
412M
    for (i = 0; i < gx_cie_cache_size; i++) {
1118
411M
        float v = pcache->values[i];
1119
1120
411M
        if (v < prange->rmin)
1121
43.1M
            pcache->values[i] = prange->rmin;
1122
368M
        else if (v > prange->rmax)
1123
58.9M
            pcache->values[i] = prange->rmax;
1124
411M
    }
1125
803k
}
1126
1127
/* Convert a cache from floats to fracs. */
1128
/* Note that the two may be aliased. */
1129
void
1130
gs_cie_cache_to_fracs(const cie_cache_floats *pfloats, cie_cache_fracs *pfracs)
1131
267k
{
1132
267k
    int i;
1133
1134
    /* Loop from bottom to top so that we don't */
1135
    /* overwrite elements before they're used. */
1136
137M
    for (i = 0; i < gx_cie_cache_size; ++i)
1137
137M
        pfracs->values[i] = float2frac(pfloats->values[i]);
1138
267k
    pfracs->params = pfloats->params;
1139
267k
}
1140
1141
/* ------ Fill in the joint cache ------ */
1142
1143
/* If the current color space is a CIE space, or has a CIE base space, */
1144
/* return a pointer to the common part of the space; otherwise return 0. */
1145
static const gs_cie_common *
1146
cie_cs_common_abc(const gs_color_space *pcs_orig, const gs_cie_abc **ppabc)
1147
89.2k
{
1148
89.2k
    const gs_color_space *pcs = pcs_orig;
1149
1150
89.2k
    *ppabc = 0;
1151
89.2k
    do {
1152
89.2k
        switch (pcs->type->index) {
1153
0
        case gs_color_space_index_CIEDEF:
1154
0
            *ppabc = (const gs_cie_abc *)pcs->params.def;
1155
0
            return &pcs->params.def->common;
1156
0
        case gs_color_space_index_CIEDEFG:
1157
0
            *ppabc = (const gs_cie_abc *)pcs->params.defg;
1158
0
            return &pcs->params.defg->common;
1159
0
        case gs_color_space_index_CIEABC:
1160
0
            *ppabc = pcs->params.abc;
1161
0
            return &pcs->params.abc->common;
1162
0
        case gs_color_space_index_CIEA:
1163
0
            return &pcs->params.a->common;
1164
89.2k
        default:
1165
89.2k
            pcs = gs_cspace_base_space(pcs);
1166
89.2k
            break;
1167
89.2k
        }
1168
89.2k
    } while (pcs != 0);
1169
1170
89.2k
    return 0;
1171
89.2k
}
1172
const gs_cie_common *
1173
gs_cie_cs_common(const gs_gstate * pgs)
1174
89.2k
{
1175
89.2k
    const gs_cie_abc *ignore_pabc;
1176
1177
89.2k
    return cie_cs_common_abc(gs_currentcolorspace_inline(pgs), &ignore_pabc);
1178
89.2k
}
1179
1180
/*
1181
 * Mark the joint caches as needing completion.  This is done lazily,
1182
 * when a color is being mapped.  However, make sure the joint caches
1183
 * exist now.
1184
 */
1185
int
1186
gs_cie_cs_complete(gs_gstate * pgs, bool init)
1187
89.2k
{
1188
89.2k
    gx_cie_joint_caches *pjc = gx_unshare_cie_caches(pgs);
1189
1190
89.2k
    if (pjc == 0)
1191
0
        return_error(gs_error_VMerror);
1192
89.2k
    pjc->status = (init ? CIE_JC_STATUS_BUILT : CIE_JC_STATUS_INITED);
1193
89.2k
    return 0;
1194
89.2k
}
1195
/* Actually complete the joint caches. */
1196
int
1197
gs_cie_jc_complete(const gs_gstate *pgs, const gs_color_space *pcs)
1198
0
{
1199
0
    const gs_cie_abc *pabc;
1200
0
    const gs_cie_common *common = cie_cs_common_abc(pcs, &pabc);
1201
0
    gs_cie_render *pcrd = pgs->cie_render;
1202
0
    gx_cie_joint_caches *pjc = pgs->cie_joint_caches;
1203
1204
0
    if (pjc->cspace_id == pcs->id &&
1205
0
        pjc->render_id == pcrd->id)
1206
0
        pjc->status = pjc->id_status;
1207
0
    switch (pjc->status) {
1208
0
    case CIE_JC_STATUS_BUILT: {
1209
0
        int code = cie_joint_caches_init(pjc, common, pcrd);
1210
1211
0
        if (code < 0)
1212
0
            return code;
1213
0
    }
1214
        /* falls through */
1215
0
    case CIE_JC_STATUS_INITED:
1216
0
        cie_joint_caches_complete(pjc, common, pabc, pcrd);
1217
0
        pjc->cspace_id = pcs->id;
1218
0
        pjc->render_id = pcrd->id;
1219
0
        pjc->id_status = pjc->status = CIE_JC_STATUS_COMPLETED;
1220
        /* falls through */
1221
0
    case CIE_JC_STATUS_COMPLETED:
1222
0
        break;
1223
0
    }
1224
0
    return 0;
1225
0
}
1226
1227
/*
1228
 * Compute the source and destination WhitePoint and BlackPoint for
1229
 * the TransformPQR procedure.
1230
 */
1231
int
1232
gs_cie_compute_points_sd(gx_cie_joint_caches *pjc,
1233
                         const gs_cie_common * pcie,
1234
                         const gs_cie_render * pcrd)
1235
0
{
1236
0
    gs_cie_wbsd *pwbsd = &pjc->points_sd;
1237
1238
0
    pwbsd->ws.xyz = pcie->points.WhitePoint;
1239
0
    cie_mult3(&pwbsd->ws.xyz, &pcrd->MatrixPQR, &pwbsd->ws.pqr);
1240
0
    pwbsd->bs.xyz = pcie->points.BlackPoint;
1241
0
    cie_mult3(&pwbsd->bs.xyz, &pcrd->MatrixPQR, &pwbsd->bs.pqr);
1242
0
    pwbsd->wd.xyz = pcrd->points.WhitePoint;
1243
0
    pwbsd->wd.pqr = pcrd->wdpqr;
1244
0
    pwbsd->bd.xyz = pcrd->points.BlackPoint;
1245
0
    pwbsd->bd.pqr = pcrd->bdpqr;
1246
0
    return 0;
1247
0
}
1248
1249
/*
1250
 * Sample the TransformPQR procedure for the joint caches.
1251
 * This routine is idempotent.
1252
 */
1253
static int
1254
cie_joint_caches_init(gx_cie_joint_caches * pjc,
1255
                      const gs_cie_common * pcie,
1256
                      gs_cie_render * pcrd)
1257
0
{
1258
0
    bool is_identity;
1259
0
    int j;
1260
1261
0
    gs_cie_compute_points_sd(pjc, pcie, pcrd);
1262
    /*
1263
     * If a client pre-loaded the cache, we can't adjust the range.
1264
     * ****** WRONG ******
1265
     */
1266
0
    if (pcrd->TransformPQR.proc == TransformPQR_from_cache.proc)
1267
0
        return 0;
1268
0
    is_identity = pcrd->TransformPQR.proc == TransformPQR_default.proc;
1269
0
    for (j = 0; j < 3; j++) {
1270
0
        int i;
1271
0
        gs_sample_loop_params_t lp;
1272
1273
0
        gs_cie_cache_init(&pjc->TransformPQR.caches[j].floats.params, &lp,
1274
0
                          &pcrd->RangePQR.ranges[j], "TransformPQR");
1275
0
        for (i = 0; i <= lp.N; ++i) {
1276
0
            float in = SAMPLE_LOOP_VALUE(i, lp);
1277
0
            float out;
1278
0
            int code = (*pcrd->TransformPQR.proc)(j, in, &pjc->points_sd,
1279
0
                                                  pcrd, &out);
1280
1281
0
            if (code < 0)
1282
0
                return code;
1283
0
            pjc->TransformPQR.caches[j].floats.values[i] = out;
1284
0
            if_debug4('C', "[C]TransformPQR[%d,%d] = %g => %g\n",
1285
0
                      j, i, in, out);
1286
0
        }
1287
0
        pjc->TransformPQR.caches[j].floats.params.is_identity = is_identity;
1288
0
    }
1289
0
    return 0;
1290
0
}
1291
1292
/*
1293
 * Complete the loading of the joint caches.
1294
 * This routine is idempotent.
1295
 */
1296
static void
1297
cie_joint_caches_complete(gx_cie_joint_caches * pjc,
1298
                          const gs_cie_common * pcie,
1299
                          const gs_cie_abc * pabc /* NULL if CIEA */,
1300
                          const gs_cie_render * pcrd)
1301
0
{
1302
0
    gs_matrix3 mat3, mat2;
1303
0
    gs_matrix3 MatrixLMN_PQR;
1304
0
    int j;
1305
1306
0
    pjc->remap_finish = gx_cie_real_remap_finish;
1307
1308
    /*
1309
     * We number the pipeline steps as follows:
1310
     *   1 - DecodeABC/MatrixABC
1311
     *   2 - DecodeLMN/MatrixLMN/MatrixPQR
1312
     *   3 - TransformPQR/MatrixPQR'/MatrixLMN
1313
     *   4 - EncodeLMN/MatrixABC
1314
     *   5 - EncodeABC, RenderTable (we don't do anything with this here)
1315
     * We work from back to front, combining steps where possible.
1316
     * Currently we only combine steps if a procedure is the identity
1317
     * transform, but we could do it whenever the procedure is linear.
1318
     * A project for another day....
1319
     */
1320
1321
        /* Step 4 */
1322
1323
0
#ifdef OPTIMIZE_CIE_MAPPING
1324
0
    if (pcrd->caches.EncodeLMN.caches[0].floats.params.is_identity &&
1325
0
        pcrd->caches.EncodeLMN.caches[1].floats.params.is_identity &&
1326
0
        pcrd->caches.EncodeLMN.caches[2].floats.params.is_identity
1327
0
        ) {
1328
        /* Fold step 4 into step 3. */
1329
0
        if_debug0('c', "[c]EncodeLMN is identity, folding MatrixABC(Encode) into MatrixPQR'+LMN.\n");
1330
0
        cie_matrix_mult3(&pcrd->MatrixABCEncode, &pcrd->MatrixPQR_inverse_LMN,
1331
0
                         &mat3);
1332
0
        pjc->skipEncodeLMN = true;
1333
0
    } else
1334
0
#endif /* OPTIMIZE_CIE_MAPPING */
1335
0
    {
1336
0
        if_debug0('c', "[c]EncodeLMN is not identity.\n");
1337
0
        mat3 = pcrd->MatrixPQR_inverse_LMN;
1338
0
        pjc->skipEncodeLMN = false;
1339
0
    }
1340
1341
        /* Step 3 */
1342
1343
0
    cache3_set_linear(&pjc->TransformPQR);
1344
0
    cie_matrix_mult3(&pcrd->MatrixPQR, &pcie->MatrixLMN,
1345
0
                     &MatrixLMN_PQR);
1346
1347
0
#ifdef OPTIMIZE_CIE_MAPPING
1348
0
    if (pjc->TransformPQR.caches[0].floats.params.is_identity &
1349
0
        pjc->TransformPQR.caches[1].floats.params.is_identity &
1350
0
        pjc->TransformPQR.caches[2].floats.params.is_identity
1351
0
        ) {
1352
        /* Fold step 3 into step 2. */
1353
0
        if_debug0('c', "[c]TransformPQR is identity, folding MatrixPQR'+LMN into MatrixLMN+PQR.\n");
1354
0
        cie_matrix_mult3(&mat3, &MatrixLMN_PQR, &mat2);
1355
0
        pjc->skipPQR = true;
1356
0
    } else
1357
0
#endif /* OPTIMIZE_CIE_MAPPING */
1358
0
    {
1359
0
        if_debug0('c', "[c]TransformPQR is not identity.\n");
1360
0
        mat2 = MatrixLMN_PQR;
1361
0
        for (j = 0; j < 3; j++) {
1362
0
            cie_cache_restrict(&pjc->TransformPQR.caches[j].floats,
1363
0
                               &pcrd->RangePQR.ranges[j]);
1364
0
        }
1365
0
        cie_cache_mult3(&pjc->TransformPQR, &mat3, CACHE_THRESHOLD);
1366
0
        pjc->skipPQR = false;
1367
0
    }
1368
1369
        /* Steps 2 & 1 */
1370
1371
0
#ifdef OPTIMIZE_CIE_MAPPING
1372
0
    if (pcie->caches.DecodeLMN[0].floats.params.is_identity &
1373
0
        pcie->caches.DecodeLMN[1].floats.params.is_identity &
1374
0
        pcie->caches.DecodeLMN[2].floats.params.is_identity
1375
0
        ) {
1376
0
        if_debug0('c', "[c]DecodeLMN is identity, folding MatrixLMN+PQR into MatrixABC.\n");
1377
0
        if (!pabc) {
1378
0
            pjc->skipDecodeLMN = mat2.is_identity;
1379
0
            pjc->skipDecodeABC = false;
1380
0
            if (!pjc->skipDecodeLMN) {
1381
0
                for (j = 0; j < 3; j++) {
1382
0
                    cie_cache_mult(&pjc->DecodeLMN.caches[j], &mat2.cu + j,
1383
0
                                   &pcie->caches.DecodeLMN[j].floats,
1384
0
                                   CACHE_THRESHOLD);
1385
0
                }
1386
0
                cie_cache3_set_interpolation(&pjc->DecodeLMN);
1387
0
            }
1388
0
        } else {
1389
            /*
1390
             * Fold step 2 into step 1.  This is a little different because
1391
             * the data for step 1 are in the color space structure.
1392
             */
1393
0
            gs_matrix3 mat1;
1394
1395
0
            cie_matrix_mult3(&mat2, &pabc->MatrixABC, &mat1);
1396
0
            for (j = 0; j < 3; j++) {
1397
0
                cie_cache_mult(&pjc->DecodeLMN.caches[j], &mat1.cu + j,
1398
0
                               &pabc->caches.DecodeABC.caches[j].floats,
1399
0
                               CACHE_THRESHOLD);
1400
0
            }
1401
0
            cie_cache3_set_interpolation(&pjc->DecodeLMN);
1402
0
            pjc->skipDecodeLMN = false;
1403
0
            pjc->skipDecodeABC = true;
1404
0
        }
1405
0
    } else
1406
0
#endif /* OPTIMIZE_CIE_MAPPING */
1407
0
    {
1408
0
        if_debug0('c', "[c]DecodeLMN is not identity.\n");
1409
0
        for (j = 0; j < 3; j++) {
1410
0
            cie_cache_mult(&pjc->DecodeLMN.caches[j], &mat2.cu + j,
1411
0
                           &pcie->caches.DecodeLMN[j].floats,
1412
0
                           CACHE_THRESHOLD);
1413
0
        }
1414
0
        cie_cache3_set_interpolation(&pjc->DecodeLMN);
1415
0
        pjc->skipDecodeLMN = false;
1416
0
        pjc->skipDecodeABC = pabc != 0 && pabc->caches.skipABC;
1417
0
    }
1418
1419
0
}
1420
1421
/*
1422
 * Initialize (just enough of) an gs_gstate so that "concretizing" colors
1423
 * using this gs_gstate will do only the CIE->XYZ mapping.  This is a
1424
 * semi-hack for the PDF writer.
1425
 */
1426
int
1427
gx_cie_to_xyz_alloc(gs_gstate **ppgs, const gs_color_space *pcs,
1428
                    gs_memory_t *mem)
1429
0
{
1430
    /*
1431
     * In addition to the gs_gstate itself, we need the joint caches.
1432
     */
1433
0
    gs_gstate *pgs =
1434
0
        gs_alloc_struct(mem, gs_gstate, &st_gs_gstate,
1435
0
                        "gx_cie_to_xyz_alloc(gs_gstate)");
1436
0
    gx_cie_joint_caches *pjc;
1437
0
    const gs_cie_abc *pabc;
1438
0
    const gs_cie_common *pcie = cie_cs_common_abc(pcs, &pabc);
1439
0
    int j;
1440
1441
0
    if (pgs == 0)
1442
0
        return_error(gs_error_VMerror);
1443
0
    memset(pgs, 0, sizeof(*pgs)); /* mostly paranoia */
1444
0
    pgs->memory = mem;
1445
0
    GS_STATE_INIT_VALUES(pgs, 1.0);
1446
0
    gs_gstate_initialize(pgs, mem);
1447
1448
0
    pjc = gs_alloc_struct(mem, gx_cie_joint_caches, &st_joint_caches,
1449
0
                          "gx_cie_to_xyz_free(joint caches)");
1450
0
    if (pjc == 0) {
1451
0
        gs_free_object(mem, pgs, "gx_cie_to_xyz_alloc(gs_gstate)");
1452
0
        return_error(gs_error_VMerror);
1453
0
    }
1454
0
    rc_init(pjc, mem, 1);
1455
1456
    /*
1457
     * Perform an abbreviated version of cie_joint_caches_complete.
1458
     * Don't bother with any optimizations.
1459
     */
1460
0
    for (j = 0; j < 3; j++) {
1461
0
        cie_cache_mult(&pjc->DecodeLMN.caches[j], &pcie->MatrixLMN.cu + j,
1462
0
                       &pcie->caches.DecodeLMN[j].floats,
1463
0
                       CACHE_THRESHOLD);
1464
0
    }
1465
0
    cie_cache3_set_interpolation(&pjc->DecodeLMN);
1466
0
    pjc->skipDecodeLMN = false;
1467
0
    pjc->skipDecodeABC = pabc != 0 && pabc->caches.skipABC;
1468
    /* Mark the joint caches as completed. */
1469
0
    pjc->remap_finish = gx_cie_xyz_remap_finish;
1470
0
    pjc->cspace_id = pcs->id;
1471
0
    pjc->status = CIE_JC_STATUS_COMPLETED;
1472
0
    pgs->cie_joint_caches = pjc;
1473
0
    pgs->cie_to_xyz = true;
1474
0
    *ppgs = pgs;
1475
0
    return 0;
1476
0
}
1477
void
1478
gx_cie_to_xyz_free(gs_gstate *pgs)
1479
0
{
1480
0
    gs_memory_t *mem = pgs->memory;
1481
1482
0
    rc_decrement(pgs->cie_joint_caches,"gx_cie_to_xyz_free");
1483
1484
    /* Free up the ICC objects if created */    /* FIXME: does this need to be thread safe */
1485
0
    if (pgs->icc_link_cache != NULL) {
1486
0
        rc_decrement(pgs->icc_link_cache,"gx_cie_to_xyz_free");
1487
0
    }
1488
0
    if (pgs->icc_manager != NULL) {
1489
0
        rc_decrement(pgs->icc_manager,"gx_cie_to_xyz_free");
1490
0
    }
1491
0
    if (pgs->icc_profile_cache != NULL) {
1492
0
        rc_decrement(pgs->icc_profile_cache,"gx_cie_to_xyz_free");
1493
0
    }
1494
0
    gs_free_object(mem, pgs, "gx_cie_to_xyz_free(gs_gstate)");
1495
0
}
1496
1497
/* ================ Utilities ================ */
1498
1499
/* Multiply a vector by a matrix. */
1500
/* Note that we are computing M * V where v is a column vector. */
1501
void
1502
cie_mult3(const gs_vector3 * in, register const gs_matrix3 * mat,
1503
          gs_vector3 * out)
1504
446k
{
1505
446k
    if_debug_vector3("[c]mult", in);
1506
446k
    if_debug_matrix3("  *", mat);
1507
446k
    {
1508
446k
        float u = in->u, v = in->v, w = in->w;
1509
1510
446k
        out->u = (u * mat->cu.u) + (v * mat->cv.u) + (w * mat->cw.u);
1511
446k
        out->v = (u * mat->cu.v) + (v * mat->cv.v) + (w * mat->cw.v);
1512
446k
        out->w = (u * mat->cu.w) + (v * mat->cv.w) + (w * mat->cw.w);
1513
446k
    }
1514
446k
    if_debug_vector3("  =", out);
1515
446k
}
1516
1517
/*
1518
 * Multiply two matrices.  Note that the composition of the transformations
1519
 * M1 followed by M2 is M2 * M1, not M1 * M2.  (See gscie.h for details.)
1520
 */
1521
void
1522
cie_matrix_mult3(const gs_matrix3 *ma, const gs_matrix3 *mb, gs_matrix3 *mc)
1523
89.2k
{
1524
89.2k
    gs_matrix3 mprod;
1525
89.2k
    gs_matrix3 *mp = (mc == ma || mc == mb ? &mprod : mc);
1526
1527
89.2k
    if_debug_matrix3("[c]matrix_mult", ma);
1528
89.2k
    if_debug_matrix3("             *", mb);
1529
89.2k
    cie_mult3(&mb->cu, ma, &mp->cu);
1530
89.2k
    cie_mult3(&mb->cv, ma, &mp->cv);
1531
89.2k
    cie_mult3(&mb->cw, ma, &mp->cw);
1532
89.2k
    cie_matrix_init(mp);
1533
89.2k
    if_debug_matrix3("             =", mp);
1534
89.2k
    if (mp != mc)
1535
0
        *mc = *mp;
1536
89.2k
}
1537
1538
/*
1539
 * Transpose a 3x3 matrix. In and out can not be the same
1540
 */
1541
void
1542
cie_matrix_transpose3(const gs_matrix3 *in, gs_matrix3 *out)
1543
0
{
1544
0
    out->cu.u = in->cu.u;
1545
0
    out->cu.v = in->cv.u;
1546
0
    out->cu.w = in->cw.u;
1547
1548
0
    out->cv.u = in->cu.v;
1549
0
    out->cv.v = in->cv.v;
1550
0
    out->cv.w = in->cw.v;
1551
1552
0
    out->cw.u = in->cu.w;
1553
0
    out->cw.v = in->cv.w;
1554
0
    out->cw.w = in->cw.w;
1555
0
}
1556
1557
/* Invert a matrix. */
1558
/* The output must not be an alias for the input. */
1559
static void
1560
cie_invert3(const gs_matrix3 *in, gs_matrix3 *out)
1561
89.2k
{ /* This is a brute force algorithm; maybe there are better. */
1562
    /* We label the array elements */
1563
    /*   [ A B C ]   */
1564
    /*   [ D E F ]   */
1565
    /*   [ G H I ]   */
1566
535k
#define A cu.u
1567
535k
#define B cv.u
1568
535k
#define C cw.u
1569
446k
#define D cu.v
1570
446k
#define E cv.v
1571
446k
#define F cw.v
1572
446k
#define G cu.w
1573
446k
#define H cv.w
1574
446k
#define I cw.w
1575
89.2k
    double coA = in->E * in->I - in->F * in->H;
1576
89.2k
    double coB = in->F * in->G - in->D * in->I;
1577
89.2k
    double coC = in->D * in->H - in->E * in->G;
1578
89.2k
    double det = in->A * coA + in->B * coB + in->C * coC;
1579
1580
89.2k
    if_debug_matrix3("[c]invert", in);
1581
89.2k
    out->A = coA / det;
1582
89.2k
    out->D = coB / det;
1583
89.2k
    out->G = coC / det;
1584
89.2k
    out->B = (in->C * in->H - in->B * in->I) / det;
1585
89.2k
    out->E = (in->A * in->I - in->C * in->G) / det;
1586
89.2k
    out->H = (in->B * in->G - in->A * in->H) / det;
1587
89.2k
    out->C = (in->B * in->F - in->C * in->E) / det;
1588
89.2k
    out->F = (in->C * in->D - in->A * in->F) / det;
1589
89.2k
    out->I = (in->A * in->E - in->B * in->D) / det;
1590
89.2k
    if_debug_matrix3("        =", out);
1591
89.2k
#undef A
1592
89.2k
#undef B
1593
89.2k
#undef C
1594
89.2k
#undef D
1595
89.2k
#undef E
1596
89.2k
#undef F
1597
89.2k
#undef G
1598
89.2k
#undef H
1599
89.2k
#undef I
1600
89.2k
    out->is_identity = in->is_identity;
1601
89.2k
}
1602
1603
/* Set the is_identity flag that accelerates multiplication. */
1604
static void
1605
cie_matrix_init(register gs_matrix3 * mat)
1606
357k
{
1607
357k
    mat->is_identity =
1608
357k
        mat->cu.u == 1.0 && is_fzero2(mat->cu.v, mat->cu.w) &&
1609
357k
        mat->cv.v == 1.0 && is_fzero2(mat->cv.u, mat->cv.w) &&
1610
357k
        mat->cw.w == 1.0 && is_fzero2(mat->cw.u, mat->cw.v);
1611
357k
}
1612
1613
bool
1614
gx_color_space_needs_cie_caches(const gs_color_space * pcs)
1615
0
{
1616
0
    switch (pcs->type->index) {
1617
0
        case gs_color_space_index_CIEDEFG:
1618
0
        case gs_color_space_index_CIEDEF:
1619
0
        case gs_color_space_index_CIEABC:
1620
0
        case gs_color_space_index_CIEA:
1621
0
            return true;
1622
0
        case gs_color_space_index_ICC:
1623
0
            return false;
1624
0
        case gs_color_space_index_DevicePixel:
1625
0
        case gs_color_space_index_DeviceN:
1626
0
        case gs_color_space_index_Separation:
1627
0
        case gs_color_space_index_Indexed:
1628
0
        case gs_color_space_index_Pattern:
1629
0
            return gx_color_space_needs_cie_caches(pcs->base_space);
1630
0
        default:
1631
0
            return false;
1632
0
    }
1633
0
}