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

« back to all changes in this revision

Viewing changes to base/gdevpdfv.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 value writing for pdfwrite driver */
18
 
#include "math_.h"
19
 
#include "string_.h"
20
 
#include "gx.h"
21
 
#include "gscindex.h"
22
 
#include "gserrors.h"
23
 
#include "gsiparm3.h"           /* for pattern colors */
24
 
#include "gsmatrix.h"           /* for gspcolor.h */
25
 
#include "gscoord.h"            /* for gs_currentmatrix, requires gsmatrix.h */
26
 
#include "gsptype2.h"
27
 
#include "gxcolor2.h"           /* for gxpcolor.h */
28
 
#include "gxdcolor.h"           /* for gxpcolor.h */
29
 
#include "gxpcolor.h"           /* for pattern device color types */
30
 
#include "gxshade.h"
31
 
#include "gdevpdfx.h"
32
 
#include "gdevpdfg.h"
33
 
#include "gdevpdfo.h"
34
 
 
35
 
/* Import the PatternType 2 Pattern device color type. */
36
 
extern const gx_device_color_type_t gx_dc_pattern2;
37
 
 
38
 
/*
39
 
 * Define the scaling and range of values written for mesh shadings.
40
 
 * BitsPerCoordinate is always 24; BitsPerComponent (for colors) is
41
 
 * always 16.
42
 
 */
43
 
#define ENCODE_VALUE(v, emax, vmin, vmax)\
44
 
  ( ((v) - (vmin)) * ((double)(emax) / ((vmax) - (vmin))) )
45
 
/*
46
 
 * Because of the Acrobat Reader limitation noted in gdevpdfx.h,
47
 
 * we must limit coordinate values to 14 bits.
48
 
 */
49
 
#define MIN_MESH_COORDINATE (-0x400000 / 256.0)
50
 
#define MAX_MESH_COORDINATE ( 0x3fffff / 256.0)
51
 
#define ENCODE_MESH_COORDINATE(v)\
52
 
  ENCODE_VALUE(v, 0xffffff, MIN_MESH_COORDINATE, MAX_MESH_COORDINATE)
53
 
 
54
 
#define MIN_MESH_COLOR_INDEX 0
55
 
#define MAX_MESH_COLOR_INDEX 0xffff
56
 
#define ENCODE_MESH_COLOR_INDEX(v) ((v) + MIN_MESH_COLOR_INDEX)
57
 
 
58
 
#define ENCODE_MESH_COMPONENT(v, vmin, vmax)\
59
 
  ENCODE_VALUE(v, 0xffff, vmin, vmax)
60
 
 
61
 
/* ---------------- Utilities ---------------- */
62
 
 
63
 
/* Write a matrix parameter. */
64
 
static int
65
 
cos_dict_put_matrix(cos_dict_t *pscd, const char *key, const gs_matrix *pmat)
66
 
{
67
 
    float matrix[6];
68
 
 
69
 
    matrix[0] = pmat->xx;
70
 
    matrix[1] = pmat->xy;
71
 
    matrix[2] = pmat->yx;
72
 
    matrix[3] = pmat->yy;
73
 
    matrix[4] = pmat->tx;
74
 
    matrix[5] = pmat->ty;
75
 
    return cos_dict_put_c_key_floats(pscd, key, matrix, 6);
76
 
}
77
 
 
78
 
/* ---------------- PatternType 1 colors ---------------- */
79
 
 
80
 
/*
81
 
 * Create a Pattern resource referencing an image (currently only an XObject).
82
 
 * p_tile is NULL for uncolored patterns or the NULL pattern.
83
 
 * m_tile is NULL for colored patterns that fill their bounding box,
84
 
 * including the NULL pattern.
85
 
 ****** WE DON'T HANDLE NULL PATTERNS YET ******
86
 
 */
87
 
static uint
88
 
tile_size(const gx_strip_bitmap *tile, int depth)
89
 
{
90
 
    return (tile->rep_width * depth + 7) / 8 * tile->rep_height;
91
 
}
92
 
static bool
93
 
tile_size_ok(const gx_device_pdf *pdev, const gx_color_tile *p_tile,
94
 
             const gx_color_tile *m_tile)
95
 
{
96
 
    /*
97
 
     * Acrobat Reader can't handle image Patterns with more than
98
 
     * 64K of data.  :-(
99
 
     */
100
 
    uint p_size =
101
 
        (p_tile == 0 ? 0 : tile_size(&p_tile->tbits, p_tile->depth));
102
 
    uint m_size =
103
 
        (m_tile == 0 ? 0 : tile_size(&m_tile->tmask, 1));
104
 
    /* The image limit only applies to Acrobat versions less than 5
105
 
     * (PDF 1.4).
106
 
     */
107
 
    if (pdev->CompatibilityLevel < 1.4)
108
 
        return (max(p_size, m_size) <= 65500);
109
 
    else
110
 
        return 1;
111
 
}
112
 
 
113
 
static int
114
 
pdf_pattern(gx_device_pdf *pdev, const gx_drawing_color *pdc,
115
 
            const gx_color_tile *p_tile, const gx_color_tile *m_tile,
116
 
            cos_stream_t *pcs_image, pdf_resource_t **ppres)
117
 
