Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/devices/vector/gdevpdfb.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* Low-level bitmap image handling for PDF-writing driver */
18
#include "string_.h"
19
#include "gx.h"
20
#include "gserrors.h"
21
#include "gdevpdfx.h"
22
#include "gdevpdfg.h"
23
#include "gdevpdfo.h"                /* for data stream */
24
#include "gxcspace.h"
25
#include "gxdcolor.h"
26
#include "gxpcolor.h"
27
#include "gxhldevc.h"
28
#include "gxchar.h"
29
#include "gdevpdtf.h"                /* Required to include gdevpdti.h */
30
#include "gdevpdti.h"                /* For pdf_charproc_x_offset */
31
#include "gsptype1.h"
32
33
/* We need this color space type for constructing temporary color spaces. */
34
extern const gs_color_space_type gs_color_space_type_Indexed;
35
36
/* ---------------- Utilities ---------------- */
37
38
/* Fill in the image parameters for a bitmap image. */
39
static void
40
pdf_make_bitmap_image(gs_image_t * pim, int x, int y, int w, int h)
41
507k
{
42
507k
    pim->Width = w;
43
507k
    pim->Height = h;
44
507k
    pdf_make_bitmap_matrix(&pim->ImageMatrix, x, y, w, h, h);
45
507k
}
46
47
/* ---------------- Driver procedures ---------------- */
48
49
/* Copy a mask bitmap.  for_pattern = -1 means put the image in-line, */
50
/* 1 means put the image in a resource. */
51
static int
52
pdf_copy_mask_data(gx_device_pdf * pdev, const byte * base, int sourcex,
53
                   int raster, gx_bitmap_id id, int x, int y, int w, int h,
54
                   gs_image_t *pim, pdf_image_writer *piw,
55
                   int for_pattern)
56
0
{
57
0
    ulong nbytes;
58
0
    int code;
59
0
    const byte *row_base;
60
0
    int row_step;
61
0
    bool in_line;
62
63
0
    gs_image_t_init_mask(pim, true);
64
0
    pdf_make_bitmap_image(pim, x, y, w, h);
65
0
    nbytes = ((ulong)w * h + 7) / 8;
66
67
0
    if (for_pattern) {
68
        /*
69
         * Patterns must be emitted in order of increasing user Y, i.e.,
70
         * the opposite of PDF's standard image order.
71
         */
72
0
        row_base = base + (h - 1) * raster;
73
0
        row_step = -raster;
74
0
        in_line = for_pattern < 0;
75
0
    } else {
76
0
        row_base = base;
77
0
        row_step = raster;
78
0
        in_line = nbytes < pdev->MaxInlineImageSize;
79
0
        pdf_put_image_matrix(pdev, &pim->ImageMatrix, 1.0);
80
        /*
81
         * Check whether we've already made an XObject resource for this
82
         * image.
83
         */
84
0
        if (id != gx_no_bitmap_id) {
85
0
            piw->pres = pdf_find_resource_by_gs_id(pdev, resourceXObject, id);
86
0
            if (piw->pres)
87
0
                return 0;
88
0
        }
89
0
    }
90
    /*
91
     * We have to be able to control whether to put Pattern images in line,
92
     * to avoid trying to create an XObject resource while we're in the
93
     * middle of writing a Pattern resource.
94
     */
95
0
    if (for_pattern < 0)
96
0
        stream_puts(pdev->strm, "q ");
97
0
    pdf_image_writer_init(piw);
98
0
    pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
99
0
    if ((code = pdf_begin_write_image(pdev, piw, id, w, h, NULL, in_line)) < 0 ||
100
0
        (code = psdf_setup_lossless_filters((gx_device_psdf *) pdev,
101
0
                                            &piw->binary[0],
102
0
                                            (gs_pixel_image_t *)pim, in_line)) < 0 ||
103
0
        (code = pdf_begin_image_data(pdev, piw, (const gs_pixel_image_t *)pim,
104
0
                                     NULL, 0)) < 0
105
0
        )
106
0
        return code;
107
0
    pdf_copy_mask_bits(piw->binary[0].strm, row_base, sourcex, row_step, w, h, 0);
108
0
    pdf_end_image_binary(pdev, piw, piw->height);
109
0
    return pdf_end_write_image(pdev, piw);
110
0
}
111
112
static void
113
set_image_color(gx_device_pdf *pdev, gx_color_index c)
114
0
{
115
0
    pdf_set_pure_color(pdev, c, &pdev->saved_fill_color,
116
0
                        &pdev->fill_used_process_color,
117
0
                        &psdf_set_fill_color_commands);
118
0
    if (!pdev->HaveStrokeColor)
119
0
        pdf_set_pure_color(pdev, c, &pdev->saved_stroke_color,
120
0
                            &pdev->stroke_used_process_color,
121
0
                            &psdf_set_stroke_color_commands);
122
0
}
123
124
static int
125
pdf_copy_mono(gx_device_pdf *pdev,
126
              const byte *base, int sourcex, int raster, gx_bitmap_id id,
127
              int x, int y, int w, int h, gx_color_index zero,
128
              gx_color_index one, const gx_clip_path *pcpath)
