~ubuntu-branches/ubuntu/vivid/ghostscript/vivid-security

« back to all changes in this revision

Viewing changes to base/gdevpdfc.c

  • Committer: Package Import Robot
  • Author(s): Till Kamppeter
  • Date: 2013-08-09 20:01:36 UTC
  • mfrom: (1.1.37)
  • Revision ID: package-import@ubuntu.com-20130809200136-amb6zrr7hnjb5jq9
Tags: 9.08~rc1~dfsg-0ubuntu1
* New upstream release
   - Ghostscript 9.08rc1.
   - We are using the system's liblcms2 and libopenjpeg now.
* debian/patches/020130401-852e545-pxl-xl-driver-produced-drawing-commands-without-setting-color-space.patch:
  Removed patch backported from upstream.
* debian/patches/ojdk-8007925+8007926.patch,
  debian/patches/ojdk-8007927.patch,
  debian/patches/ojdk-8007929.patch,
  debian/patches/ojdk-8009654.patch: Removed patches on build in liblcms2, we
  use the system's liblcms2 now.
* debian/patches/2001_docdir_fix_for_debian.patch: Manually updated to new
  upstream source code.
* debian/patches/2003_support_multiarch.patch: Refreshed with quilt.
* debian/control: Added build dependencies on liblcms2-dev and
  libopenjpeg-dev.
* debian/rules: Check for removed lcms2/ and openjpeg/ subdirectories in
  the repackaging check again, also set build options for shared liblcms2
  and libopenjpeg libraries.
* debian/rules: Makefile.in and configure.ac are in the root directory of
  the source now and do not need to get linked from base/. Also there is no
  gstoraster and gstopxl CUPS filter in the package any more and no
  "install-cups" make target any more.
* debian/control, debian/rules, debian/ghostscript-cups.install,
  debian/ghostscript-cups.ppd-updater: Removed the ghostscript-cups binary
  package. The files are now provided by cups-filters.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2001-2012 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.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13
 
   CA  94903, U.S.A., +1(415)492-9861, for further information.
14
 
*/
15
 
 
16
 
 
17
 
/* Color space management and writing for pdfwrite driver */
18
 
#include "math_.h"
19
 
#include "memory_.h"
20
 
#include "gx.h"
21
 
#include "gscspace.h"           /* for gscie.h */
22
 
#include "gscdevn.h"
23
 
#include "gscie.h"
24
 
#include "gscindex.h"
25
 
#include "gscsepr.h"
26
 
#include "stream.h"
27
 
#include "gsicc.h"
28
 
#include "gserrors.h"
29
 
#include "gsfunc.h"             /* required for colour space function evaluation */
30
 
#include "gsfunc3.h"            /* Required to create a replacement lineat interpolation function */
31
 
#include "gdevpdfx.h"
32
 
#include "gdevpdfg.h"
33
 
#include "gdevpdfc.h"
34
 
#include "gdevpdfo.h"
35
 
#include "strimpl.h"
36
 
#include "sstring.h"
37
 
#include "gxcspace.h"
38
 
#include "gxcdevn.h"
39
 
#include "gscspace.h"
40
 
#include "gsicc_manage.h"
41
 
#include "gsicc_cache.h"
42
 
 
43
 
/*
44
 
 * PDF doesn't have general CIEBased color spaces.  However, it provides
45
 
 * two methods for handling general CIE spaces:
46
 
 *
47
 
 *      - For PDF 1.2 and above, we note that the transformation from L*a*b*
48
 
 *      space to XYZ space is invertible, so we can handle any PostScript
49
 
 *      CIEBased space by transforming color values in that space to XYZ,
50
 
 *      then inverse-transforming them to L*a*b* and using a PDF Lab space
51
 
 *      with the same WhitePoint and BlackPoint and appropriate ranges for
52
 
 *      a and b.  This approach has the drawback that Y values outside the
53
 
 *      range [0..1] can't be represented: we just clamp them.
54
 
 *
55
 
 *      - For PDF 1.3 and above, we can create an ICCBased space.  This is
56
 
 *      actually necessary, not just an option, because for shadings (also
57
 
 *      introduced in PDF 1.3), we want color interpolation to occur in the
58
 
 *      original space.
59
 
 *
60
 
 * The Lab approach is not currently implemented, because it requires
61
 
 * transforming all the sample values of images.  The ICCBased approach is
62
 
 * implemented for color spaces whose ranges lie within [0..1], which are
63
 
 * the only ranges supported by the ICC standard: we think that removing
64
 
 * this limitation would also require transforming image sample values.
65
 
 */
66
 
 
67
 
/* GC descriptors */
68
 
public_st_pdf_color_space();
69
 
 
70
 
/* ------ CIE space testing ------ */
71
 
 
72
 
/* Test whether a cached CIE procedure is the identity function. */
73
 
#define CIE_CACHE_IS_IDENTITY(pc)\
74
 
  ((pc)->floats.params.is_identity)
75
 
#define CIE_CACHE3_IS_IDENTITY(pca)\
76
 
  (CIE_CACHE_IS_IDENTITY(&(pca)[0]) &&\
77
 
   CIE_CACHE_IS_IDENTITY(&(pca)[1]) &&\
78
 
   CIE_CACHE_IS_IDENTITY(&(pca)[2]))
79
 
 
80
 
/*
81
 
 * Test whether a cached CIE procedure is an exponential.  A cached
82
 
 * procedure is exponential iff f(x) = k*(x^p).  We make a very cursory
83
 
 * check for this: we require that f(0) = 0, set k = f(1), set p =
84
 
 * log[a](f(a)/k), and then require that f(b) = k*(b^p), where a and b are
85
 
 * two arbitrarily chosen values between 0 and 1.  Naturally all this is
86
 
 * done with some slop.
87
 
 */
88
 
#define CC_INDEX_A (gx_cie_cache_size / 3)
89
 
#define CC_INDEX_B (gx_cie_cache_size * 2 / 3)
90
 
#define CC_INDEX_1 (gx_cie_cache_size - 1)
91
 
#define CC_KEY(i) ((i) / (double)CC_INDEX_1)
92
 
#define CC_KEY_A CC_KEY(CC_INDEX_A)
93
 
#define CC_KEY_B CC_KEY(CC_INDEX_B)
94
 
 
95
 
static bool
96
 
cie_values_are_exponential(floatp v0, floatp va, floatp vb, floatp k,
97
 
                           float *pexpt)
98
 
{
99
 
    double p;
100
 
 
101
 
    if (fabs(v0) >= 0.001 || fabs(k) < 0.001)
102
 
        return false;
103
 
    if (va == 0 || (va > 0) != (k > 0))
104
 
        return false;
105
 
    p = log(va / k) / log(CC_KEY_A);
106
 
    if (fabs(vb - k * pow(CC_KEY_B, p)) >= 0.001)
107
 
        return false;
108
 
    *pexpt = p;
109
 
    return true;
110
 
}
111
 
 
112
 
static bool
113
 
cie_scalar_cache_is_exponential(const gx_cie_scalar_cache * pc, float *pexpt)
114
 
{
115
 
    return cie_values_are_exponential(pc->floats.values[0],
116
 
                                      pc->floats.values[CC_INDEX_A],
117
 
                                      pc->floats.values[CC_INDEX_B],
118
 
                                      pc->floats.values[CC_INDEX_1],
119
 
                                      pexpt);
120
 
}
121
 
#define CIE_SCALAR3_CACHE_IS_EXPONENTIAL(pca, expts)\
122
 
  (cie_scalar_cache_is_exponential(&(pca)[0], &(expts).u) &&\
123
 
   cie_scalar_cache_is_exponential(&(pca)[1], &(expts).v) &&\
124
 
   cie_scalar_cache_is_exponential(&(pca)[2], &(expts).w))
125
 
 
126
 
static bool
127
 
cie_vector_cache_is_exponential(const gx_cie_vector_cache * pc, float *pexpt)
128
 
{
129
 
    return cie_values_are_exponential(pc->vecs.values[0].u,
130
 
                                      pc->vecs.values[CC_INDEX_A].u,
131
 
                                      pc->vecs.values[CC_INDEX_B].u,
132
 
                                      pc->vecs.values[CC_INDEX_1].u,
133
 
                                      pexpt);
134
 
}
135
 
#define CIE_VECTOR3_CACHE_IS_EXPONENTIAL(pca, expts)\
136
 
  (cie_vector_cache_is_exponential(&(pca)[0], &(expts).u) &&\
137
 
   cie_vector_cache_is_exponential(&(pca)[1], &(expts).v) &&\
138
 
   cie_vector_cache_is_exponential(&(pca)[2], &(expts).w))
139
 
 
140
 
#undef CC_INDEX_A
141
 
#undef CC_INDEX_B
142
 
#undef CC_KEY_A
143
 
#undef CC_KEY_B
144
 
 
145
 