{
118
 
    pdf_resource_t *pres;
119
 
    int code = pdf_alloc_resource(pdev, resourcePattern, pdc->mask.id, ppres,
120
 
                                  0L);
121
 
    cos_stream_t *pcos;
122
 
    cos_dict_t *pcd;
123
 
    cos_dict_t *pcd_Resources = cos_dict_alloc(pdev, "pdf_pattern(Resources)");
124
 
    const gx_color_tile *tile = (p_tile ? p_tile : m_tile);
125
 
    const gx_strip_bitmap *btile = (p_tile ? &p_tile->tbits : &m_tile->tmask);
126
 
    bool mask = p_tile == 0;
127
 
    gs_point step;
128
 
    gs_matrix smat;
129
 
 
130
 
    if (code < 0)
131
 
        return code;
132
 
    if (!tile_size_ok(pdev, p_tile, m_tile))
133
 
        return_error(gs_error_limitcheck);
134
 
    /*
135
 
     * We currently can't handle Patterns whose X/Y step isn't parallel
136
 
     * to the coordinate axes.
137
 
     */
138
 
    if (is_xxyy(&tile->step_matrix))
139
 
        step.x = tile->step_matrix.xx, step.y = tile->step_matrix.yy;
140
 
    else if (is_xyyx(&tile->step_matrix))
141
 
        step.x = tile->step_matrix.yx, step.y = tile->step_matrix.xy;
142
 
    else
143
 
        return_error(gs_error_rangecheck);
144
 
    if (pcd_Resources == 0)
145
 
        return_error(gs_error_VMerror);
146
 
    gs_make_identity(&smat);
147
 
    smat.xx = btile->rep_width / (pdev->HWResolution[0] / 72.0);
148
 
    smat.yy = btile->rep_height / (pdev->HWResolution[1] / 72.0);
149
 
    smat.tx = tile->step_matrix.tx / (pdev->HWResolution[0] / 72.0);
150
 
    smat.ty = tile->step_matrix.ty / (pdev->HWResolution[1] / 72.0);
151
 
    pres = *ppres;
152
 
    {
153
 
        cos_dict_t *pcd_XObject = cos_dict_alloc(pdev, "pdf_pattern(XObject)");
154
 
        char key[MAX_REF_CHARS + 3];
155
 
        cos_value_t v;
156
 
        cos_object_t *object;
157
 
 
158
 
        if (pcd_XObject == 0)
159
 
            return_error(gs_error_VMerror);
160
 
        sprintf(key, "/R%ld", pcs_image->id);
161
 
        /* This is non-obvious code. Previously we would put the image object (pcs_image)
162
 
         * into the Resources dit. When we come to write out the Resources dict
163
 
         * that code writes a reference (index 0 R) using the ID from the object.
164
 
         * However that means we have two pointers to the XObject. One in the chain
165
 
         * of resoruces (which we need in order to write teh XObject) and one from
166
 
         * the pattern here. That seriously messes up memory handling. So instead
167
 
         * we now make a new object, and copy the id from the pcs_image. Since that's
168
 
         * all that the writing code will use, we cna avoid the double pointers.
169
 
         */
170
 
        object = cos_reference_alloc(pdev, "pdf_pattern(reference copy of XObject)");
171
 
        object->id = pcs_image->id;
172
 
        COS_OBJECT_VALUE(&v, object);
173
 
        if ((code = cos_dict_put(pcd_XObject, (byte *)key, strlen(key), &v)) < 0 ||
174
 
            (code = cos_dict_put_c_key_object(pcd_Resources, "/XObject",
175
 
                                              COS_OBJECT(pcd_XObject))) < 0
176
 
            )
177
 
            return code;
178
 
    }
179
 
    if ((code = cos_dict_put_c_strings(pcd_Resources, "/ProcSet",
180
 
                                       (mask ? "[/PDF/ImageB]" :
181
 
                                        "[/PDF/ImageC]"))) < 0)
182
 
        return code;
183
 
    cos_become(pres->object, cos_type_stream);
184
 
    pcos = (cos_stream_t *)pres->object;
185
 
    pcd = cos_stream_dict(pcos);
186
 
    if ((code = cos_dict_put_c_key_int(pcd, "/PatternType", 1)) < 0 ||
187
 
        (code = cos_dict_put_c_key_int(pcd, "/PaintType",
188
 
                                       (mask ? 2 : 1))) < 0 ||
189
 
        (code = cos_dict_put_c_key_int(pcd, "/TilingType",
190
 
                                       tile->tiling_type)) < 0 ||
191
 
        (code = cos_dict_put_c_key_object(pcd, "/Resources",
192
 
                                          COS_OBJECT(pcd_Resources))) < 0 ||
193
 
        (code = cos_dict_put_c_strings(pcd, "/BBox", "[0 0 1 1]")) < 0 ||
194
 
        (code = cos_dict_put_matrix(pcd, "/Matrix", &smat)) < 0 ||
195
 
        (code = cos_dict_put_c_key_real(pcd, "/XStep", step.x / btile->rep_width)) < 0 ||
196
 
        (code = cos_dict_put_c_key_real(pcd, "/YStep", step.y / btile->rep_height)) < 0
197
 
        ) {
198
 
        return code;
199
 
    }
200
 
 
201
 
    {
202
 
        char buf[MAX_REF_CHARS + 6 + 1]; /* +6 for /R# Do\n */
203
 
 
204
 
        sprintf(buf, "/R%ld Do\n", pcs_image->id);
205
 
        cos_stream_add_bytes(pcos, (const byte *)buf, strlen(buf));
206
 
    }
207
 
 
208
 
    return 0;
209
 
}
210
 
 
211
 
/* Store pattern 1 parameters to cos dictionary. */
212
 
int
213
 
pdf_store_pattern1_params(gx_device_pdf *pdev, pdf_resource_t *pres,
214
 
                        gs_pattern1_instance_t *pinst)
215
 