129
507k
{
130
507k
    int code;
131
507k
    gs_color_space *pcs = NULL;
132
507k
    cos_value_t cs_value;
133
507k
    cos_value_t *pcsvalue;
134
507k
    byte palette[ARCH_SIZEOF_COLOR_INDEX * 2];
135
507k
    gs_image_t image;
136
507k
    pdf_image_writer writer;
137
507k
    pdf_stream_position_t ipos;
138
507k
    pdf_resource_t *pres = 0;
139
507k
    byte invert = 0;
140
507k
    bool in_line = false, char_proc_begun = false;
141
507k
    gs_show_enum *show_enum = (gs_show_enum *)pdev->pte;
142
507k
    int x_offset, y_offset;
143
507k
    double width;
144
145
    /* Update clipping. */
146
507k
    if (pdf_must_put_clip_path(pdev, pcpath)) {
147
0
        code = pdf_open_page(pdev, PDF_IN_STREAM);
148
0
        if (code < 0)
149
0
            return code;
150
0
        code = pdf_put_clip_path(pdev, pcpath);
151
0
        if (code < 0)
152
0
            return code;
153
0
    }
154
    /* We have 3 cases: mask, inverse mask, and solid. */
155
507k
    if (zero == gx_no_color_index) {
156
507k
        if (one == gx_no_color_index)
157
0
            return 0;
158
        /* If a mask has an id, assume it's a character. */
159
507k
        if (id != gx_no_bitmap_id && sourcex == 0 && show_enum) {
160
507k
            pdf_char_proc_t *pcp;
161
162
507k
            if (show_enum->use_wxy_float)
163
0
                pdev->char_width.x = show_enum->wxy_float.x;
164
507k
            else
165
507k
                pdev->char_width.x = fixed2float(show_enum->wxy.x);
166
507k
            pres = pdf_find_resource_by_gs_id(pdev, resourceCharProc, id);
167
507k
            if (pres == 0) {        /* Define the character in an embedded font. */
168
25.6k
                gs_image_t_init_mask(&image, false);
169
25.6k
                invert = 0xff;
170
25.6k
                x_offset = x - (int)show_enum->pgs->current_point.x;
171
25.6k
                y_offset = y - (int)show_enum->pgs->current_point.y;
172
25.6k
                x -= x_offset;
173
25.6k
                y -= y_offset;
174
25.6k
                y -= h;
175
25.6k
                pdf_make_bitmap_image(&image, x, y, w, h);
176
                /*
177
                 * The Y axis of the text matrix is inverted,
178
                 * so we need to negate the Y offset appropriately.
179
                 */
180
25.6k
                code = pdf_begin_char_proc(pdev, w, h, 0, y_offset, x_offset, id,
181
25.6k
                                           &pcp, &ipos);
182
25.6k
                if (code < 0)
183
0
                    return code;
184
25.6k
                char_proc_begun = true;
185
25.6k
                y_offset = -y_offset;
186
25.6k
                width = psdf_round(pdev->char_width.x, 100, 10); /* See
187
                        pdf_write_Widths about rounding. We need to provide
188
                        a compatible data for Tj. */
189
25.6k
                pprintg1(pdev->strm, "%g ", width);
190
25.6k
                pprintd4(pdev->strm, "0 %d %d %d %d d1\n",  x_offset, -h + y_offset, w + x_offset, y_offset);
191
25.6k
                pprintd4(pdev->strm, "%d 0 0 %d %d %d cm\n", w, h, x_offset,
192
25.6k
                         -h + y_offset);
193
25.6k
                pdf_image_writer_init(&writer);
194
25.6k
                code = pdf_begin_write_image(pdev, &writer, gs_no_id, w, h, NULL, true);
195
25.6k
                if (code < 0)
196
0
                    goto fail;
197
25.6k
                pres = (pdf_resource_t *) pcp;
198
25.6k
                goto wr;
199
482k
            } else if (pdev->pte != NULL) {
200
                /* We're under pdf_text_process. It set a high level color. */
201
482k
            } else
202
0
                set_image_color(pdev, one);
203
482k
            pcp = (pdf_char_proc_t *) pres;
204
482k
            x -= pdf_charproc_x_offset(pcp);
205
482k
            y -= pdf_charproc_y_offset(pcp);
206
482k
            y -= h;
207
482k
            pdf_make_bitmap_image(&image, x, y, w, h);
208
482k
            goto rx;
209
507k
        }
210
4
        if (pdev->pte == NULL)
211
0
            set_image_color(pdev, one);
212
4
        gs_image_t_init_mask(&image, false);
213
4
        invert = 0xff;
214
4
    } else if (one == gx_no_color_index) {
215
0
        gs_image_t_init_mask(&image, false);
216
0
        if (pdev->pte == NULL)
217
0
            set_image_color(pdev, zero);
218
0
    } else if (zero == pdev->black && one == pdev->white) {
219
0
        pcs = gs_cspace_new_DeviceGray(pdev->memory);
220
0
        if (pcs == NULL) {
221
0
            code = gs_note_error(gs_error_VMerror);
222
0
            goto fail;
223
0
        }
224
0
        gs_image_t_init(&image, pcs);
225
0
    } else if (zero == pdev->white && one == pdev->black) {
226
0
        pcs = gs_cspace_new_DeviceGray(pdev->memory);
227
0
        if (pcs == NULL) {
228
0
            code = gs_note_error(gs_error_VMerror);
229
0
            goto fail;
230
0
        }
231
0
        gs_image_t_init(&image, pcs);
232
0
        invert = 0xff;
233
0
    } else {
234
        /*
235
         * We think this code is never executed when interpreting PostScript
236
         * or PDF: the library never uses monobit non-mask images
237
         * internally, and high-level images don't go through this code.
238
         * However, we still want the code to work.
239
         */
240
0
        gs_color_space *pcs_base;
241
0
        gx_color_index c[2];
242
0
        int i, j;
243
0
        int ncomp = pdev->color_info.num_components;
244
0
        byte *p;
245
246
0
        code = pdf_cspace_init_Device(pdev->memory, &pcs_base, ncomp);
247
0
        if (code < 0)
248
0
            goto fail;
249
0
        c[0] = psdf_adjust_color_index((gx_device_vector *)pdev, zero);
250
0
        c[1] = psdf_adjust_color_index((gx_device_vector *)pdev, one);
251
0
        pcs = gs_cspace_alloc(pdev->memory, &gs_color_space_type_Indexed);
252
0
        if (pcs == NULL) {
253
0
            rc_decrement_cs(pcs_base, "pdf_copy_mono");
254
0
            code = gs_note_error(gs_error_VMerror);
255
0
            goto fail;
256
0
        }
257
0
        pcs->base_space = pcs_base;
258
0
        pcs->params.indexed.hival = 1;
259
0
        pcs->params.indexed.n_comps = ncomp;
260
0
        p = palette;
261
0
        for (i = 0; i < 2; ++i)
262
0
            for (j = ncomp - 1; j >= 0; --j)
263
0
                *p++ = (byte)(c[i] >> (j * 8));
264
0
        pcs->params.indexed.lookup.table.data = palette;
265
0
        pcs->params.indexed.lookup.table.size = p - palette;
266
0
        pcs->params.indexed.use_proc = false;
267
0
        gs_image_t_init(&image, pcs);
268
0
        image.BitsPerComponent = 1;
269
0
    }
270
4
    pdf_make_bitmap_image(&image, x, y, w, h);
271
4
    {
272
4
        ulong nbytes = (ulong) ((w + 7) >> 3) * h;
273
274
4
        code = pdf_open_page(pdev, PDF_IN_STREAM);
275
4
        if (code < 0)
276
0
            goto fail;
277
4
        in_line = nbytes < pdev->MaxInlineImageSize;
278
4
        if (in_line)
279
4
            pdf_put_image_matrix(pdev, &image.ImageMatrix, 1.0);
280
4
        pdf_image_writer_init(&writer);
281
4
        code = pdf_begin_write_image(pdev, &writer, gs_no_id, w, h, NULL, in_line);
282
4
        if (code < 0)
283
0
            goto fail;
284
4
    }
285
25.6k
  wr:
286
25.6k
    if (image.ImageMask)
287
25.6k
        pcsvalue = NULL;
288
0
    else {
289
        /*
290
         * We don't have to worry about color space scaling: the color
291
         * space is always a Device space.
292
         */
293
0
        code = pdf_color_space_named(pdev, NULL, &cs_value, NULL, pcs,
294
0
                               &writer.pin->color_spaces, in_line, NULL, 0, false);
295
0
        if (code < 0)
296
0
            goto fail;
297
0
        pcsvalue = &cs_value;
298
0
    }
299
    /*
300
     * There are 3 different cases at this point:
301
     *      - Writing an in-line image (pres == 0, writer.pres == 0);
302
     *      - Writing an XObject image (pres == 0, writer.pres != 0);
303
     *      - Writing the image for a CharProc (pres != 0).
304
     * We handle them with in-line code followed by a switch,
305
     * rather than making the shared code into a procedure,
306
     * simply because there would be an awful lot of parameters
307
     * that would need to be passed.
308
     */
309
25.6k
    if (pres) {
310
25.6k
        if (!pdev->NoT3CCITT) {
311
            /*
312
             * Always use CCITTFax 2-D for character bitmaps.  It takes less
313
             * space to invert the data with Decode than to set BlackIs1.
314
             */
315
25.6k
            float d0 = image.Decode[0];
316
317
25.6k
            image.Decode[0] = image.Decode[1];
318
25.6k
            image.Decode[1] = d0;
319
25.6k
            psdf_CFE_binary(&writer.binary[0], image.Width, image.Height, true);
320
25.6k
            invert ^= 0xff;
321
25.6k
        }
322
25.6k
    } else {
323
        /* Use the Distiller compression parameters. */
324
4
        pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
325
4
        psdf_setup_image_filters((gx_device_psdf *) pdev, &writer.binary[0],
326
4
                                 (gs_pixel_image_t *)&image, NULL, NULL, true, in_line);
327
4
    }
328
25.6k
    code = pdf_begin_image_data(pdev, &writer, (const gs_pixel_image_t *)&image,
329
25.6k
                         pcsvalue, 0);
330
25.6k
    if (code < 0)
331
0
        goto fail;
332
333
25.6k
    code = pdf_copy_mask_bits(writer.binary[0].strm, base, sourcex, raster,
334
25.6k
                              w, h, invert);
335
25.6k
    if (code < 0)
336
0
        goto fail;
337
25.6k
    code = pdf_end_image_binary(pdev, &writer, writer.height);
338
25.6k
    if (code < 0)
339
0
        goto fail;
340
341
25.6k
    if (!pres) {
342
4
        switch ((code = pdf_end_write_image(pdev, &writer))) {
343
0
            default:                /* error */
344
0
                goto fail;
345
4
            case 1:
346
4
                code = 0;
347
4
                goto fail;
348
0
            case 0:
349
0
                code = pdf_do_image(pdev, writer.pres, &image.ImageMatrix,
350
0
                                    true);
351
0
                goto fail;
352
4
        }
353
4
    }
354
25.6k
    writer.end_string = "";        /* no Q */
355
25.6k
    switch ((code = pdf_end_write_image(pdev, &writer))) {
356
0
    default:                /* error */
357
0
        goto fail;
358
0
        return code;
359
0
    case 0:                        /* not possible */
360
0
        code = gs_note_error(gs_error_Fatal);
361
0
        goto fail;
362
25.6k
    case 1:
363
25.6k
        break;
364
25.6k
    }
365
25.6k
    code = pdf_end_char_proc(pdev, &ipos);
366
25.6k
    if (code < 0)
367
0
        return code;
368
507k
  rx:{
369
507k
        gs_matrix imat;
370
371
507k
        imat = image.ImageMatrix;
372
507k
        imat.xx /= w;
373
507k
        imat.xy /= h;
374
507k
        imat.yx /= w;
375
507k
        imat.yy /= h;
376
507k
        return pdf_do_char_image(pdev, (const pdf_char_proc_t *)pres, &imat);
377
25.6k
    }
378
379
4
fail:
380
4
    if (char_proc_begun)
381
0
        (void)pdf_end_char_proc(pdev, &ipos);
382
4
    return code;
383
25.6k
}
384
int
385
gdev_pdf_copy_mono(gx_device * dev,
386
                   const byte * base, int sourcex, int raster, gx_bitmap_id id,
387
                   int x, int y, int w, int h, gx_color_index zero,
388
                   gx_color_index one)