/*
146
 
 * Test whether a cached CIEBasedABC space consists only of a single
147
 
 * Decode step followed by a single Matrix step.
148
 
 */
149
 
static cie_cache_one_step_t
150
 
cie_cached_abc_is_one_step(const gs_cie_abc *pcie, const gs_matrix3 **ppmat)
151
 
{
152
 
    /* The order of steps is, DecodeABC, MatrixABC, DecodeLMN, MatrixLMN. */
153
 
 
154
 
    if (CIE_CACHE3_IS_IDENTITY(pcie->common.caches.DecodeLMN)) {
155
 
        if (pcie->MatrixABC.is_identity) {
156
 
            *ppmat = &pcie->common.MatrixLMN;
157
 
            return ONE_STEP_ABC;
158
 
        }
159
 
        if (pcie->common.MatrixLMN.is_identity) {
160
 
            *ppmat = &pcie->MatrixABC;
161
 
            return ONE_STEP_ABC;
162
 
        }
163
 
    }
164
 
    if (CIE_CACHE3_IS_IDENTITY(pcie->caches.DecodeABC.caches)) {
165
 
        if (pcie->MatrixABC.is_identity) {
166
 
            *ppmat = &pcie->common.MatrixLMN;
167
 
            return ONE_STEP_LMN;
168
 
        }
169
 
    }
170
 
    return ONE_STEP_NOT;
171
 
}
172
 
 
173
 
/*
174
 
 * Test whether a cached CIEBasedABC space is a L*a*b* space.
175
 
 */
176
 
static bool
177
 
cie_scalar_cache_is_lab_lmn(const gs_cie_abc *pcie, int i)
178
 
{
179
 
    double k = CC_KEY(i);
180
 
    double g = (k >= 6.0 / 29 ? k * k * k :
181
 
                (k - 4.0 / 29) * (108.0 / 841));
182
 
 
183
 
#define CC_V(j,i) (pcie->common.caches.DecodeLMN[j].floats.values[i])
184
 
#define CC_WP(uvw) (pcie->common.points.WhitePoint.uvw)
185
 
 
186
 
    return (fabs(CC_V(0, i) - g * CC_WP(u)) < 0.001 &&
187
 
            fabs(CC_V(1, i) - g * CC_WP(v)) < 0.001 &&
188
 
            fabs(CC_V(2, i) - g * CC_WP(w)) < 0.001
189
 
            );
190
 
 
191
 
#undef CC_V
192
 
#undef CC_WP
193
 
}
194
 
static bool
195
 
cie_vector_cache_is_lab_abc(const gx_cie_vector_cache3_t *pvc, int i)
196
 
{
197
 
    const gx_cie_vector_cache *const pc3 = pvc->caches;
198
 
    double k = CC_KEY(i);
199
 
    double l0 = pc3[0].vecs.params.base,
200
 
        l = l0 + k * (pc3[0].vecs.params.limit - l0);
201
 
    double a0 = pc3[1].vecs.params.base,
202
 
        a = a0 + k * (pc3[1].vecs.params.limit - a0);
203
 
    double b0 = pc3[2].vecs.params.base,
204
 
        b = b0 + k * (pc3[2].vecs.params.limit - b0);
205
 
 
206
 
    return (fabs(cie_cached2float(pc3[0].vecs.values[i].u) -
207
 
                 (l + 16) / 116) < 0.001 &&
208
 
            fabs(cie_cached2float(pc3[1].vecs.values[i].u) -
209
 
                 a / 500) < 0.001 &&
210
 
            fabs(cie_cached2float(pc3[2].vecs.values[i].w) -
211
 
                 b / -200) < 0.001
212
 
            );
213
 
}
214
 
 
215
 
static bool
216
 
cie_is_lab(const gs_cie_abc *pcie)
217
 
{
218
 
    int i;
219
 
 
220
 
    /* Check MatrixABC and MatrixLMN. */
221
 
    if (!(pcie->MatrixABC.cu.u == 1 && pcie->MatrixABC.cu.v == 1 &&
222
 
          pcie->MatrixABC.cu.w == 1 &&
223
 
          pcie->MatrixABC.cv.u == 1 && pcie->MatrixABC.cv.v == 0 &&
224
 
          pcie->MatrixABC.cv.w == 0 &&
225
 
          pcie->MatrixABC.cw.u == 0 && pcie->MatrixABC.cw.v == 0 &&
226
 
          pcie->MatrixABC.cw.w == -1 &&
227
 
          pcie->common.MatrixLMN.is_identity
228
 
          ))
229
 
        return false;
230
 
 
231
 
    /* Check DecodeABC and DecodeLMN. */
232
 
    for (i = 0; i <= CC_INDEX_1; ++i)
233
 
        if (!(cie_vector_cache_is_lab_abc(&pcie->caches.DecodeABC, i) &&
234
 
              cie_scalar_cache_is_lab_lmn(pcie, i)
235
 
              ))
236
 
            return false;
237
 
 
238
 
    return true;
239
 
}
240
 
 
241
 
#undef CC_INDEX_1
242
 
#undef CC_KEY
243
 
 
244
 
/* Test whether one or more CIE-based ranges are [0..1]. */
245
 
static bool
246
 
cie_ranges_are_0_1(const gs_range *prange, int n)
247
 
{
248
 
    int i;
249
 
 
250
 
    for (i = 0; i < n; ++i)
251
 
        if (prange[i].rmin != 0 || prange[i].rmax != 1)
252
 
            return false;
253
 
    return true;
254
 
}
255
 
 
256
 
/* ------ Utilities ------ */
257
 
 
258
 
/* Add a 3-element vector to a Cos array or dictionary. */
259
 
static int
260
 
cos_array_add_vector3(cos_array_t *pca, const gs_vector3 *pvec)
261
 
{
262
 
    int code = cos_array_add_real(pca, pvec->u);
263
 
 
264
 
    if (code >= 0)
265
 
        code = cos_array_add_real(pca, pvec->v);
266
 
    if (code >= 0)
267
 
        code = cos_array_add_real(pca, pvec->w);
268
 
    return code;
269
 
}
270
 
static int
271
 
cos_dict_put_c_key_vector3(cos_dict_t *pcd, const char *key,
272
 
                           const gs_vector3 *pvec)
273
 
{
274
 
    cos_array_t *pca = cos_array_alloc(pcd->pdev, "cos_array_from_vector3");
275
 
    int code;
276
 
 
277
 
    if (pca == 0)
278
 
        return_error(gs_error_VMerror);
279
 
    code = cos_array_add_vector3(pca, pvec);
280
 
    if (code < 0) {
281
 
        COS_FREE(pca, "cos_array_from_vector3");
282
 
        return code;
283
 
    }
284
 
    return cos_dict_put_c_key_object(pcd, key, COS_OBJECT(pca));
285
 
}
286
 
 
287
 
/*
288
 
 * Finish creating a CIE-based color space (Calxxx or Lab.)
289
 
 * This procedure is exported for gdevpdfk.c.
290
 
 */
291
 
int
292
 
pdf_finish_cie_space(cos_array_t *pca, cos_dict_t *pcd,
293
 
                     const gs_cie_common *pciec)
294
 
{
295
 
    int code = cos_dict_put_c_key_vector3(pcd, "/WhitePoint",
296
 
                                          &pciec->points.WhitePoint);
297
 
 
298
 
    if (code < 0)
299
 
        return code;
300
 
    if (pciec->points.BlackPoint.u != 0 ||
301
 
        pciec->points.BlackPoint.v != 0 ||
302
 
        pciec->points.BlackPoint.w != 0
303
 
        ) {
304
 
        code = cos_dict_put_c_key_vector3(pcd, "/BlackPoint",
305
 
                                          &pciec->points.BlackPoint);
306
 
        if (code < 0)
307
 
            return code;
308
 
    }
309
 
    return cos_array_add_object(pca, COS_OBJECT(pcd));
310
 
}
311
 
 
312
 
/* ------ Color space writing ------ */
313
 
 
314
 
/* Define standard and short color space names. */
315
 
const pdf_color_space_names_t pdf_color_space_names = {
316
 
    PDF_COLOR_SPACE_NAMES
317
 
};
318
 
const pdf_color_space_names_t pdf_color_space_names_short = {
319
 
    PDF_COLOR_SPACE_NAMES_SHORT
320
 
};
321
 
 
322
 
/*
323
 
 * Create a local Device{Gray,RGB,CMYK} color space corresponding to the
324
 
 * given number of components.
325
 
 */
326
 
int
327
 
pdf_cspace_init_Device(gs_memory_t *mem, gs_color_space **ppcs,
328
 
                       int num_components)
329
 
{
330
 
    switch (num_components) {
331
 
    case 1: *ppcs = gs_cspace_new_DeviceGray(mem); break;
332
 
    case 3: *ppcs = gs_cspace_new_DeviceRGB(mem); break;
333
 
    case 4: *ppcs = gs_cspace_new_DeviceCMYK(mem); break;
334
 
    default: return_error(gs_error_rangecheck);
335
 
    }
336
 
    return 0;
337
 
}
338
 
 
339
 