{
216
 
    gs_pattern1_template_t *t = &pinst->templat;
217
 
    gs_matrix smat2 = ctm_only((gs_imager_state *)pinst->saved), smat;
218
 
    double scale_x = pdev->HWResolution[0] / 72.0;
219
 
    double scale_y = pdev->HWResolution[1] / 72.0;
220
 
    cos_dict_t *pcd = cos_stream_dict((cos_stream_t *)pres->object);
221
 
    cos_dict_t *pcd_Resources = cos_dict_alloc(pdev, "pdf_pattern(Resources)");
222
 
    float bbox[4];
223
 
    int code;
224
 
 
225
 
    if (pcd == NULL || pcd_Resources == NULL)
226
 
        return_error(gs_error_VMerror);
227
 
    pdev->substream_Resources = pcd_Resources;
228
 
    bbox[0] = t->BBox.p.x;
229
 
    bbox[1] = t->BBox.p.y;
230
 
    bbox[2] = t->BBox.q.x;
231
 
    bbox[3] = t->BBox.q.y;
232
 
    /* The graphics library assumes a shifted origin to provide
233
 
       positive bitmap pixel indices. Compensate it now. */
234
 
    smat2.tx += pinst->step_matrix.tx;
235
 
    smat2.ty += pinst->step_matrix.ty;
236
 
    /*
237
 
     * In PDF, the Matrix is the transformation from the pattern space to
238
 
     * the *default* user coordinate space, not the current space.
239
 
     * NB. For a form the default space is the parent. This means that when a
240
 
     * form is nested inside a form, the default space is the space of the
241
 
     * first form, and therefore we do *not* remove the resolution scaling.
242
 
     */
243
 
    if (pdev->FormDepth == 0) {
244
 
        gs_matrix scaled;
245
 
 
246
 
        gs_make_scaling(1 / scale_x, 1 / scale_y, &scaled);
247
 
        gs_matrix_multiply(&smat2, &scaled, &smat);
248
 
    } else {
249
 
        smat = smat2;
250
 
    }
251
 
    if (pdev->ForOPDFRead) {
252
 
        if (pdev->PatternDepth) {
253
 
            gs_matrix_multiply(&smat, &pdev->AccumulatedPatternMatrix, &smat2);
254
 
            gs_matrix_multiply(&pdev->AccumulatedPatternMatrix, &smat, &pdev->AccumulatedPatternMatrix);
255
 
            smat = smat2;
256
 
        } else {
257
 
            gs_make_identity(&pdev->AccumulatedPatternMatrix);
258
 
            gs_matrix_multiply(&pdev->AccumulatedPatternMatrix, &smat, &pdev->AccumulatedPatternMatrix);
259
 
        }
260
 
    }
261
 
    if (any_abs(smat.tx) < 0.0001)  /* Noise. */
262
 
        smat.tx = 0;
263
 
    if (any_abs(smat.ty) < 0.0001)
264
 
        smat.ty = 0;
265
 
    code = cos_dict_put_c_strings(pcd, "/Type", "/Pattern");
266
 
    if (code >= 0)
267
 
        code = cos_dict_put_c_key_int(pcd, "/PatternType", 1);
268
 
    if (code >= 0)
269
 
        code = cos_dict_put_c_key_int(pcd, "/PaintType", t->PaintType);
270
 
    if (code >= 0)
271
 
        code = cos_dict_put_c_key_int(pcd, "/TilingType", t->TilingType);
272
 
    if (code >= 0)
273
 
        code = cos_dict_put_c_key_floats(pcd, "/BBox", bbox, 4);
274
 
    if (code >= 0)
275
 
        code = cos_dict_put_matrix(pcd, "/Matrix", &smat);
276
 
    if (code >= 0)
277
 
        code = cos_dict_put_c_key_real(pcd, "/XStep", t->XStep);
278
 
    if (code >= 0)
279
 
        code = cos_dict_put_c_key_real(pcd, "/YStep", t->YStep);
280
 
    if (code >= 0)
281
 
        code = cos_dict_put_c_key_object(pcd, "/Resources", COS_OBJECT(pcd_Resources));
282
 
    pdev->skip_colors = (t->PaintType == 2);
283
 
    return code;
284
 
}
285
 
 
286
 
/* Set the ImageMatrix, Width, and Height for a Pattern image. */
287
 
static void
288
 
pdf_set_pattern_image(gs_data_image_t *pic, const gx_strip_bitmap *tile)
289
 
{
290
 
    pic->ImageMatrix.xx = (float)(pic->Width = tile->rep_width);
291
 
    pic->ImageMatrix.yy = (float)(pic->Height = tile->rep_height);
292
 
}
293
 
 
294
 
/* Write the mask for a Pattern (colored or uncolored). */
295
 
static int
296
 
pdf_put_pattern_mask(gx_device_pdf *pdev, const gx_color_tile *m_tile,
297
 
                     cos_stream_t **ppcs_mask)
298
 
{
299
 
    int w = m_tile->tmask.rep_width, h = m_tile->tmask.rep_height;
300
 
    gs_image1_t image;
301
 
    pdf_image_writer writer;
302
 
    int code;
303
 
 
304
 
    gs_image_t_init_mask_adjust(&image, true, false);
305
 
    pdf_set_pattern_image((gs_data_image_t *)&image, &m_tile->tmask);
306
 
    pdf_image_writer_init(&writer);
307
 
    if ((code = pdf_begin_write_image(pdev, &writer, gs_no_id, w, h, NULL, false)) < 0 ||
308
 
        (pdev->params.MonoImage.Encode &&
309
 
         (code = psdf_CFE_binary(&writer.binary[0], w, h, true)) < 0) ||
310
 
        (code = pdf_begin_image_data(pdev, &writer, (const gs_pixel_image_t *)&image, NULL, 0)) < 0
311
 
        )
312
 
        return code;
313
 
    /* Pattern masks are specified in device coordinates, so invert Y. */
314
 
    if ((code = pdf_copy_mask_bits(writer.binary[0].strm, m_tile->tmask.data + (h - 1) * m_tile->tmask.raster, 0, -m_tile->tmask.raster, w, h, 0)) < 0 ||
315
 
        (code = pdf_end_image_binary(pdev, &writer, h)) < 0 ||
316
 
        (code = pdf_end_write_image(pdev, &writer)) < 0
317
 
        )
318
 
        return code;
319
 
    *ppcs_mask = (cos_stream_t *)writer.pres->object;
320
 
    return 0;
321
 
}
322
 
 
323
 
/* Write an uncolored Pattern color. */
324
 
int
325
 
pdf_put_uncolored_pattern(gx_device_pdf *pdev, const gx_drawing_color *pdc,
326
 
                          const gs_color_space *pcs,
327
 
                          const psdf_set_color_commands_t *ppscc,
328
 
                          bool have_pattern_streams, pdf_resource_t **ppres)
329
 
{
330
 
    const gx_color_tile *m_tile = pdc->mask.m_tile;
331
 
    gx_drawing_color dc_pure;
332
 
 
333
 
    if (!have_pattern_streams && m_tile == 0) {
334
 
        /*
335
 
         * If m_tile == 0, this uncolored Pattern is all 1's,
336
 
         * equivalent to a pure color.
337
 
         */
338
 
        *ppres = 0;
339
 
        set_nonclient_dev_color(&dc_pure, gx_dc_pure_color(pdc));
340
 
        return psdf_set_color((gx_device_vector *)pdev, &dc_pure, ppscc);
341
 
    } else {
342
 
        cos_value_t v;
343
 
        stream *s = pdev->strm;
344
 
        int code;
345
 
        cos_stream_t *pcs_image;
346
 
        static const psdf_set_color_commands_t no_scc = {0, 0, 0};
347
 
 
348
 
        if (!tile_size_ok(pdev, NULL, m_tile))
349
 
            return_error(gs_error_limitcheck);
350
 
        if (!have_pattern_streams) {
351
 
            if ((code = pdf_cs_Pattern_uncolored(pdev, &v)) < 0 ||
352
 
                (code = pdf_put_pattern_mask(pdev, m_tile, &pcs_image)) < 0 ||
353
 
                (code = pdf_pattern(pdev, pdc, NULL, m_tile, pcs_image, ppres)) < 0
354
 
                )
355
 
                return code;
356
 
        } else {
357
 
            code = pdf_cs_Pattern_uncolored_hl(pdev, pcs, &v);
358
 
            if (code < 0)
359
 
                return code;
360
 
            *ppres = pdf_find_resource_by_gs_id(pdev, resourcePattern, pdc->mask.id);
361
 
            *ppres = pdf_substitute_pattern(*ppres);
362
 
            if (!pdev->AR4_save_bug && pdev->CompatibilityLevel <= 1.3) {
363
 
                /* We reconnized AR4 behavior as reserving "q Q" stack elements
364
 
                 * on demand. It looks as processing a pattern stream
365
 
                 * with PaintType 1 AR4 replaces the topmost stack element
366
 
                 * instead allocating a new one, if it was not previousely allocated.
367
 
                 * AR 5 doesn't have this bug. Working around the AR4 bug here.
368
 
                 */
369
 
                stream_puts(pdev->strm, "q q Q Q\n");
370
 
                pdev->AR4_save_bug = true;
371
 
            }
372
 
            (*ppres)->where_used |= pdev->used_mask;
373
 
        }
374
 
        cos_value_write(&v, pdev);
375
 
        pprints1(s, " %s ", ppscc->setcolorspace);
376
 
        if (have_pattern_streams)
377
 
            return 0;
378
 
        set_nonclient_dev_color(&dc_pure, gx_dc_pure_color(pdc));
379
 
        return psdf_set_color((gx_device_vector *)pdev, &dc_pure, &no_scc);
380
 
    }
381
 
}
382
 
 
383
 