389
0
{
390
0
    gx_device_pdf *pdev = (gx_device_pdf *) dev;
391
392
0
    if (w <= 0 || h <= 0)
393
0
        return 0;
394
0
    return pdf_copy_mono(pdev, base, sourcex, raster, id, x, y, w, h,
395
0
                         zero, one, NULL);
396
0
}
397
398
/* Copy a color bitmap.  for_pattern = -1 means put the image in-line, */
399
/* 1 means put the image in a resource, 2 means image is a rasterized shading. */
400
int
401
pdf_copy_color_data(gx_device_pdf * pdev, const byte * base, int sourcex,
402
                    int raster, gx_bitmap_id id, int x, int y, int w, int h,
403
                    gs_image_t *pim, pdf_image_writer *piw,
404
                    int for_pattern)
405
7
{
406
7
    int depth = pdev->color_info.depth;
407
7
    int bytes_per_pixel = depth >> 3;
408
7
    gs_color_space *pcs;
409
7
    cos_value_t cs_value;
410
7
    ulong nbytes;
411
7
    int code = pdf_cspace_init_Device(pdev->memory, &pcs, bytes_per_pixel);
412
7
    const byte *row_base;
413
7
    int row_step;
414
7
    bool in_line;
415
416
7
    if (code < 0)
417
0
        return code;                /* can't happen */
418
7
    if (!base)
419
0
        return 1;
420
7
    gs_image_t_init(pim, pcs);
421
7
    pdf_make_bitmap_image(pim, x, y, w, h);
422
7
    pim->BitsPerComponent = 8;
423
7
    nbytes = (ulong)w * bytes_per_pixel * h;
424
425
7
    if (for_pattern == 1) {
426
        /*
427
         * Patterns must be emitted in order of increasing user Y, i.e.,
428
         * the opposite of PDF's standard image order.
429
         */
430
0
        row_base = base + (h - 1) * raster;
431
0
        row_step = -raster;
432
0
        in_line = for_pattern < 0;
433
7
    } else {
434
7
        row_base = base;
435
7
        row_step = raster;
436
7
        in_line = nbytes < pdev->MaxInlineImageSize;
437
7
        pdf_put_image_matrix(pdev, &pim->ImageMatrix, 1.0);
438
        /*
439
         * Check whether we've already made an XObject resource for this
440
         * image.
441
         */
442
7
        if (id != gx_no_bitmap_id) {
443
0
            piw->pres = pdf_find_resource_by_gs_id(pdev, resourceXObject, id);
444
0
            if (piw->pres)
445
0
                return 0;
446
0
        }
447
7
    }
448
    /*
449
     * We have to be able to control whether to put Pattern images in line,
450
     * to avoid trying to create an XObject resource while we're in the
451
     * middle of writing a Pattern resource.
452
     */
453
7
    if (for_pattern < 0)
454
0
        stream_puts(pdev->strm, "q ");
455
    /*
456
     * We don't have to worry about color space scaling: the color
457
     * space is always a Device space.
458
     */
459
7
    pdf_image_writer_init(piw);
460
7
    pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
461
7
    if ((code = pdf_begin_write_image(pdev, piw, id, w, h, NULL, in_line)) < 0 ||
462
7
        (code = pdf_color_space_named(pdev, NULL, &cs_value, NULL, pcs,
463
7
                                &piw->pin->color_spaces, in_line, NULL, 0, false)) < 0 ||
464
7
        (for_pattern < 2 || nbytes < 512000 ?
465
7
            (code = psdf_setup_lossless_filters((gx_device_psdf *) pdev,
466
7
                        &piw->binary[0], (gs_pixel_image_t *)pim, false)) :
467
7
            (code = psdf_setup_image_filters((gx_device_psdf *) pdev,
468
0
                        &piw->binary[0], (gs_pixel_image_t *)pim, NULL, NULL, false, false))
469
7
        ) < 0 ||
470
7
        (code = pdf_begin_image_data(pdev, piw, (const gs_pixel_image_t *)pim,
471
7
                                     &cs_value, 0)) < 0
472
7
        )
473
0
        return code;
474
7
    pdf_copy_color_bits(piw->binary[0].strm, row_base, sourcex, row_step, w, h,
475
7
                        bytes_per_pixel);
476
7
    pdf_end_image_binary(pdev, piw, piw->height);
477
7
    rc_decrement(pcs, "pdf_copy_color_data");
478
7
    return pdf_end_write_image(pdev, piw);
479
7
}
480
481
int
482
gdev_pdf_copy_color(gx_device * dev, const byte * base, int sourcex,
483
                    int raster, gx_bitmap_id id, int x, int y, int w, int h)