static int pdf_delete_base_space_function(gx_device_pdf *pdev, gs_function_t *pfn)
340
 
{
341
 
    gs_function_ElIn_params_t *params = (gs_function_ElIn_params_t *)&pfn->params;
342
 
 
343
 
    gs_free_object(pdev->memory, (void *)params->Domain, "pdf_delete_function");
344
 
    gs_free_object(pdev->memory, (void *)params->Range, "pdf_delete_function");
345
 
    gs_free_object(pdev->memory, (void *)params->C0, "pdf_delete_function");
346
 
    gs_free_object(pdev->memory, (void *)params->C1, "pdf_delete_function");
347
 
    gs_free_object(pdev->memory, (void *)pfn, "pdf_delete_function");
348
 
    return 0;
349
 
}
350
 
 
351
 
static int pdf_make_base_space_function(gx_device_pdf *pdev, gs_function_t **pfn,
352
 
                                        int ncomp, float *data_low, float *data_high)
353
 
{
354
 
    gs_function_ElIn_params_t params;
355
 
    float *ptr1, *ptr2;
356
 
    int i, code;
357
 
 
358
 
    ptr1 = (float *)
359
 
        gs_alloc_byte_array(pdev->memory, 2, sizeof(float), "pdf_make_function(Domain)");
360
 
    if (ptr1 == 0) {
361
 
        return gs_note_error(gs_error_VMerror);
362
 
    }
363
 
    ptr2 = (float *)
364
 
        gs_alloc_byte_array(pdev->memory, 2 * ncomp, sizeof(float), "pdf_make_function(Range)");
365
 
    if (ptr2 == 0) {
366
 
        gs_free_object(pdev->memory, (void *)ptr1, "pdf_make_function(Range)");
367
 
        return gs_note_error(gs_error_VMerror);
368
 
    }
369
 
    params.m = 1;
370
 
    params.n = ncomp;
371
 
    params.N = 1.0f;
372
 
    ptr1[0] = 0.0f;
373
 
    ptr1[1] = 1.0f;
374
 
    for (i=0;i<ncomp;i++) {
375
 
        ptr2[i*2] = 0.0f;
376
 
        ptr2[(i*2) + 1] = 1.0f;
377
 
    }
378
 
    params.Domain = ptr1;
379
 
    params.Range = ptr2;
380
 
 
381
 
    ptr1 = (float *)gs_alloc_byte_array(pdev->memory, ncomp, sizeof(float), "pdf_make_function(C0)");
382
 
    if (ptr1 == 0) {
383
 
        gs_free_object(pdev->memory, (void *)params.Domain, "pdf_make_function(C0)");
384
 
        gs_free_object(pdev->memory, (void *)params.Range, "pdf_make_function(C0)");
385
 
        return gs_note_error(gs_error_VMerror);
386
 
    }
387
 
    ptr2 = (float *)gs_alloc_byte_array(pdev->memory, ncomp, sizeof(float), "pdf_make_function(C1)");
388
 
    if (ptr2 == 0) {
389
 
        gs_free_object(pdev->memory, (void *)params.Domain, "pdf_make_function(C1)");
390
 
        gs_free_object(pdev->memory, (void *)params.Range, "pdf_make_function(C1)");
391
 
        gs_free_object(pdev->memory, (void *)ptr1, "pdf_make_function(C1)");
392
 
        return gs_note_error(gs_error_VMerror);
393
 
    }
394
 
 
395
 
    for (i=0;i<ncomp;i++) {
396
 
        ptr1[i] = data_low[i];
397
 
        ptr2[i] = data_high[i];
398
 
    }
399
 
    params.C0 = ptr1;
400
 
    params.C1 = ptr2;
401
 
    code = gs_function_ElIn_init(pfn, &params, pdev->memory);
402
 
    if (code < 0) {
403
 
        gs_free_object(pdev->memory, (void *)params.Domain, "pdf_make_function");
404
 
        gs_free_object(pdev->memory, (void *)params.Range, "pdf_make_function");
405
 
        gs_free_object(pdev->memory, (void *)params.C0, "pdf_make_function");
406
 
        gs_free_object(pdev->memory, (void *)params.C1, "pdf_make_function");
407
 
    }
408
 
    return code;
409
 
}
410
 
 
411
 
static void pdf_SepRGB_ConvertToCMYK (float *in, float *out)
412
 
{
413
 
    float CMYK[4];
414
 
    int i;
415
 
 
416
 
    if (in[0] <= in[1] && in[0] <= in[2]) {
417
 
        CMYK[3] = 1.0 - in[0];
418
 
    } else {
419
 
        if (in[1]<= in[0] && in[1] <= in[2]) {
420
 
            CMYK[3] = 1.0 - in[1];
421
 
        } else {
422
 
            CMYK[3] = 1.0 - in[2];
423
 
        }
424
 
    }
425
 
    CMYK[0] = 1.0 - in[0] - CMYK[3];
426
 
    CMYK[1] = 1.0 - in[1] - CMYK[3];
427
 
    CMYK[2] = 1.0 - in[2] - CMYK[3];
428
 
    for (i=0;i<4;i++)
429
 
        out[i] = CMYK[i];
430
 
}
431
 
 
432
 
static void pdf_SepCMYK_ConvertToRGB (float *in, float *out)
433
 
{
434
 
    float RGB[3];
435
 
 
436
 
    RGB[0] = in[0] + in[3];
437
 
    RGB[1] = in[1] + in[3];
438
 
    RGB[2] = in[2] + in[3];
439
 
 
440
 
    if (RGB[0] > 1)
441
 
        out[0] = 0.0f;
442
 
    else
443
 
        out[0] = 1 - RGB[0];
444
 
    if (RGB[1] > 1)
445
 
        out[1] = 0.0f;
446
 
    else
447
 
        out[1] = 1 - RGB[1];
448
 
    if (RGB[2] > 1)
449
 
        out[2] = 0.0f;
450
 
    else
451
 
        out[2] = 1 - RGB[2];
452
 
}
453
 
 
454
 
/* Create a Separation or DeviceN color space (internal). */
455
 
static int
456
 
pdf_separation_color_space(gx_device_pdf *pdev,
457
 
                           cos_array_t *pca, const char *csname,
458
 
                           const cos_value_t *snames,
459
 
                           const gs_color_space *alt_space,
460
 
                           const gs_function_t *pfn,
461
 
                           const pdf_color_space_names_t *pcsn,
462
 
                           const cos_value_t *v_attributes)
463
 