int
384
 
pdf_put_colored_pattern(gx_device_pdf *pdev, const gx_drawing_color *pdc,
385
 
                        const gs_color_space *pcs,
386
 
                        const psdf_set_color_commands_t *ppscc,
387
 
                        bool have_pattern_streams, pdf_resource_t **ppres)
388
 
{
389
 
    const gx_color_tile *p_tile = pdc->colors.pattern.p_tile;
390
 
    gs_color_space *pcs_Device;
391
 
    cos_value_t cs_value;
392
 
    cos_value_t v;
393
 
    int code;
394
 
    gs_image1_t image;
395
 
    const gx_color_tile *m_tile = NULL;
396
 
    pdf_image_writer writer;
397
 
    int w = p_tile->tbits.rep_width, h = p_tile->tbits.rep_height;
398
 
 
399
 
    if (!have_pattern_streams) {
400
 
        /*
401
 
         * NOTE: We assume here that the color space of the cached Pattern
402
 
         * is the same as the native color space of the device.  This will
403
 
         * have to change in the future!
404
 
         */
405
 
        /*
406
 
         * Check whether this colored pattern is actually a masked pure color,
407
 
         * by testing whether all the colored pixels have the same color.
408
 
         */
409
 
        m_tile = pdc->mask.m_tile;
410
 
        if (m_tile) {
411
 
            if (p_tile && !(p_tile->depth & 7) && p_tile->depth <= arch_sizeof_color_index * 8) {
412
 
                int depth_bytes = p_tile->depth >> 3;
413
 
                int width = p_tile->tbits.rep_width;
414
 
                int skip = p_tile->tbits.raster -
415
 
                    p_tile->tbits.rep_width * depth_bytes;
416
 
                const byte *bp;
417
 
                const byte *mp;
418
 
                int i, j, k;
419
 
                gx_color_index color = 0; /* init is arbitrary if not empty */
420
 
                bool first = true;
421
 
 
422
 
                for (i = 0, bp = p_tile->tbits.data, mp = p_tile->tmask.data;
423
 
                     i < p_tile->tbits.rep_height;
424
 
                     ++i, bp += skip, mp += p_tile->tmask.raster) {
425
 
 
426
 
                    for (j = 0; j < width; ++j) {
427
 
                        if (mp[j >> 3] & (0x80 >> (j & 7))) {
428
 
                            gx_color_index ci = 0;
429
 
 
430
 
                            for (k = 0; k < depth_bytes; ++k)
431
 
                                ci = (ci << 8) + *bp++;
432
 
                            if (first)
433
 
                                color = ci, first = false;
434
 
                            else if (ci != color)
435
 
                                goto not_pure;
436
 
                        } else
437
 
                            bp += depth_bytes;
438
 
                    }
439
 
                }
440
 
                {
441
 
                    /* Set the color, then handle as an uncolored pattern. */
442
 
                    gx_drawing_color dcolor;
443
 
 
444
 
                    dcolor = *pdc;
445
 
                    dcolor.colors.pure = color;
446
 
                    return pdf_put_uncolored_pattern(pdev, &dcolor, pcs, ppscc,
447
 
                                have_pattern_streams, ppres);
448
 
                }
449
 
            not_pure:
450
 
                DO_NOTHING;             /* required by MSVC */
451
 
            }
452
 
            if (pdev->CompatibilityLevel < 1.3) {
453
 
                /* Masked images are only supported starting in PDF 1.3. */
454
 
                return_error(gs_error_rangecheck);
455
 
            }
456
 
        }
457
 
        /* Acrobat Reader has a size limit for image Patterns. */
458
 
        if (!tile_size_ok(pdev, p_tile, m_tile))
459
 
            return_error(gs_error_limitcheck);
460
 
    }
461
 
    code = pdf_cs_Pattern_colored(pdev, &v);
462
 
    if (code < 0)
463
 
        return code;
464
 
    pdf_cspace_init_Device(pdev->memory, &pcs_Device, pdev->color_info.num_components);
465
 
    /*
466
 
     * We don't have to worry about color space scaling: the color
467
 
     * space is always a Device space.
468
 
     */
469
 
    code = pdf_color_space_named(pdev, &cs_value, NULL, pcs_Device,
470
 
                           &pdf_color_space_names, true, NULL, 0);
471
 
    if (code < 0)
472
 
        return code;
473
 
    if (!have_pattern_streams) {
474
 
        cos_stream_t *pcs_mask = 0;
475
 
        cos_stream_t *pcs_image;
476
 
 
477
 
        gs_image_t_init_adjust(&image, pcs_Device, false);
478
 
        image.BitsPerComponent = 8;
479
 
        pdf_set_pattern_image((gs_data_image_t *)&image, &p_tile->tbits);
480
 
        if (m_tile) {
481
 
            if ((code = pdf_put_pattern_mask(pdev, m_tile, &pcs_mask)) < 0)
482
 
                return code;
483
 
        }
484
 
        pdf_image_writer_init(&writer);
485
 
        pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
486
 
        if ((code = pdf_begin_write_image(pdev, &writer, gs_no_id, w, h, NULL, false)) < 0 ||
487
 
            (code = psdf_setup_lossless_filters((gx_device_psdf *)pdev,
488
 
                                                &writer.binary[0],
489
 
                                                (gs_pixel_image_t *)&image, false)) < 0 ||
490
 
            (code = pdf_begin_image_data(pdev, &writer, (const gs_pixel_image_t *)&image, &cs_value, 0)) < 0
491
 
            )
492
 
            return code;
493
 
        /* Pattern masks are specified in device coordinates, so invert Y. */
494
 
        if ((code = pdf_copy_color_bits(writer.binary[0].strm, p_tile->tbits.data + (h - 1) * p_tile->tbits.raster, 0, -p_tile->tbits.raster, w, h, pdev->color_info.depth >> 3)) < 0 ||
495
 
            (code = pdf_end_image_binary(pdev, &writer, h)) < 0
496
 
            )
497
 
            return code;
498
 
        pcs_image = (cos_stream_t *)writer.pres->object;
499
 
        if ((pcs_mask != 0 &&
500
 
             (code = cos_dict_put_c_key_object(cos_stream_dict(pcs_image), "/Mask",
501
 
                                               COS_OBJECT(pcs_mask))) < 0) ||
502
 
            (code = pdf_end_write_image(pdev, &writer)) < 0
503
 
            )
504
 
            return code;
505
 
        pcs_image = (cos_stream_t *)writer.pres->object; /* pdf_end_write_image may change it. */
506
 
        code = pdf_pattern(pdev, pdc, p_tile, m_tile, pcs_image, ppres);
507
 
        if (code < 0)
508
 
            return code;
509
 
    } else {
510
 
        *ppres = pdf_find_resource_by_gs_id(pdev, resourcePattern, p_tile->id);
511
 
        *ppres = pdf_substitute_pattern(*ppres);
512
 
        (*ppres)->where_used |= pdev->used_mask;
513
 
    }
514
 
    /* pcs_Device will leak (picked up by GC in PS) on error, but we'll
515
 
       tolerate that for now. */
516
 
    rc_decrement_cs(pcs_Device, "pdf_put_colored_pattern");
517
 
    cos_value_write(&v, pdev);
518
 
    pprints1(pdev->strm, " %s", ppscc->setcolorspace);
519
 
    return 0;
520
 
}
521
 
 
522
 