484
0
{
485
0
    gx_device_pdf *pdev = (gx_device_pdf *) dev;
486
0
    gs_image_t image;
487
0
    pdf_image_writer writer;
488
0
    int code;
489
490
0
    if (w <= 0 || h <= 0)
491
0
        return 0;
492
0
    code = pdf_open_page(pdev, PDF_IN_STREAM);
493
0
    if (code < 0)
494
0
        return code;
495
    /* Make sure we aren't being clipped. */
496
0
    code = pdf_put_clip_path(pdev, NULL);
497
0
    if (code < 0)
498
0
        return code;
499
0
    code = pdf_copy_color_data(pdev, base, sourcex, raster, id, x, y, w, h,
500
0
                               &image, &writer, 0);
501
0
    switch (code) {
502
0
        default:
503
0
            return code;        /* error */
504
0
        case 1:
505
0
            return 0;
506
0
        case 0:
507
0
            return pdf_do_image(pdev, writer.pres, NULL, true);
508
0
    }
509
0
}
510
511
/* Fill a mask. */
512
int
513
gdev_pdf_fill_mask(gx_device * dev,
514
                   const byte * data, int data_x, int raster, gx_bitmap_id id,
515
                   int x, int y, int width, int height,
516
                   const gx_drawing_color * pdcolor, int depth,
517
                   gs_logical_operation_t lop, const gx_clip_path * pcpath)