{
464
 
    cos_value_t v;
465
 
    const gs_range_t *ranges;
466
 
    int code, csi;
467
 
 
468
 
    /* We need to think about the alternate space. If we are producing
469
 
     * PDF/X or PDF/A we can't produce some device spaces, and the code in
470
 
     * pdf_color_space_named always allows device spaces. We could alter
471
 
     * that code, but by then we don't know its an Alternate space, and have
472
 
     * lost the tin transform procedure. So instead we check here.
473
 
     */
474
 
    csi = gs_color_space_get_index(alt_space);
475
 
    /* Note that if csi is ICC, check to see if this was one of
476
 
       the default substitutes that we introduced for DeviceGray,
477
 
       DeviceRGB or DeviceCMYK.  If it is, then just write
478
 
       the default color.  Depending upon the flavor of PDF,
479
 
       or other options, we may want to actually have all
480
 
       the colors defined by ICC profiles and not do the following
481
 
       substituion of the Device space. */
482
 
    if (csi == gs_color_space_index_ICC) {
483
 
        csi = gsicc_get_default_type(alt_space->cmm_icc_profile_data);
484
 
    }
485
 
    if (csi == gs_color_space_index_DeviceRGB && (pdev->PDFX ||
486
 
        (pdev->PDFA != 0 && (pdev->pcm_color_info_index == gs_color_space_index_DeviceCMYK)))) {
487
 
 
488
 
        /* We have a DeviceRGB alternate, but are producing either PDF/X or
489
 
         * PDF/A with a DeviceCMYK process color model. So we need to convert
490
 
         * the alternate space into CMYK. We do this by evaluating the function
491
 
         * at each end of the Separation space (0 and 1), convert the resulting
492
 
         * RGB colours into CMYK and create a new function which linearly
493
 
         * interpolates between these points.
494
 
         */
495
 
        gs_function_t *new_pfn = 0;
496
 
        float in[1] = {0.0f};
497
 
        float out_low[4];
498
 
        float out_high[4];
499
 
 
500
 
        code = gs_function_evaluate(pfn, in, out_low);
501
 
        if (code < 0)
502
 
            return code;
503
 
        pdf_SepRGB_ConvertToCMYK((float *)&out_low, (float *)&out_low);
504
 
 
505
 
        in[0] = 1.0f;
506
 
        code = gs_function_evaluate(pfn, in, out_high);
507
 
        if (code < 0)
508
 
            return code;
509
 
        pdf_SepRGB_ConvertToCMYK((float *)&out_high, (float *)&out_high);
510
 
 
511
 
        code = pdf_make_base_space_function(pdev, &new_pfn, 4, out_low, out_high);
512
 
        if (code < 0)
513
 
            return code;
514
 
 
515
 
        code = cos_array_add(pca, cos_c_string_value(&v, csname));
516
 
        if (code >= 0) {
517
 
            code = cos_array_add_no_copy(pca, snames);
518
 
            if (code >= 0) {
519
 
                cos_c_string_value(&v, (const char *)pcsn->DeviceCMYK);
520
 
                code = cos_array_add(pca, &v);
521
 
                if (code >= 0) {
522
 
                    code = pdf_function_scaled(pdev, new_pfn, 0x00, &v);
523
 
                    if (code >= 0) {
524
 
                        code = cos_array_add(pca, &v);
525
 
                        if (code >= 0 && v_attributes != NULL)
526
 
                            code = cos_array_add(pca, v_attributes);
527
 
                    }
528
 
                }
529
 
            }
530
 
        }
531
 
        pdf_delete_base_space_function(pdev, new_pfn);
532
 
        return code;
533
 
    }
534
 
    if (csi == gs_color_space_index_DeviceCMYK &&
535
 
        (pdev->PDFA != 0 && (pdev->pcm_color_info_index == gs_color_space_index_DeviceRGB))) {
536
 
        /* We have a DeviceCMYK alternate, but are producingPDF/A with a
537
 
         * DeviceRGB process color model. See comment above re DviceRGB.
538
 
         */
539
 
        gs_function_t *new_pfn = 0;
540
 
        float in[1] = {0.0f};
541
 
        float out_low[4];
542
 
        float out_high[4];
543
 
 
544
 
        code = gs_function_evaluate(pfn, in, out_low);
545
 
        if (code < 0)
546
 
            return code;
547
 
        pdf_SepCMYK_ConvertToRGB((float *)&out_low, (float *)&out_low);
548
 
 
549
 
        in[0] = 1.0f;
550
 
        code = gs_function_evaluate(pfn, in, out_high);
551
 
        if (code < 0)
552
 
            return code;
553
 
        pdf_SepCMYK_ConvertToRGB((float *)&out_high, (float *)&out_high);
554
 
 
555
 
        code = pdf_make_base_space_function(pdev, &new_pfn, 3, out_low, out_high);
556
 
        if (code < 0)
557
 
            return code;
558
 
 
559
 
        code = cos_array_add(pca, cos_c_string_value(&v, csname));
560
 
        if (code >= 0) {
561
 
            code = cos_array_add_no_copy(pca, snames);
562
 
            if (code >= 0) {
563
 
                cos_c_string_value(&v, pcsn->DeviceRGB);
564
 
                code = cos_array_add(pca, &v);
565
 
                if (code >= 0) {
566
 
                    code = pdf_function_scaled(pdev, new_pfn, 0x00, &v);
567
 
                    if (code >= 0) {
568
 
                        code = cos_array_add(pca, &v);
569
 
                        if (code >= 0 && v_attributes != NULL)
570
 
                            code = cos_array_add(pca, v_attributes);
571
 
                    }
572
 
                }
573
 
            }
574
 
        }
575
 
        pdf_delete_base_space_function(pdev, new_pfn);
576
 
        return code;
577
 
    }
578
 
 
579
 
    if ((code = cos_array_add(pca, cos_c_string_value(&v, csname))) < 0 ||
580
 
        (code = cos_array_add_no_copy(pca, snames)) < 0 ||
581
 
        (code = pdf_color_space_named(pdev, &v, &ranges, alt_space, pcsn, false, NULL, 0)) < 0 ||
582
 
        (code = cos_array_add(pca, &v)) < 0 ||
583
 
        (code = pdf_function_scaled(pdev, pfn, ranges, &v)) < 0 ||
584
 
        (code = cos_array_add(pca, &v)) < 0 ||
585
 
        (v_attributes != NULL ? code = cos_array_add(pca, v_attributes) : 0) < 0
586
 
        )
587
 
        return code;
588
 
    return 0;
589
 
}
590
 
 
591
 
/*
592
 
 * Create an Indexed color space.  This is a single-use procedure,
593
 
 * broken out only for readability.
594
 
 */
595
 
static int
596
 
pdf_indexed_color_space(gx_device_pdf *pdev, cos_value_t *pvalue,
597
 
                        const gs_color_space *pcs, cos_array_t *pca)
598
 
{
599
 
    const gs_indexed_params *pip = &pcs->params.indexed;
600
 
    const gs_color_space *base_space = pcs->base_space;
601
 
    int num_entries = pip->hival + 1;
602
 
    int num_components = gs_color_space_num_components(base_space);
603
 
    uint table_size = num_entries * num_components;
604
 
    /* Guess at the extra space needed for PS string encoding. */
605
 
    uint string_size = 2 + table_size * 4;
606
 
    uint string_used;
607
 
    byte buf[100];              /* arbitrary */
608
 
    stream_AXE_state st;
609
 
    stream s, es;
610
 
    gs_memory_t *mem = pdev->pdf_memory;
611
 
    byte *table;
612
 
    byte *palette;
613
 
    cos_value_t v;
614
 
    int code;
615
 
 
616
 
    /* PDF doesn't support Indexed color spaces with more than 256 entries. */
617
 
    if (num_entries > 256)
618
 
        return_error(gs_error_rangecheck);
619
 
    if (pdev->CompatibilityLevel < 1.3 && !pdev->ForOPDFRead) {
620
 
        switch (gs_color_space_get_index(pcs)) {
621
 
            case gs_color_space_index_Pattern:
622
 
            case gs_color_space_index_Separation:
623
 
            case gs_color_space_index_Indexed:
624
 
            case gs_color_space_index_DeviceN:
625
 
                return_error(gs_error_rangecheck);
626
 
            default: DO_NOTHING;
627
 
        }
628
 
 
629
 
    }
630
 
    table = gs_alloc_string(mem, string_size, "pdf_color_space(table)");
631
 
    palette = gs_alloc_string(mem, table_size, "pdf_color_space(palette)");
632
 
    if (table == 0 || palette == 0) {
633
 
        gs_free_string(mem, palette, table_size,
634
 
                       "pdf_color_space(palette)");
635
 
        gs_free_string(mem, table, string_size,
636
 
                       "pdf_color_space(table)");
637
 
        return_error(gs_error_VMerror);
638
 
    }
639
 
    s_init(&s, mem);
640
 
    swrite_string(&s, table, string_size);
641
 
    s_init(&es, mem);
642
 
    s_init_state((stream_state *)&st, &s_PSSE_template, NULL);
643
 
    s_init_filter(&es, (stream_state *)&st, buf, sizeof(buf), &s);
644
 
    sputc(&s, '(');
645
 
    if (pcs->params.indexed.use_proc) {
646
 
        gs_client_color cmin, cmax;
647
 
        byte *pnext = palette;
648
 
        int i, j;
649
 
 
650
 
        /* Find the legal range for the color components. */
651
 
        for (j = 0; j < num_components; ++j)
652
 
            cmin.paint.values[j] = (float)min_long,
653
 
                cmax.paint.values[j] = (float)max_long;
654
 
        gs_color_space_restrict_color(&cmin, base_space);
655
 
        gs_color_space_restrict_color(&cmax, base_space);
656
 
        /*
657
 
         * Compute the palette values, with the legal range for each
658
 
         * one mapped to [0 .. 255].
659
 
         */
660
 
        for (i = 0; i < num_entries; ++i) {
661
 
            gs_client_color cc;
662
 
 
663
 
            gs_cspace_indexed_lookup(pcs, i, &cc);
664
 
            for (j = 0; j < num_components; ++j) {
665
 
                float v = (cc.paint.values[j] - cmin.paint.values[j])
666
 
                    * 255 / (cmax.paint.values[j] - cmin.paint.values[j]);
667
 
 
668
 
                *pnext++ = (v <= 0 ? 0 : v >= 255 ? 255 : (byte)v);
669
 
            }
670
 
        }
671
 
    } else
672
 
        memcpy(palette, pip->lookup.table.data, table_size);
673
 
    if (gs_color_space_get_index(base_space) ==
674
 
        gs_color_space_index_DeviceRGB
675
 
        ) {
676
 
        /* Check for an all-gray palette3. */
677
 
        int i;
678
 
 
679
 
        for (i = table_size; (i -= 3) >= 0; )
680
 
            if (palette[i] != palette[i + 1] ||
681
 
                palette[i] != palette[i + 2]
682
 
                )
683
 
                break;
684
 
        if (i < 0) {
685
 
            /* Change the color space to DeviceGray. */
686
 
            for (i = 0; i < num_entries; ++i)
687
 
                palette[i] = palette[i * 3];
688
 
            table_size = num_entries;
689
 
            base_space = gs_cspace_new_DeviceGray(mem);
690
 
        }
691
 
    }
692
 
    stream_write(&es, palette, table_size);
693
 
    gs_free_string(mem, palette, table_size, "pdf_color_space(palette)");
694
 
    sclose(&es);
695
 
    sflush(&s);
696
 
    string_used = (uint)stell(&s);
697
 
    table = gs_resize_string(mem, table, string_size, string_used,
698
 
                             "pdf_color_space(table)");
699
 
    /*
700
 
     * Since the array is always referenced by name as a resource
701
 
     * rather than being written as a value, even for in-line images,
702
 
     * always use the full name for the color space.
703
 
     *
704
 
     * We don't have to worry about the range of the base space:
705
 
     * in PDF, unlike PostScript, the values from the lookup table are
706
 
     * scaled automatically.
707
 
     */
708
 
    if ((code = pdf_color_space_named(pdev, pvalue, NULL, base_space,
709
 
                                &pdf_color_space_names, false, NULL, 0)) < 0 ||
710
 
        (code = cos_array_add(pca,
711
 
                              cos_c_string_value(&v,
712
 
                                                 pdf_color_space_names.Indexed
713
 
                                                 /*pcsn->Indexed*/))) < 0 ||
714
 
        (code = cos_array_add(pca, pvalue)) < 0 ||
715
 
        (code = cos_array_add_int(pca, pip->hival)) < 0 ||
716
 
        (code = cos_array_add_no_copy(pca,
717
 
                                      cos_string_value(&v, table,
718
 
                                                       string_used))) < 0
719
 
        )
720
 
        return code;
721
 
    return 0;
722
 
}
723
 
 
724
 