/* ---------------- PatternType 2 colors ---------------- */
523
 
 
524
 
/* Write parameters common to all Shadings. */
525
 
static int
526
 
pdf_put_shading_common(cos_dict_t *pscd, const gs_shading_t *psh,
527
 
                       bool shfill, const gs_range_t **ppranges)
528
 
{
529
 
    gs_shading_type_t type = ShadingType(psh);
530
 
    const gs_color_space *pcs = psh->params.ColorSpace;
531
 
    int code = cos_dict_put_c_key_int(pscd, "/ShadingType", (int)type);
532
 
    cos_value_t cs_value;
533
 
 
534
 
    if (code < 0 ||
535
 
        (psh->params.AntiAlias &&
536
 
         (code = cos_dict_put_c_strings(pscd, "/AntiAlias", "true")) < 0) ||
537
 
        (code = pdf_color_space_named(pscd->pdev, &cs_value, ppranges, pcs,
538
 
                                &pdf_color_space_names, false, NULL, 0)) < 0 ||
539
 
        (code = cos_dict_put_c_key(pscd, "/ColorSpace", &cs_value)) < 0
540
 
        )
541
 
        return code;
542
 
    if (psh->params.Background && !shfill) {
543
 
        /****** SCALE Background ******/
544
 
        code = cos_dict_put_c_key_floats(pscd, "/Background",
545
 
                                   psh->params.Background->paint.values,
546
 
                                   gs_color_space_num_components(pcs));
547
 
        if (code < 0)
548
 
            return code;
549
 
    }
550
 
    if (psh->params.have_BBox) {
551
 
        float bbox[4];
552
 
 
553
 
        bbox[0] = psh->params.BBox.p.x;
554
 
        bbox[1] = psh->params.BBox.p.y;
555
 
        bbox[2] = psh->params.BBox.q.x;
556
 
        bbox[3] = psh->params.BBox.q.y;
557
 
        code = cos_dict_put_c_key_floats(pscd, "/BBox", bbox, 4);
558
 
        if (code < 0)
559
 
            return code;
560
 
    }
561
 
    return 0;
562
 
}
563
 
 
564
 
/* Write an optional Function parameter. */
565
 
static int
566
 
pdf_put_shading_Function(cos_dict_t *pscd, const gs_function_t *pfn,
567
 
                         const gs_range_t *pranges)
568
 
{
569
 
    int code = 0;
570
 
 
571
 
    if (pfn != 0) {
572
 
        cos_value_t fn_value;
573
 
 
574
 
        if ((code = pdf_function_scaled(pscd->pdev, pfn, pranges, &fn_value)) >= 0)
575
 
            code = cos_dict_put_c_key(pscd, "/Function", &fn_value);
576
 
    }
577
 
    return code;
578
 
}
579
 
 
580
 
/* Write a linear (Axial / Radial) Shading. */
581
 
static int
582
 
pdf_put_linear_shading(cos_dict_t *pscd, const float *Coords,
583
 
                       int num_coords, const float *Domain /*[2]*/,
584
 
                       const gs_function_t *Function,
585
 
                       const bool *Extend /*[2]*/,
586
 
                       const gs_range_t *pranges)
587
 
{
588
 
    int code = cos_dict_put_c_key_floats(pscd, "/Coords", Coords, num_coords);
589
 
 
590
 
    if (code < 0 ||
591
 
        ((Domain[0] != 0 || Domain[1] != 1) &&
592
 
         (code = cos_dict_put_c_key_floats(pscd, "/Domain", Domain, 2)) < 0) ||
593
 
        (code = pdf_put_shading_Function(pscd, Function, pranges)) < 0
594
 
        )
595
 
        return code;
596
 
    if (Extend[0] | Extend[1]) {
597
 
        char extend_str[1 + 5 + 1 + 5 + 1 + 1]; /* [bool bool] */
598
 
 
599
 
        sprintf(extend_str, "[%s %s]",
600
 
                (Extend[0] ? "true" : "false"),
601
 
                (Extend[1] ? "true" : "false"));
602
 
        code = cos_dict_put_c_key_string(pscd, "/Extend",
603
 
                                         (const byte *)extend_str,
604
 
                                         strlen(extend_str));
605
 
    }
606
 
    return code;
607
 
}
608
 
 
609
 