518
617k
{
519
617k
    gx_device_pdf *pdev = (gx_device_pdf *) dev;
520
521
617k
    if (width <= 0 || height <= 0)
522
109k
        return 0;
523
524
    /* If OCRStage is 'OCR_Rendering' then we are handling an image which is a rendered glyph
525
     * that we want to have OCR software process and return a Unicode code point for.
526
     * We specifically do *not* want to send the image to the output PDF file!
527
     */
528
507k
    if (pdev->OCRStage == OCR_Rendering) {
529
0
        int code = 0;
530
0
        ocr_glyph_t *new_glyph = NULL;
531
0
        int index;
532
533
0
        new_glyph = (ocr_glyph_t *)gs_alloc_bytes(pdev->pdf_memory, sizeof(ocr_glyph_t), "");
534
0
        if (new_glyph == NULL)
535
0
            return_error(gs_error_VMerror);
536
0
        new_glyph->data = gs_alloc_bytes(pdev->pdf_memory, raster*height, "");
537
0
        if (new_glyph->data == NULL)
538
0
            return_error(gs_error_VMerror);
539
0
        memcpy(new_glyph->data, data, raster * height);
540
0
        new_glyph->height = height;
541
0
        new_glyph->width = width;
542
0
        new_glyph->raster = raster;
543
0
        new_glyph->x = x;
544
0
        new_glyph->y = y;
545
0
        new_glyph->char_code = pdev->OCR_char_code;
546
0
        new_glyph->glyph = pdev->OCR_glyph;
547
0
        new_glyph->next = NULL;
548
0
        new_glyph->is_space = true;
549
0
        for(index = 0; index < height * raster;index++){
550
0
            if(data[index] != 0x00) {
551
0
                new_glyph->is_space = false;
552
0
                break;
553
0
            }
554
0
        }
555
0
        if (pdev->ocr_glyphs == NULL)
556
0
            pdev->ocr_glyphs = new_glyph;
557
0
        else {
558
0
            ocr_glyph_t *next = pdev->ocr_glyphs;
559
560
0
            while (next->next != NULL)
561
0
                next = next->next;
562
0
            next->next = new_glyph;
563
0
        }
564
0
        return code;
565
0
    }
566
567
507k
    if (depth > 1 || (!gx_dc_is_pure(pdcolor) != 0 && !(gx_dc_is_pattern1_color(pdcolor))))
568
0
        return gx_default_fill_mask(dev, data, data_x, raster, id,
569
0
                                    x, y, width, height, pdcolor, depth, lop,
570
0
                                    pcpath);
571
507k
    return pdf_copy_mono(pdev, data, data_x, raster, id, x, y, width, height,
572
507k
                         gx_no_color_index, gx_dc_pure_color(pdcolor),
573
507k
                         pcpath);
574
507k
}
575
576
/* Tile with a bitmap.  This is important for pattern fills. */
577
int
578
gdev_pdf_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
579
                              int x, int y, int w, int h,