/*
725
 
 * Find a color space resource by seriialized data.
726
 
 */
727
 
static pdf_resource_t *
728
 
pdf_find_cspace_resource(gx_device_pdf *pdev, const byte *serialized, uint serialized_size)
729
 
{
730
 
    pdf_resource_t **pchain = pdev->resources[resourceColorSpace].chains;
731
 
    pdf_resource_t *pres;
732
 
    int i;
733
 
 
734
 
    for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
735
 
        for (pres = pchain[i]; pres != 0; pres = pres->next) {
736
 
            const pdf_color_space_t *const ppcs =
737
 
                (const pdf_color_space_t *)pres;
738
 
            if (ppcs->serialized_size != serialized_size)
739
 
                continue;
740
 
            if (!memcmp(ppcs->serialized, serialized, ppcs->serialized_size))
741
 
                return pres;
742
 
        }
743
 
    }
744
 
    return NULL;
745
 
}
746
 
 
747
 
int pdf_convert_ICC(gx_device_pdf *pdev,
748
 
                const gs_color_space *pcs, cos_value_t *pvalue,
749
 
                const pdf_color_space_names_t *pcsn)
750
 
{
751
 
    gs_color_space_index csi;
752
 
    int code;
753
 
 
754
 
    csi = gs_color_space_get_index(pcs);
755
 
    if (csi == gs_color_space_index_ICC) {
756
 
        csi = gsicc_get_default_type(pcs->cmm_icc_profile_data);
757
 
    }
758
 
    if (csi == gs_color_space_index_Indexed) {
759
 
        pcs = pcs->base_space;
760
 
        csi = gs_color_space_get_index(pcs);
761
 
    }
762
 
    if (csi == gs_color_space_index_ICC) {
763
 
        if (pcs->cmm_icc_profile_data == NULL ||
764
 
            pdev->CompatibilityLevel < 1.3
765
 
            ) {
766
 
            if (pcs->base_space != NULL) {
767
 
                return 0;
768
 
            } else {
769
 
                int num_des_comps;
770
 
                cmm_dev_profile_t *dev_profile;
771
 
 
772
 
                /* determine number of components in device space */
773
 
                code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev, &dev_profile);
774
 
                if (code < 0)
775
 
                    return code;
776
 
 
777
 
                num_des_comps = gsicc_get_device_profile_comps(dev_profile);
778
 
                /* Set image color space to be device space */
779
 
                switch( num_des_comps )  {
780
 
                    case 1:
781
 
                        cos_c_string_value(pvalue, pcsn->DeviceGray);
782
 
                        /* negative return means we do conversion */
783
 
                        return -1;
784
 
                    case 3:
785
 
                        cos_c_string_value(pvalue, pcsn->DeviceRGB);
786
 
                        return -1;
787
 
                    case 4:
788
 
                        cos_c_string_value(pvalue, pcsn->DeviceCMYK);
789
 
                        return -1;
790
 
                    default:
791
 
                        break;
792
 
                }
793
 
            }
794
 
        }
795
 
    }
796
 
    return 0;
797
 
}
798
 
 
799
 
/*
800
 
 * Create a PDF color space corresponding to a PostScript color space.
801
 
 * For parameterless color spaces, set *pvalue to a (literal) string with
802
 
 * the color space name; for other color spaces, create a cos_array_t if
803
 
 * necessary and set *pvalue to refer to it.  In the latter case, if
804
 
 * by_name is true, return a string /Rxxxx rather than a reference to
805
 
 * the actual object.
806
 
 *
807
 
 * If ppranges is not NULL, then if  the domain of the color space had
808
 
 * to be scaled (to convert a CIEBased space to ICCBased), store a pointer
809
 
 * to the ranges in *ppranges, otherwise set *ppranges to 0.
810
 
 */
811
 
int
812
 
pdf_color_space_named(gx_device_pdf *pdev, cos_value_t *pvalue,
813
 
                const gs_range_t **ppranges,
814
 
                const gs_color_space *pcs_in,
815
 
                const pdf_color_space_names_t *pcsn,
816
 
                bool by_name, const byte *res_name, int name_length)
817
 