/* Write a scalar (non-mesh) Shading. */
610
 
/* (Single-use procedure for readability.) */
611
 
static int
612
 
pdf_put_scalar_shading(cos_dict_t *pscd, const gs_shading_t *psh,
613
 
                       const gs_range_t *pranges)
614
 
{
615
 
    int code;
616
 
 
617
 
    switch (ShadingType(psh)) {
618
 
    case shading_type_Function_based: {
619
 
        const gs_shading_Fb_params_t *const params =
620
 
            (const gs_shading_Fb_params_t *)&psh->params;
621
 
 
622
 
        if ((code = cos_dict_put_c_key_floats(pscd, "/Domain", params->Domain, 4)) < 0 ||
623
 
            (code = pdf_put_shading_Function(pscd, params->Function, pranges)) < 0 ||
624
 
            (code = cos_dict_put_matrix(pscd, "/Matrix", &params->Matrix)) < 0
625
 
            )
626
 
            return code;
627
 
        return 0;
628
 
    }
629
 
    case shading_type_Axial: {
630
 
        const gs_shading_A_params_t *const params =
631
 
            (const gs_shading_A_params_t *)&psh->params;
632
 
 
633
 
        return pdf_put_linear_shading(pscd, params->Coords, 4,
634
 
                                      params->Domain, params->Function,
635
 
                                      params->Extend, pranges);
636
 
    }
637
 
    case shading_type_Radial: {
638
 
        const gs_shading_R_params_t *const params =
639
 
            (const gs_shading_R_params_t *)&psh->params;
640
 
 
641
 
        return pdf_put_linear_shading(pscd, params->Coords, 6,
642
 
                                      params->Domain, params->Function,
643
 
                                      params->Extend, pranges);
644
 
    }
645
 
    default:
646
 
        return_error(gs_error_rangecheck);
647
 
    }
648
 
}
649
 
 
650
 
/* Add a floating point range to an array. */
651
 
static int
652
 
pdf_array_add_real2(cos_array_t *pca, floatp lower, floatp upper)
653
 
{
654
 
    int code = cos_array_add_real(pca, lower);
655
 
 
656
 
    if (code >= 0)
657
 
        code = cos_array_add_real(pca, upper);
658
 
    return code;
659
 
}
660
 
 
661
 
/* Define a parameter structure for mesh data. */
662
 
typedef struct pdf_mesh_data_params_s {
663
 
    int num_points;
664
 
    int num_components;
665
 
    bool is_indexed;
666
 
    const float *Domain;        /* iff Function */
667
 
    const gs_range_t *ranges;
668
 
} pdf_mesh_data_params_t;
669
 
 
670
 
/* Put a clamped value into a data stream.  num_bytes < sizeof(int). */
671
 
static void
672
 
put_clamped(byte *p, floatp v, int num_bytes)
673
 
{
674
 
    int limit = 1 << (num_bytes * 8);
675
 
    int i, shift;
676
 
 
677
 
    if (v <= -limit)
678
 
        i = -limit + 1;
679
 
    else if (v >= limit)
680
 
        i = limit - 1;
681
 
    else
682
 
        i = (int)v;
683
 
    for (shift = (num_bytes - 1) * 8; shift >= 0; shift -= 8)
684
 
        *p++ = (byte)(i >> shift);
685
 
}
686
 
static inline void
687
 
put_clamped_coord(byte *p, floatp v, int num_bytes)
688
 
{
689
 
    put_clamped(p, ENCODE_MESH_COORDINATE(v), num_bytes);
690
 
}
691
 
 
692
 
/* Convert floating-point mesh data to packed binary. */
693
 
/* BitsPerFlag = 8, BitsPerCoordinate = 24, BitsPerComponent = 16, */
694
 
/* scaling is as defined below. */
695
 
static int
696
 
put_float_mesh_data(cos_stream_t *pscs, shade_coord_stream_t *cs,
697
 
                    int flag, const pdf_mesh_data_params_t *pmdp)
698
 
{
699
 
    int num_points = pmdp->num_points;
700
 
    byte b[1 + (3 + 3) * 16];   /* flag + x + y or c */
701
 
    gs_fixed_point pts[16];
702
 
    const float *domain = pmdp->Domain;
703
 
    const gs_range_t *pranges = pmdp->ranges;
704
 
    int i, code;
705
 
 
706
 
    b[0] = (byte)flag;          /* may be -1 */
707
 
    if ((code = shade_next_coords(cs, pts, num_points)) < 0)
708
 
        return code;
709
 
    for (i = 0; i < num_points; ++i) {
710
 
        put_clamped_coord(b + 1 + i * 6, fixed2float(pts[i].x), 3);
711
 
        put_clamped_coord(b + 4 + i * 6, fixed2float(pts[i].y), 3);
712
 
    }
713
 
    if ((code = cos_stream_add_bytes(pscs, b + (flag < 0),
714
 
                                     (flag >= 0) + num_points * 6)) < 0)
715
 
        return code;
716
 
    for (i = 0; i < pmdp->num_components; ++i) {
717
 
        float c;
718
 
        double v;
719
 
 
720
 
        cs->get_decoded(cs, 0, NULL, &c);
721
 
        if (pmdp->is_indexed)
722
 
            v = ENCODE_MESH_COLOR_INDEX(c);
723
 
        else {
724
 
            /*
725
 
             * We don't rescale stream data values, only the Decode ranges.
726
 
             * (We do have to rescale data values from an array, unless
727
 
             * they are the input parameter for a Function.)
728
 
             * This makes everything come out as it should.
729
 
             */
730
 
            double vmin, vmax;
731
 
 
732
 
            if (domain)
733
 
                vmin = domain[2 * i], vmax = domain[2 * i + 1];
734
 
            else
735
 
                vmin = 0.0, vmax = 1.0;
736
 
            if (pranges) {
737
 
                double base = pranges[i].rmin, factor = pranges[i].rmax - base;
738
 
 
739
 
                vmin = vmin * factor + base;
740
 
                vmax = vmax * factor + base;
741
 
            }
742
 
            v = ENCODE_MESH_COMPONENT(c, vmin, vmax);
743
 
        }
744
 
        put_clamped(b, v, 2);
745
 
        if ((code = cos_stream_add_bytes(pscs, b, 2)) < 0)
746
 
            return code;
747
 
    }
748
 
    return 0;
749
 
}
750
 
 
751
 
/* Write a mesh Shading. */
752
 
static int
753
 