580
                              gx_color_index color0, gx_color_index color1,
581
                              int px, int py)
582
0
{
583
0
    gx_device_pdf *const pdev = (gx_device_pdf *) dev;
584
0
    int tw = tiles->rep_width, th = tiles->rep_height;
585
0
    double xscale = pdev->HWResolution[0] / 72.0,
586
0
        yscale = pdev->HWResolution[1] / 72.0;
587
0
    bool mask;
588
0
    int depth;
589
0
    int (*copy_data)(gx_device_pdf *, const byte *, int, int,
590
0
                     gx_bitmap_id, int, int, int, int,
591
0
                     gs_image_t *, pdf_image_writer *, int);
592
0
    pdf_resource_t *pres;
593
0
    cos_value_t cs_value;
594
0
    int code;
595
596
0
    if (tiles->id == gx_no_bitmap_id || tiles->shift != 0 ||
597
0
        (w < tw && h < th) ||
598
0
        color0 != gx_no_color_index
599
0
        )
600
0
        goto use_default;
601
0
    if (color1 != gx_no_color_index) {
602
        /* This is a mask pattern. */
603
0
        mask = true;
604
0
        depth = 1;
605
0
        copy_data = pdf_copy_mask_data;
606
0
        code = pdf_cs_Pattern_uncolored(pdev, &cs_value);
607
0
    } else {
608
        /* This is a colored pattern. */
609
0
        mask = false;
610
0
        depth = pdev->color_info.depth;
611
0
        copy_data = pdf_copy_color_data;
612
0
        code = pdf_cs_Pattern_colored(pdev, &cs_value);
613
0
    }
614
0
    if (code < 0)
615
0
        goto use_default;
616
0
    pres = pdf_find_resource_by_gs_id(pdev, resourcePattern, tiles->id);
617
0
    if (!pres) {
618
        /* Create the Pattern resource. */
619
0
        int code;
620
0
        long length_id;
621
0
        gs_offset_t start, end;
622
0
        stream *s;
623
0
        gs_image_t image;
624
0
        pdf_image_writer writer;
625
0
        long image_bytes = ((long)tw * depth + 7) / 8 * th;
626
0
        bool in_line = image_bytes < pdev->MaxInlineImageSize;
627
0
        ulong tile_id =
628
0
            (tw == tiles->size.x && th == tiles->size.y ? tiles->id :
629
0
             gx_no_bitmap_id);
630
631
0
        if (!in_line)
632
0
            goto use_default;
633
634
0
        code = pdf_begin_resource(pdev, resourcePattern, tiles->id, &pres);
635
0
        if (code < 0)
636
0
            goto use_default;
637
0
        s = pdev->strm;
638
0
        pprintd1(s, "/PatternType 1/PaintType %d/TilingType 1/Resources<<\n",
639
0
                 (mask ? 2 : 1));
640
641
0
        if (pdev->CompatibilityLevel <= 1.7)
642
0
            pprints1(s, "/ProcSet[/PDF/Image%s]>>\n", (mask ? "B" : "C"));
643
        /*
644
         * Because of bugs in Acrobat Reader's Print function, we can't use
645
         * the natural BBox and Step here: they have to be 1.
646
         */
647
0
        pprintg2(s, "/Matrix[%g 0 0 %g 0 0]", tw / xscale, th / yscale);
648
0
        stream_puts(s, "/BBox[0 0 1 1]/XStep 1/YStep 1/Length ");
649
0
        length_id = pdf_obj_ref(pdev);
650
0
        pprintld1(s, "%ld 0 R>>stream\n", length_id);
651
0
        start = pdf_stell(pdev);
652
0
        code = copy_data(pdev, tiles->data, 0, tiles->raster,
653
0
                         tile_id, 0, 0, tw, th, &image, &writer, -1);
654
0
        switch (code) {
655
0
        default:
656
0
            return code;        /* error */
657
0
        case 1:
658
0
            break;
659
0
        case 0:                        /* not possible */
660
0
            return_error(gs_error_Fatal);
661
0
        }
662
0
        end = pdf_stell(pdev);
663
0
        stream_puts(s, "\nendstream\n");
664
0
        pdf_end_resource(pdev, resourcePattern);
665
0
        pdf_open_separate(pdev, length_id, resourceNone);
666
0
        pprintld1(pdev->strm, "%ld\n", end - start);
667
0
        pdf_end_separate(pdev, resourceNone);
668
0
        pres->object->written = true; /* don't write at end of page */
669
0
    }
670
    /* Fill the rectangle with the Pattern. */
671
0
    {
672
0
        int code = pdf_open_page(pdev, PDF_IN_STREAM);
673
0
        stream *s;
674
675
0
        if (code < 0)
676
0
            goto use_default;
677
        /* Make sure we aren't being clipped. */
678
0
        code = pdf_put_clip_path(pdev, NULL);
679
0
        if (code < 0)
680
0
            return code;
681
0
        s = pdev->strm;
682
        /*
683
         * Because of bugs in Acrobat Reader's Print function, we can't
684
         * leave the CTM alone here: we have to reset it to the default.
685
         */
686
0
        pprintg2(s, "q %g 0 0 %g 0 0 cm\n", xscale, yscale);
687
0
        cos_value_write(&cs_value, pdev);
688
0
        stream_puts(s, " cs");
689
0
        if (mask)
690
0
            pprintg3(s, " %g %g %g", (int)(color1 >> 16) / 255.0,
691
0
                     (int)((color1 >> 8) & 0xff) / 255.0,
692
0
                     (int)(color1 & 0xff) / 255.0);
693
0
        pprintld1(s, "/R%ld scn", pdf_resource_id(pres));
694
0
        pprintg4(s, " %g %g %g %g re f Q\n",
695
0
                 x / xscale, y / yscale, w / xscale, h / xscale);
696
0
    }
697
0
    return 0;
698
0
use_default:
699
0
    return gx_default_strip_tile_rectangle(dev, tiles, x, y, w, h,
700
0
                                           color0, color1, px, py);
701
0
}