{
818
 
    const gs_color_space *pcs;
819
 
    gs_color_space_index csi;
820
 
    cos_array_t *pca;
821
 
    cos_dict_t *pcd;
822
 
    cos_value_t v;
823
 
    const gs_cie_common *pciec;
824
 
    gs_function_t *pfn;
825
 
    const gs_range_t *ranges = 0;
826
 
    uint serialized_size;
827
 
    byte *serialized = NULL, serialized0[100];
828
 
    pdf_resource_t *pres = NULL;
829
 
    int code;
830
 
#ifdef DEPRECATED_906
831
 
    bool islab = false;
832
 
#endif
833
 
 
834
 
    /* If color space is CIE based and we have compatibility then go ahead and use the ICC alternative */
835
 
    if ((pdev->CompatibilityLevel < 1.3) || !gs_color_space_is_PSCIE(pcs_in) ) {
836
 
        pcs = pcs_in;
837
 
    } else {
838
 
        pcs = pcs_in;
839
 
        /* The snippet below creates an ICC equivalent profile for the PS
840
 
           color space.  This is disabled until I add the capability to
841
 
           specify the profile version to ensure compatability with
842
 
           the PDF versions */
843
 
#ifdef DEPRECATED_906
844
 
        if (pcs_in->icc_equivalent != NULL) {
845
 
            pcs = pcs_in->icc_equivalent;
846
 
        } else {
847
 
            /* Need to create the equivalent object */
848
 
            gs_colorspace_set_icc_equivalent((gs_color_space *)pcs_in, &islab, pdev->memory);
849
 
            pcs = pcs_in->icc_equivalent;
850
 
        }
851
 
#endif
852
 
    }
853
 
    csi = gs_color_space_get_index(pcs);
854
 
    /* Note that if csi is ICC, check to see if this was one of
855
 
       the default substitutes that we introduced for DeviceGray,
856
 
       DeviceRGB or DeviceCMYK.  If it is, then just write
857
 
       the default color.  Depending upon the flavor of PDF,
858
 
       or other options, we may want to actually have all
859
 
       the colors defined by ICC profiles and not do the following
860
 
       substituion of the Device space. */
861
 
    if (csi == gs_color_space_index_ICC) {
862
 
        csi = gsicc_get_default_type(pcs->cmm_icc_profile_data);
863
 
    }
864
 
    if (ppranges)
865
 
        *ppranges = 0;          /* default */
866
 
    switch (csi) {
867
 
    case gs_color_space_index_DeviceGray:
868
 
        cos_c_string_value(pvalue, pcsn->DeviceGray);
869
 
        return 0;
870
 
    case gs_color_space_index_DeviceRGB:
871
 
        cos_c_string_value(pvalue, pcsn->DeviceRGB);
872
 
        return 0;
873
 
    case gs_color_space_index_DeviceCMYK:
874
 
        cos_c_string_value(pvalue, pcsn->DeviceCMYK);
875
 
        return 0;
876
 
    case gs_color_space_index_Pattern:
877
 
        if (!pcs->params.pattern.has_base_space) {
878
 
            cos_c_string_value(pvalue, "/Pattern");
879
 
            return 0;
880
 
        }
881
 
        break;
882
 
    case gs_color_space_index_ICC:
883
 
        /*
884
 
         * Take a special early exit for unrecognized ICCBased color spaces,
885
 
         * or for PDF 1.2 output (ICCBased color spaces date from PDF 1.3).
886
 
         */
887
 
 
888
 
        if (pcs->cmm_icc_profile_data == NULL ||
889
 
            pdev->CompatibilityLevel < 1.3
890
 
            ) {
891
 
            if (res_name != NULL)
892
 
                return 0; /* Ignore .includecolorspace */
893
 
            if (pcs->base_space != NULL) {
894
 
            return pdf_color_space_named( pdev, pvalue, ppranges,
895
 
                                    pcs->base_space,
896
 
                                    pcsn, by_name, NULL, 0);
897
 
            } else {
898
 
                switch( cs_num_components(pcs) )  {
899
 
                    case 1:
900
 
                        cos_c_string_value(pvalue, pcsn->DeviceGray);
901
 
                        return 0;
902
 
                    case 3:
903
 
                        cos_c_string_value(pvalue, pcsn->DeviceRGB);
904
 
                        return 0;
905
 
                    case 4:
906
 
                        cos_c_string_value(pvalue, pcsn->DeviceCMYK);
907
 
                        return 0;
908
 
                    default:
909
 
                        break;
910
 
                }
911
 
            }
912
 
        }
913
 
 
914
 
        break;
915
 
    default:
916
 
        break;
917
 
    }
918
 
    if (pdev->params.ColorConversionStrategy == ccs_CMYK &&
919
 
            csi != gs_color_space_index_DeviceCMYK &&
920
 
            csi != gs_color_space_index_DeviceGray &&
921
 
            csi != gs_color_space_index_Pattern) {
922
 
          emprintf(pdev->memory,
923
 
                 "\nUnable to convert color space to CMYK, reverting strategy to LeaveColorUnchanged.\n");
924
 
          pdev->params.ColorConversionStrategy = ccs_LeaveColorUnchanged;
925
 
    }
926
 
    if (pdev->params.ColorConversionStrategy == ccs_sRGB &&
927
 
            csi != gs_color_space_index_DeviceRGB &&
928
 
            csi != gs_color_space_index_DeviceGray &&
929
 
            csi != gs_color_space_index_Pattern) {
930
 
          emprintf(pdev->memory,
931
 
                 "\nUnable to convert color space to sRGB, reverting strategy to LeaveColorUnchanged.\n");
932
 
          pdev->params.ColorConversionStrategy = ccs_LeaveColorUnchanged;
933
 
    }
934
 
    if (pdev->params.ColorConversionStrategy == ccs_Gray &&
935
 
            csi != gs_color_space_index_DeviceGray &&
936
 
            csi != gs_color_space_index_Pattern) {
937
 
          emprintf(pdev->memory,
938
 
                 "\nUnable to convert color space to Gray, reverting strategy to LeaveColorUnchanged.\n");
939
 
          pdev->params.ColorConversionStrategy = ccs_LeaveColorUnchanged;
940
 
    }
941
 
    /* Check whether we already have a PDF object for this color space. */
942
 
    if (pcs->id != gs_no_id)
943
 
        pres = pdf_find_resource_by_gs_id(pdev, resourceColorSpace, pcs->id);
944
 
    if (pres == NULL) {
945
 
        stream s;
946
 
 
947
 
        s_init(&s, pdev->memory);
948
 
        swrite_position_only(&s);
949
 
        code = cs_serialize(pcs, &s);
950
 
        if (code < 0)
951
 
            return_error(gs_error_unregistered); /* Must not happen. */
952
 
        serialized_size = stell(&s);
953
 
        sclose(&s);
954
 
        if (serialized_size <= sizeof(serialized0))
955
 
            serialized = serialized0;
956
 
        else {
957
 
            serialized = gs_alloc_bytes(pdev->pdf_memory, serialized_size, "pdf_color_space");
958
 
            if (serialized == NULL)
959
 
                return_error(gs_error_VMerror);
960
 
        }
961
 
        swrite_string(&s, serialized, serialized_size);
962
 
        code = cs_serialize(pcs, &s);
963
 
        if (code < 0)
964
 
            return_error(gs_error_unregistered); /* Must not happen. */
965
 
        if (stell(&s) != serialized_size)
966
 
            return_error(gs_error_unregistered); /* Must not happen. */
967
 
        sclose(&s);
968
 
        pres = pdf_find_cspace_resource(pdev, serialized, serialized_size);
969
 
        if (pres != NULL) {
970
 
            if (serialized != serialized0)
971
 
                gs_free_object(pdev->pdf_memory, serialized, "pdf_color_space");
972
 
            serialized = NULL;
973
 
        }
974
 
    }
975
 
    if (pres) {
976
 
        const pdf_color_space_t *const ppcs =
977
 
            (const pdf_color_space_t *)pres;
978
 
 
979
 
        if (ppranges != 0 && ppcs->ranges != 0)
980
 
            *ppranges = ppcs->ranges;
981
 
        pca = (cos_array_t *)pres->object;
982
 
        goto ret;
983
 
    }
984
 
 
985
 
    /* Space has parameters -- create an array. */
986
 
    pca = cos_array_alloc(pdev, "pdf_color_space");
987
 
    if (pca == 0)
988
 
        return_error(gs_error_VMerror);
989
 
 
990
 
    switch (csi) {
991
 
 
992
 
    case gs_color_space_index_ICC:
993
 
        code = pdf_iccbased_color_space(pdev, pvalue, pcs, pca);
994
 
        break;
995
 
 
996
 
    case gs_color_space_index_CIEA: {
997
 
        /* Check that we can represent this as a CalGray space. */
998
 
        const gs_cie_a *pcie = pcs->params.a;
999
 
        bool unitary = cie_ranges_are_0_1(&pcie->RangeA, 1);
1000
 
        bool identityA = (pcie->MatrixA.u == 1 && pcie->MatrixA.v == 1 &&
1001
 
                          pcie->MatrixA.w == 1);
1002
 
        gs_vector3 expts;
1003
 
 
1004
 
        pciec = (const gs_cie_common *)pcie;
1005
 
        if (!pcie->common.MatrixLMN.is_identity) {
1006
 
            code = pdf_convert_cie_space(pdev, pca, pcs, "GRAY", pciec,
1007
 
                                         &pcie->RangeA, ONE_STEP_NOT, NULL,
1008
 
                                         &ranges);
1009
 
            break;
1010
 
        }
1011
 
        if (unitary && identityA &&
1012
 
            CIE_CACHE_IS_IDENTITY(&pcie->caches.DecodeA) &&
1013
 
            CIE_SCALAR3_CACHE_IS_EXPONENTIAL(pcie->common.caches.DecodeLMN, expts) &&
1014
 
            expts.v == expts.u && expts.w == expts.u
1015
 
            ) {
1016
 
            DO_NOTHING;
1017
 
        } else if (unitary && identityA &&
1018
 
                   CIE_CACHE3_IS_IDENTITY(pcie->common.caches.DecodeLMN) &&
1019
 
                   cie_vector_cache_is_exponential(&pcie->caches.DecodeA, &expts.u)
1020
 
                   ) {
1021
 
            DO_NOTHING;
1022
 
        } else {
1023
 
            code = pdf_convert_cie_space(pdev, pca, pcs, "GRAY", pciec,
1024
 
                                         &pcie->RangeA, ONE_STEP_NOT, NULL,
1025
 
                                         &ranges);
1026
 
            break;
1027
 
        }
1028
 
        code = cos_array_add(pca, cos_c_string_value(&v, "/CalGray"));
1029
 
        if (code < 0)
1030
 
            return code;
1031
 
        pcd = cos_dict_alloc(pdev, "pdf_color_space(dict)");
1032
 
        if (pcd == 0)
1033
 
            return_error(gs_error_VMerror);
1034
 
        if (expts.u != 1) {
1035
 
            code = cos_dict_put_c_key_real(pcd, "/Gamma", expts.u);
1036
 
            if (code < 0)
1037
 
                return code;
1038
 
        }
1039
 
    }
1040
 
    cal:
1041
 
    /* Finish handling a CIE-based color space (Calxxx or Lab). */
1042
 
    if (code < 0)
1043
 
        return code;
1044
 
    code = pdf_finish_cie_space(pca, pcd, pciec);
1045
 
    break;
1046
 
 
1047
 
    case gs_color_space_index_CIEABC: {
1048
 
        /* Check that we can represent this as a CalRGB space. */
1049
 
        const gs_cie_abc *pcie = pcs->params.abc;
1050
 
        bool unitary = cie_ranges_are_0_1(pcie->RangeABC.ranges, 3);
1051
 
        gs_vector3 expts;
1052
 
        const gs_matrix3 *pmat = NULL;
1053
 
        cie_cache_one_step_t one_step =
1054
 
            cie_cached_abc_is_one_step(pcie, &pmat);
1055
 
 
1056
 
        pciec = (const gs_cie_common *)pcie;
1057
 
        if (unitary) {
1058
 
            switch (one_step) {
1059
 
            case ONE_STEP_ABC:
1060
 
                if (CIE_VECTOR3_CACHE_IS_EXPONENTIAL(pcie->caches.DecodeABC.caches, expts))
1061
 
                    goto calrgb;
1062
 
                break;
1063
 
            case ONE_STEP_LMN:
1064
 
                if (CIE_SCALAR3_CACHE_IS_EXPONENTIAL(pcie->common.caches.DecodeLMN, expts))
1065
 
                    goto calrgb;
1066
 
            default:
1067
 
                break;
1068
 
            }
1069
 
        }
1070
 
        if (cie_is_lab(pcie)) {
1071
 
            /* Represent this as a Lab space. */
1072
 
            pcd = cos_dict_alloc(pdev, "pdf_color_space(dict)");
1073
 
            if (pcd == 0)
1074
 
                return_error(gs_error_VMerror);
1075
 
            code = pdf_put_lab_color_space(pca, pcd, pcie->RangeABC.ranges);
1076
 
            goto cal;
1077
 
        } else {
1078
 
            code = pdf_convert_cie_space(pdev, pca, pcs, "RGB ", pciec,
1079
 
                                         pcie->RangeABC.ranges,
1080
 
                                         one_step, pmat, &ranges);
1081
 
            break;
1082
 
        }
1083
 
    calrgb:
1084
 
        code = cos_array_add(pca, cos_c_string_value(&v, "/CalRGB"));
1085
 
        if (code < 0)
1086
 
            return code;
1087
 
        pcd = cos_dict_alloc(pdev, "pdf_color_space(dict)");
1088
 
        if (pcd == 0)
1089
 
            return_error(gs_error_VMerror);
1090
 
        if (expts.u != 1 || expts.v != 1 || expts.w != 1) {
1091
 
            code = cos_dict_put_c_key_vector3(pcd, "/Gamma", &expts);
1092
 
            if (code < 0)
1093
 
                return code;
1094
 
        }
1095
 
        if (!pmat->is_identity) {
1096
 
            cos_array_t *pcma =
1097
 
                cos_array_alloc(pdev, "pdf_color_space(Matrix)");
1098
 
 
1099
 
            if (pcma == 0)
1100
 
                return_error(gs_error_VMerror);
1101
 
            if ((code = cos_array_add_vector3(pcma, &pmat->cu)) < 0 ||
1102
 
                (code = cos_array_add_vector3(pcma, &pmat->cv)) < 0 ||
1103
 
                (code = cos_array_add_vector3(pcma, &pmat->cw)) < 0 ||
1104
 
                (code = cos_dict_put(pcd, (const byte *)"/Matrix", 7,
1105
 
                                     COS_OBJECT_VALUE(&v, pcma))) < 0
1106
 
                )
1107
 
                return code;
1108
 
        }
1109
 
    }
1110
 
    goto cal;
1111
 
 
1112
 
    case gs_color_space_index_CIEDEF:
1113
 
        code = pdf_convert_cie_space(pdev, pca, pcs, "RGB ",
1114
 
                                     (const gs_cie_common *)pcs->params.def,
1115
 
                                     pcs->params.def->RangeDEF.ranges,
1116
 
                                     ONE_STEP_NOT, NULL, &ranges);
1117
 
        break;
1118
 
 
1119
 
    case gs_color_space_index_CIEDEFG:
1120
 
        code = pdf_convert_cie_space(pdev, pca, pcs, "CMYK",
1121
 
                                     (const gs_cie_common *)pcs->params.defg,
1122
 
                                     pcs->params.defg->RangeDEFG.ranges,
1123
 
                                     ONE_STEP_NOT, NULL, &ranges);
1124
 
        break;
1125
 
 
1126
 
    case gs_color_space_index_Indexed:
1127
 
        code = pdf_indexed_color_space(pdev, pvalue, pcs, pca);
1128
 
        break;
1129
 
 
1130
 
    case gs_color_space_index_DeviceN:
1131
 
        if (!pdev->PreserveDeviceN)
1132
 
            return_error(gs_error_rangecheck);
1133
 
        if (pdev->CompatibilityLevel < 1.3)
1134
 
            return_error(gs_error_rangecheck);
1135
 
        pfn = gs_cspace_get_devn_function(pcs);
1136
 
        /****** CURRENTLY WE ONLY HANDLE Functions ******/
1137
 
        if (pfn == 0)
1138
 
            return_error(gs_error_rangecheck);
1139
 
        {
1140
 
            cos_array_t *psna =
1141
 
                cos_array_alloc(pdev, "pdf_color_space(DeviceN)");
1142
 
            int i;
1143
 
            byte *name_string;
1144
 
            uint name_string_length;
1145
 
            cos_value_t v_attriburtes, *va = NULL;
1146
 
 
1147
 
            if (psna == 0)
1148
 
                return_error(gs_error_VMerror);
1149
 
            for (i = 0; i < pcs->params.device_n.num_components; ++i) {
1150
 
                if ((code = pcs->params.device_n.get_colorname_string(
1151
 
                                  pdev->memory,
1152
 
                                  pcs->params.device_n.names[i], &name_string,
1153
 
                                  &name_string_length)) < 0 ||
1154
 
                    (code = pdf_string_to_cos_name(pdev, name_string,
1155
 
                                  name_string_length, &v)) < 0 ||
1156
 
                    (code = cos_array_add_no_copy(psna, &v)) < 0)
1157
 
                    return code;
1158
 
            }
1159
 
            COS_OBJECT_VALUE(&v, psna);
1160
 
            if (pcs->params.device_n.colorants != NULL) {
1161
 
                cos_dict_t *colorants  = cos_dict_alloc(pdev, "pdf_color_space(DeviceN)");
1162
 
                cos_value_t v_colorants, v_separation, v_colorant_name;
1163
 
                const gs_device_n_attributes *csa;
1164
 
                pdf_resource_t *pres_attributes;
1165
 
 
1166
 
                if (colorants == NULL)
1167
 
                    return_error(gs_error_VMerror);
1168
 
                code = pdf_alloc_resource(pdev, resourceOther, 0, &pres_attributes, -1);
1169
 
                if (code < 0)
1170
 
                    return code;
1171
 
                cos_become(pres_attributes->object, cos_type_dict);
1172
 
                COS_OBJECT_VALUE(&v_colorants, colorants);
1173
 
                code = cos_dict_put((cos_dict_t *)pres_attributes->object,
1174
 
                    (const byte *)"/Colorants", 10, &v_colorants);
1175
 
                if (code < 0)
1176
 
                    return code;
1177
 
                for (csa = pcs->params.device_n.colorants; csa != NULL; csa = csa->next) {
1178
 
                    code = pcs->params.device_n.get_colorname_string(pdev->memory,
1179
 
                                  csa->colorant_name, &name_string, &name_string_length);
1180
 
                    if (code < 0)
1181
 
                        return code;
1182
 
                    code = pdf_color_space_named(pdev, &v_separation, NULL, csa->cspace, pcsn, false, NULL, 0);
1183
 
                    if (code < 0)
1184
 
                        return code;
1185
 
                    code = pdf_string_to_cos_name(pdev, name_string, name_string_length, &v_colorant_name);
1186
 
                    if (code < 0)
1187
 
                        return code;
1188
 
                    code = cos_dict_put(colorants, v_colorant_name.contents.chars.data,
1189
 
                                        v_colorant_name.contents.chars.size, &v_separation);
1190
 
                    if (code < 0)
1191
 
                        return code;
1192
 
                }
1193
 
                code = pdf_substitute_resource(pdev, &pres_attributes, resourceOther, NULL, true);
1194
 
                if (code < 0)
1195
 
                    return code;
1196
 
                pres_attributes->where_used |= pdev->used_mask;
1197
 
                va = &v_attriburtes;
1198
 
                COS_OBJECT_VALUE(va, pres_attributes->object);
1199
 
            }
1200
 
            if ((code = pdf_separation_color_space(pdev, pca, "/DeviceN", &v,
1201
 
                                                   pcs->base_space,
1202
 
                                        pfn, &pdf_color_space_names, va)) < 0)
1203
 
                return code;
1204
 
        }
1205
 
        break;
1206
 
 
1207
 
    case gs_color_space_index_Separation:
1208
 
        if (!pdev->PreserveSeparation)
1209
 
            return_error(gs_error_rangecheck);
1210
 
        pfn = gs_cspace_get_sepr_function(pcs);
1211
 
        /****** CURRENTLY WE ONLY HANDLE Functions ******/
1212
 
        if (pfn == 0)
1213
 
            return_error(gs_error_rangecheck);
1214
 
        {
1215
 
            byte *name_string;
1216
 
            uint name_string_length;
1217
 
            if ((code = pcs->params.separation.get_colorname_string(
1218
 
                                  pdev->memory,
1219
 
                                  pcs->params.separation.sep_name, &name_string,
1220
 
                                  &name_string_length)) < 0 ||
1221
 
                (code = pdf_string_to_cos_name(pdev, name_string,
1222
 
                                      name_string_length, &v)) < 0 ||
1223
 
                (code = pdf_separation_color_space(pdev, pca, "/Separation", &v,
1224
 
                                            pcs->base_space,
1225
 
                                            pfn, &pdf_color_space_names, NULL)) < 0)
1226
 
                return code;
1227
 
        }
1228
 
        break;
1229
 
 
1230
 
    case gs_color_space_index_Pattern:
1231
 
        if ((code = pdf_color_space_named(pdev, pvalue, ppranges,
1232
 
                                    pcs->base_space,
1233
 
                                    &pdf_color_space_names, false, NULL, 0)) < 0 ||
1234
 
            (code = cos_array_add(pca,
1235
 
                                  cos_c_string_value(&v, "/Pattern"))) < 0 ||
1236
 
            (code = cos_array_add(pca, pvalue)) < 0
1237
 
            )
1238
 
            return code;
1239
 
        break;
1240
 
 
1241
 
    default:
1242
 
        return_error(gs_error_rangecheck);
1243
 
    }
1244
 
 
1245
 
    /*
1246
 
     * Register the color space as a resource, since it must be referenced
1247
 
     * by name rather than directly.
1248
 
     */
1249
 
    {
1250
 
        pdf_color_space_t *ppcs;
1251
 
 
1252
 
        if (code < 0 ||
1253
 
            (code = pdf_alloc_resource(pdev, resourceColorSpace, pcs->id,
1254
 
                                       &pres, -1)) < 0
1255
 
            ) {
1256
 
            COS_FREE(pca, "pdf_color_space");
1257
 
            return code;
1258
 
        }
1259
 
        pdf_reserve_object_id(pdev, pres, 0);
1260
 
        if (res_name != NULL) {
1261
 
            int l = min(name_length, sizeof(pres->rname) - 1);
1262
 
 
1263
 
            memcpy(pres->rname, res_name, l);
1264
 
            pres->rname[l] = 0;
1265
 
        }
1266
 
        ppcs = (pdf_color_space_t *)pres;
1267
 
        if (serialized == serialized0) {
1268
 
            serialized = gs_alloc_bytes(pdev->pdf_memory, serialized_size, "pdf_color_space");
1269
 
            if (serialized == NULL)
1270
 
                return_error(gs_error_VMerror);
1271
 
            memcpy(serialized, serialized0, serialized_size);
1272
 
        }
1273
 
        ppcs->serialized = serialized;
1274
 
        ppcs->serialized_size = serialized_size;
1275
 
        if (ranges) {
1276
 
            int num_comp = gs_color_space_num_components(pcs);
1277
 
            gs_range_t *copy_ranges = (gs_range_t *)
1278
 
                gs_alloc_byte_array(pdev->pdf_memory, num_comp,
1279
 
                                    sizeof(gs_range_t), "pdf_color_space");
1280
 
 
1281
 
            if (copy_ranges == 0) {
1282
 
                COS_FREE(pca, "pdf_color_space");
1283
 
                return_error(gs_error_VMerror);
1284
 
            }
1285
 
            memcpy(copy_ranges, ranges, num_comp * sizeof(gs_range_t));
1286
 
            ppcs->ranges = copy_ranges;
1287
 
            if (ppranges)
1288
 
                *ppranges = copy_ranges;
1289
 
        } else
1290
 
            ppcs->ranges = 0;
1291
 
        pca->id = pres->object->id;
1292
 
        COS_FREE(pres->object, "pdf_color_space");
1293
 
        pres->object = (cos_object_t *)pca;
1294
 
        cos_write_object(COS_OBJECT(pca), pdev, resourceColorSpace);
1295
 
    }
1296
 
 ret:
1297
 
    if (by_name) {
1298
 
        /* Return a resource name rather than an object reference. */
1299
 
        discard(COS_RESOURCE_VALUE(pvalue, pca));
1300
 
    } else
1301
 
        discard(COS_OBJECT_VALUE(pvalue, pca));
1302
 
    if (pres != NULL) {
1303
 
        pres->where_used |= pdev->used_mask;
1304
 
        code = pdf_add_resource(pdev, pdev->substream_Resources, "/ColorSpace", pres);
1305
 
        if (code < 0)
1306
 
            return code;
1307
 
    }
1308
 
    return 0;
1309
 
}
1310
 
 
1311
 