pdf_put_mesh_shading(cos_stream_t *pscs, const gs_shading_t *psh,
754
 
                     const gs_range_t *pranges)
755
 
{
756
 
    cos_dict_t *const pscd = cos_stream_dict(pscs);
757
 
    gs_color_space *pcs = psh->params.ColorSpace;
758
 
    const gs_shading_mesh_params_t *const pmp =
759
 
        (const gs_shading_mesh_params_t *)&psh->params;
760
 
    int code, code1;
761
 
    int bits_per_coordinate, bits_per_component, bits_per_flag;
762
 
    int num_comp;
763
 
    bool from_array = data_source_is_array(pmp->DataSource);
764
 
    pdf_mesh_data_params_t data_params;
765
 
    shade_coord_stream_t cs;
766
 
    gs_matrix_fixed ctm_ident;
767
 
    int flag;
768
 
 
769
 
    if (pmp->Function) {
770
 
        data_params.Domain = 0;
771
 
        num_comp = 1;
772
 
    } else {
773
 
        data_params.Domain = (pmp->Decode != 0 ? pmp->Decode + 4 : NULL);
774
 
        num_comp = gs_color_space_num_components(pcs);
775
 
    }
776
 
    data_params.ranges = pranges;
777
 
 
778
 
    /* Write parameters common to all mesh Shadings. */
779
 
    shade_next_init(&cs, pmp, NULL);
780
 
    if (from_array) {
781
 
        cos_array_t *pca = cos_array_alloc(pscd->pdev, "pdf_put_mesh_shading");
782
 
        int i;
783
 
 
784
 
        if (pca == 0)
785
 
            return_error(gs_error_VMerror);
786
 
        for (i = 0; i < 2; ++i)
787
 
            if ((code = pdf_array_add_real2(pca, MIN_MESH_COORDINATE,
788
 
                                            MAX_MESH_COORDINATE)) < 0)
789
 
                return code;
790
 
        data_params.is_indexed = false;
791
 
        if (gs_color_space_get_index(pcs) == gs_color_space_index_Indexed) {
792
 
            data_params.is_indexed = true;
793
 
            if ((code = pdf_array_add_real2(pca, MIN_MESH_COLOR_INDEX,
794
 
                                            MAX_MESH_COLOR_INDEX)) < 0)
795
 
                return code;
796
 
        } else {
797
 
            for (i = 0; i < num_comp; ++i) {
798
 
                double rmin, rmax;
799
 
 
800
 
                if (pmp->Function || pranges || data_params.Domain == 0)
801
 
                    rmin = 0.0, rmax = 1.0;
802
 
                else
803
 
                    rmin = data_params.Domain[2 * i],
804
 
                        rmax = data_params.Domain[2 * i + 1];
805
 
                if ((code =
806
 
                     pdf_array_add_real2(pca, rmin, rmax)) < 0)
807
 
                    return code;
808
 
            }
809
 
        }
810
 
        code = cos_dict_put_c_key_object(pscd, "/Decode", COS_OBJECT(pca));
811
 
        if (code < 0)
812
 
            return code;
813
 
        bits_per_coordinate = 24;
814
 
        bits_per_component = 16;
815
 
        bits_per_flag = 8;
816
 
        gs_make_identity((gs_matrix *)&ctm_ident);
817
 
        ctm_ident.tx_fixed = ctm_ident.ty_fixed = 0;
818
 
        ctm_ident.txy_fixed_valid = true;
819
 
        cs.pctm = &ctm_ident;
820
 
        if (pmp->Function)
821
 
            data_params.ranges = 0; /* don't scale function parameter */
822
 
    } else {
823
 
        /****** SCALE Decode ******/
824
 
        code = cos_dict_put_c_key_floats(pscd, "/Decode", pmp->Decode,
825
 
                                         4 + num_comp * 2);
826
 
        if (code >= 0)
827
 
            code = cos_stream_add_stream_contents(pscs, cs.s);
828
 
        bits_per_coordinate = pmp->BitsPerCoordinate;
829
 
        bits_per_component = pmp->BitsPerComponent;
830
 
        bits_per_flag = -1;
831
 
    }
832
 
    if (code < 0 ||
833
 
        (code = pdf_put_shading_Function(pscd, pmp->Function, pranges)) < 0 ||
834
 
        (code = cos_dict_put_c_key_int(pscd, "/BitsPerCoordinate",
835
 
                                       bits_per_coordinate)) < 0 ||
836
 
        (code = cos_dict_put_c_key_int(pscd, "/BitsPerComponent",
837
 
                                       bits_per_component)) < 0
838
 
        )
839
 
        return code;
840
 
 
841
 
    switch (ShadingType(psh)) {
842
 
    case shading_type_Free_form_Gouraud_triangle: {
843
 
        const gs_shading_FfGt_params_t *const params =
844
 
            (const gs_shading_FfGt_params_t *)pmp;
845
 
 
846
 
        data_params.num_points = 1;
847
 
        data_params.num_components = num_comp;
848
 
        if (from_array) {
849
 
            while ((flag = shade_next_flag(&cs, 0)) >= 0)
850
 
                if ((code = put_float_mesh_data(pscs, &cs, flag,
851
 
                                                &data_params)) < 0)
852
 
                    return code;
853
 
            if (!seofp(cs.s))
854
 
                code = gs_note_error(gs_error_rangecheck);
855
 
        }
856
 
        if (bits_per_flag < 0)
857
 
            bits_per_flag = params->BitsPerFlag;
858
 
        break;
859
 
    }
860
 
    case shading_type_Lattice_form_Gouraud_triangle: {
861
 
        const gs_shading_LfGt_params_t *const params =
862
 
            (const gs_shading_LfGt_params_t *)pmp;
863
 
 
864
 
        data_params.num_points = 1;
865
 
        data_params.num_components = num_comp;
866
 
        if (from_array)
867
 
            while (!seofp(cs.s))
868
 
                if ((code = put_float_mesh_data(pscs, &cs, -1,
869
 
                                                &data_params)) < 0)
870
 
                    return code;
871
 
        code = cos_dict_put_c_key_int(pscd, "/VerticesPerRow",
872
 
                                      params->VerticesPerRow);
873
 
        return code;
874
 
    }
875
 
    case shading_type_Coons_patch: {
876
 
        const gs_shading_Cp_params_t *const params =
877
 
            (const gs_shading_Cp_params_t *)pmp;
878
 
 
879
 
        if (from_array) {
880
 
            while ((flag = shade_next_flag(&cs, 0)) >= 0) {
881
 
                data_params.num_points = (flag == 0 ? 12 : 8);
882
 
                data_params.num_components = num_comp * (flag == 0 ? 4 : 2);
883
 
                if ((code = put_float_mesh_data(pscs, &cs, flag,
884
 
                                                &data_params)) < 0)
885
 
                    return code;
886
 
            }
887
 
            if (!seofp(cs.s))
888
 
                code = gs_note_error(gs_error_rangecheck);
889
 
        }
890
 
        if (bits_per_flag < 0)
891
 
            bits_per_flag = params->BitsPerFlag;
892
 
        break;
893
 
    }
894
 
    case shading_type_Tensor_product_patch: {
895
 
        const gs_shading_Tpp_params_t *const params =
896
 
            (const gs_shading_Tpp_params_t *)pmp;
897
 
 
898
 
        if (from_array) {
899
 
            while ((flag = shade_next_flag(&cs, 0)) >= 0) {
900
 
                data_params.num_points = (flag == 0 ? 16 : 12);
901
 
                data_params.num_components = num_comp * (flag == 0 ? 4 : 2);
902
 
                if ((code = put_float_mesh_data(pscs, &cs, flag,
903
 
                                                &data_params)) < 0)
904
 
                    return code;
905
 
            }
906
 
            if (!seofp(cs.s))
907
 
                code = gs_note_error(gs_error_rangecheck);
908
 
        }
909
 
        if (bits_per_flag < 0)
910
 
            bits_per_flag = params->BitsPerFlag;
911
 
        break;
912
 
    }
913
 
    default:
914
 
        return_error(gs_error_rangecheck);
915
 
    }
916
 
    code1 =  cos_dict_put_c_key_int(pscd, "/BitsPerFlag", bits_per_flag);
917
 
    if (code1 < 0)
918
 
        return code;
919
 
    return code;
920
 
}
921
 
 
922
 