int free_color_space(gx_device_pdf *pdev, pdf_resource_t *pres)
1312
 
{
1313
 
    pdf_color_space_t *ppcs = (pdf_color_space_t *)pres;
1314
 
 
1315
 
    if (ppcs->serialized)
1316
 
        gs_free_object(pdev->pdf_memory, ppcs->serialized, "free serialized colour space");
1317
 
    if (pres->object) {
1318
 
        cos_release(pres->object, "release ColorSpace object");
1319
 
        gs_free_object(pdev->pdf_memory, pres->object, "free ColorSpace object");
1320
 
        pres->object = 0;
1321
 
    }
1322
 
    return 0;
1323
 
}
1324
 
 
1325
 
/* ---------------- Miscellaneous ---------------- */
1326
 
 
1327
 
/* Create colored and uncolored Pattern color spaces. */
1328
 
static int
1329
 
pdf_pattern_space(gx_device_pdf *pdev, cos_value_t *pvalue,
1330
 
                  pdf_resource_t **ppres, const char *cs_name)
1331
 
{
1332
 
    int code;
1333
 
 
1334
 
    if (!*ppres) {
1335
 
        int code = pdf_begin_resource_body(pdev, resourceColorSpace, gs_no_id,
1336
 
                                           ppres);
1337
 
 
1338
 
        if (code < 0)
1339
 
            return code;
1340
 
        pprints1(pdev->strm, "%s\n", cs_name);
1341
 
        pdf_end_resource(pdev, resourceColorSpace);
1342
 
        (*ppres)->object->written = true; /* don't write at end */
1343
 
        ((pdf_color_space_t *)*ppres)->ranges = 0;
1344
 
        ((pdf_color_space_t *)*ppres)->serialized = 0;
1345
 
    }
1346
 
    code = pdf_add_resource(pdev, pdev->substream_Resources, "/ColorSpace", *ppres);
1347
 
    if (code < 0)
1348
 
        return code;
1349
 
    cos_resource_value(pvalue, (*ppres)->object);
1350
 
    return 0;
1351
 
}
1352
 
int
1353
 
pdf_cs_Pattern_colored(gx_device_pdf *pdev, cos_value_t *pvalue)
1354
 
{
1355
 
    return pdf_pattern_space(pdev, pvalue, &pdev->cs_Patterns[0],
1356
 
                             "[/Pattern]");
1357
 
}
1358
 
int
1359
 
pdf_cs_Pattern_uncolored(gx_device_pdf *pdev, cos_value_t *pvalue)
1360
 
{
1361
 
    /* Only for process colors. */
1362
 
    int ncomp = pdev->color_info.num_components;
1363
 
    static const char *const pcs_names[5] = {
1364
 
        0, "[/Pattern /DeviceGray]", 0, "[/Pattern /DeviceRGB]",
1365
 
        "[/Pattern /DeviceCMYK]"
1366
 
    };
1367
 
 
1368
 
    return pdf_pattern_space(pdev, pvalue, &pdev->cs_Patterns[ncomp],
1369
 
                             pcs_names[ncomp]);
1370
 
}
1371
 
int
1372
 
pdf_cs_Pattern_uncolored_hl(gx_device_pdf *pdev,
1373
 
                const gs_color_space *pcs, cos_value_t *pvalue)
1374
 
{
1375
 
    /* Only for high level colors. */
1376
 
    return pdf_color_space_named(pdev, pvalue, NULL, pcs, &pdf_color_space_names, true, NULL, 0);
1377
 
}
1378
 
 
1379
 
/* Set the ProcSets bits corresponding to an image color space. */
1380
 
void
1381
 
pdf_color_space_procsets(gx_device_pdf *pdev, const gs_color_space *pcs)
1382
 
{
1383
 
    const gs_color_space *pbcs = pcs;
1384
 
 
1385
 
 csw:
1386
 
    switch (gs_color_space_get_index(pbcs)) {
1387
 
    case gs_color_space_index_DeviceGray:
1388
 
    case gs_color_space_index_CIEA:
1389
 
        /* We only handle CIEBasedA spaces that map to CalGray. */
1390
 
        pdev->procsets |= ImageB;
1391
 
        break;
1392
 
    case gs_color_space_index_Indexed:
1393
 
        pdev->procsets |= ImageI;
1394
 
        pbcs = pcs->base_space;
1395
 
        goto csw;
1396
 
    default:
1397
 
        pdev->procsets |= ImageC;
1398
 
        break;
1399
 
    }
1400
 
}