/* Write a PatternType 2 (shading pattern) color. */
923
 
int
924
 
pdf_put_pattern2(gx_device_pdf *pdev, const gx_drawing_color *pdc,
925
 
                 const psdf_set_color_commands_t *ppscc,
926
 
                 pdf_resource_t **ppres)
927
 
{
928
 
    const gs_pattern2_instance_t *pinst =
929
 
        (gs_pattern2_instance_t *)pdc->ccolor.pattern;
930
 
    const gs_shading_t *psh = pinst->templat.Shading;
931
 
    cos_value_t v;
932
 
    pdf_resource_t *pres;
933
 
    pdf_resource_t *psres;
934
 
    cos_dict_t *pcd;
935
 
    cos_object_t *psco;
936
 
    const gs_range_t *pranges;
937
 
    int code = pdf_cs_Pattern_colored(pdev, &v);
938
 
    int code1 = 0;
939
 
    gs_matrix smat;
940
 
 
941
 
    if (code < 0)
942
 
        return code;
943
 
    code = pdf_alloc_resource(pdev, resourcePattern, gs_no_id, ppres, 0L);
944
 
    if (code < 0)
945
 
        return code;
946
 
    pres = *ppres;
947
 
    cos_become(pres->object, cos_type_dict);
948
 
    pcd = (cos_dict_t *)pres->object;
949
 
    code = pdf_alloc_resource(pdev, resourceShading, gs_no_id, &psres, 0L);
950
 
    if (code < 0)
951
 
        return code;
952
 
    psco = psres->object;
953
 
    if (ShadingType(psh) >= 4) {
954
 
        /* Shading has an associated data stream. */
955
 
        cos_become(psco, cos_type_stream);
956
 
        code = pdf_put_shading_common(cos_stream_dict((cos_stream_t *)psco),
957
 
                                      psh, pinst->shfill, &pranges);
958
 
        if (code >= 0)
959
 
            code1 = pdf_put_mesh_shading((cos_stream_t *)psco, psh, pranges);
960
 
        else
961
 
            /* We won't use this shading, we fall back because we couldn't write it */
962
 
            psres->where_used = 0;
963
 
    } else {
964
 
        cos_become(psco, cos_type_dict);
965
 
        code = pdf_put_shading_common((cos_dict_t *)psco, psh, pinst->shfill, &pranges);
966
 
        if (code >= 0)
967
 
            code = pdf_put_scalar_shading((cos_dict_t *)psco, psh, pranges);
968
 
        else
969
 
            /* We won't use this shading, we fall back because we couldn't write it */
970
 
            psres->where_used = 0;
971
 
    }
972
 
    /*
973
 
     * In PDF, the Matrix is the transformation from the pattern space to
974
 
     * the *default* user coordinate space, not the current space.
975
 
     * NB. For a form the default space is the parent. This means that when a
976
 
     * form is nested inside a form, the default space is the space of the
977
 
     * first form, and therefore we do *not* remove the resolution scaling.
978
 
     */
979
 
    gs_currentmatrix(pinst->saved, &smat);
980
 
    {
981
 
        double xscale = 1.0, yscale = 1.0;
982
 
        if (pdev->FormDepth == 0) {
983
 
            xscale = 72.0 / pdev->HWResolution[0];
984
 
            yscale = 72.0 / pdev->HWResolution[1];
985
 
        }
986
 
 
987
 
        smat.xx *= xscale, smat.yx *= xscale, smat.tx *= xscale;
988
 
        smat.xy *= yscale, smat.yy *= yscale, smat.ty *= yscale;
989
 
    }
990
 
    if (code < 0 ||
991
 
        (code = cos_dict_put_c_key_int(pcd, "/PatternType", 2)) < 0 ||
992
 
        (code = cos_dict_put_c_key_object(pcd, "/Shading", psco)) < 0 ||
993
 
        (code = cos_dict_put_matrix(pcd, "/Matrix", &smat)) < 0
994
 
        /****** ExtGState ******/
995
 
        )
996
 
        return code;
997
 
    cos_value_write(&v, pdev);
998
 
    pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
999
 
    return code1;
1000
 
}
1001
 
 
1002
 
/*
1003
 
    Include color space.
1004
 
 */
1005
 
int
1006
 
gdev_pdf_include_color_space(gx_device *dev, gs_color_space *cspace, const byte *res_name, int name_length)
1007
 
{
1008
 
    gx_device_pdf * pdev = (gx_device_pdf *)dev;
1009
 
    cos_value_t cs_value;
1010
 
 
1011
 
    return pdf_color_space_named(pdev, &cs_value, NULL, cspace,
1012
 
                                &pdf_color_space_names, true, res_name, name_length);
1013
 
}