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 /* 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
pdf_make_bitmap_image(gs_image_t * pim,int x,int y,int w,int h)40 pdf_make_bitmap_image(gs_image_t * pim, int x, int y, int w, int h)
41 {
42     pim->Width = w;
43     pim->Height = h;
44     pdf_make_bitmap_matrix(&pim->ImageMatrix, x, y, w, h, h);
45 }
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
pdf_copy_mask_data(gx_device_pdf * pdev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gs_image_t * pim,pdf_image_writer * piw,int for_pattern)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 {
57     ulong nbytes;
58     int code;
59     const byte *row_base;
60     int row_step;
61     bool in_line;
62 
63     gs_image_t_init_mask(pim, true);
64     pdf_make_bitmap_image(pim, x, y, w, h);
65     nbytes = ((ulong)w * h + 7) / 8;
66 
67     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         row_base = base + (h - 1) * raster;
73         row_step = -raster;
74         in_line = for_pattern < 0;
75     } else {
76         row_base = base;
77         row_step = raster;
78         in_line = nbytes < pdev->MaxInlineImageSize;
79         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         if (id != gx_no_bitmap_id) {
85             piw->pres = pdf_find_resource_by_gs_id(pdev, resourceXObject, id);
86             if (piw->pres)
87                 return 0;
88         }
89     }
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     if (for_pattern < 0)
96         stream_puts(pdev->strm, "q ");
97     pdf_image_writer_init(piw);
98     pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
99     if ((code = pdf_begin_write_image(pdev, piw, id, w, h, NULL, in_line)) < 0 ||
100         (code = psdf_setup_lossless_filters((gx_device_psdf *) pdev,
101                                             &piw->binary[0],
102                                             (gs_pixel_image_t *)pim, in_line)) < 0 ||
103         (code = pdf_begin_image_data(pdev, piw, (const gs_pixel_image_t *)pim,
104                                      NULL, 0)) < 0
105         )
106         return code;
107     pdf_copy_mask_bits(piw->binary[0].strm, row_base, sourcex, row_step, w, h, 0);
108     pdf_end_image_binary(pdev, piw, piw->height);
109     return pdf_end_write_image(pdev, piw);
110 }
111 
112 static void
set_image_color(gx_device_pdf * pdev,gx_color_index c)113 set_image_color(gx_device_pdf *pdev, gx_color_index c)
114 {
115     pdf_set_pure_color(pdev, c, &pdev->saved_fill_color,
116                         &pdev->fill_used_process_color,
117                         &psdf_set_fill_color_commands);
118     if (!pdev->HaveStrokeColor)
119         pdf_set_pure_color(pdev, c, &pdev->saved_stroke_color,
120                             &pdev->stroke_used_process_color,
121                             &psdf_set_stroke_color_commands);
122 }
123 
124 static int
pdf_copy_mono(gx_device_pdf * pdev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one,const gx_clip_path * pcpath)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 {
130     int code;
131     gs_color_space *pcs = NULL;
132     cos_value_t cs_value;
133     cos_value_t *pcsvalue;
134     byte palette[arch_sizeof_color_index * 2];
135     gs_image_t image;
136     pdf_image_writer writer;
137     pdf_stream_position_t ipos;
138     pdf_resource_t *pres = 0;
139     byte invert = 0;
140     bool in_line = false;
141     gs_show_enum *show_enum = (gs_show_enum *)pdev->pte;
142     int x_offset, y_offset;
143     double width;
144 
145     /* Update clipping. */
146     if (pdf_must_put_clip_path(pdev, pcpath)) {
147         code = pdf_open_page(pdev, PDF_IN_STREAM);
148         if (code < 0)
149             return code;
150         code = pdf_put_clip_path(pdev, pcpath);
151         if (code < 0)
152             return code;
153     }
154     /* We have 3 cases: mask, inverse mask, and solid. */
155     if (zero == gx_no_color_index) {
156         if (one == gx_no_color_index)
157             return 0;
158         /* If a mask has an id, assume it's a character. */
159         if (id != gx_no_bitmap_id && sourcex == 0 && show_enum) {
160             pdf_char_proc_t *pcp;
161 
162             if (show_enum->use_wxy_float)
163                 pdev->char_width.x = show_enum->wxy_float.x;
164             else
165                 pdev->char_width.x = fixed2float(show_enum->wxy.x);
166             pres = pdf_find_resource_by_gs_id(pdev, resourceCharProc, id);
167             if (pres == 0) {        /* Define the character in an embedded font. */
168                 gs_image_t_init_mask(&image, false);
169                 invert = 0xff;
170                 x_offset = x - (int)show_enum->pis->current_point.x;
171                 y_offset = y - (int)show_enum->pis->current_point.y;
172                 x -= x_offset;
173                 y -= y_offset;
174                 y -= h;
175                 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                 code = pdf_begin_char_proc(pdev, w, h, 0, y_offset, x_offset, id,
181                                            &pcp, &ipos);
182                 if (code < 0)
183                     return code;
184                 y_offset = -y_offset;
185                 width = psdf_round(pdev->char_width.x, 100, 10); /* See
186                         pdf_write_Widths about rounding. We need to provide
187                         a compatible data for Tj. */
188                 pprintg1(pdev->strm, "%g ", width);
189                 pprintd4(pdev->strm, "0 %d %d %d %d d1\n",  x_offset, -h + y_offset, w + x_offset, y_offset);
190                 pprintd4(pdev->strm, "%d 0 0 %d %d %d cm\n", w, h, x_offset,
191                          -h + y_offset);
192                 pdf_image_writer_init(&writer);
193                 code = pdf_begin_write_image(pdev, &writer, gs_no_id, w, h, NULL, true);
194                 if (code < 0)
195                     return code;
196                 pres = (pdf_resource_t *) pcp;
197                 goto wr;
198             } else if (pdev->pte) {
199                 /* We're under pdf_text_process. It set a high level color. */
200             } else
201                 set_image_color(pdev, one);
202             pcp = (pdf_char_proc_t *) pres;
203             x -= pdf_charproc_x_offset(pcp);
204             y -= pdf_charproc_y_offset(pcp);
205             y -= h;
206             pdf_make_bitmap_image(&image, x, y, w, h);
207             goto rx;
208         }
209         set_image_color(pdev, one);
210         gs_image_t_init_mask(&image, false);
211         invert = 0xff;
212     } else if (one == gx_no_color_index) {
213         gs_image_t_init_mask(&image, false);
214         set_image_color(pdev, zero);
215     } else if (zero == pdev->black && one == pdev->white) {
216         pcs = gs_cspace_new_DeviceGray(pdev->memory);
217         gs_image_t_init(&image, pcs);
218     } else if (zero == pdev->white && one == pdev->black) {
219         pcs = gs_cspace_new_DeviceGray(pdev->memory);
220         gs_image_t_init(&image, pcs);
221         invert = 0xff;
222     } else {
223         /*
224          * We think this code is never executed when interpreting PostScript
225          * or PDF: the library never uses monobit non-mask images
226          * internally, and high-level images don't go through this code.
227          * However, we still want the code to work.
228          */
229         gs_color_space *pcs_base;
230         gx_color_index c[2];
231         int i, j;
232         int ncomp = pdev->color_info.num_components;
233         byte *p;
234 
235         code = pdf_cspace_init_Device(pdev->memory, &pcs_base, ncomp);
236         if (code < 0)
237             return code;
238         c[0] = psdf_adjust_color_index((gx_device_vector *)pdev, zero);
239         c[1] = psdf_adjust_color_index((gx_device_vector *)pdev, one);
240         pcs = gs_cspace_alloc(pdev->memory, &gs_color_space_type_Indexed);
241         if (pcs == NULL) {
242             rc_decrement_cs(pcs_base, "pdf_copy_mono");
243             return_error(gs_error_VMerror);
244         }
245         pcs->base_space = pcs_base;
246         pcs->params.indexed.hival = 1;
247         pcs->params.indexed.n_comps = ncomp;
248         p = palette;
249         for (i = 0; i < 2; ++i)
250             for (j = ncomp - 1; j >= 0; --j)
251                 *p++ = (byte)(c[i] >> (j * 8));
252         pcs->params.indexed.lookup.table.data = palette;
253         pcs->params.indexed.lookup.table.size = p - palette;
254         pcs->params.indexed.use_proc = false;
255         gs_image_t_init(&image, pcs);
256         image.BitsPerComponent = 1;
257     }
258     pdf_make_bitmap_image(&image, x, y, w, h);
259     {
260         ulong nbytes = (ulong) ((w + 7) >> 3) * h;
261 
262         code = pdf_open_page(pdev, PDF_IN_STREAM);
263         if (code < 0)
264             return code;
265         in_line = nbytes < pdev->MaxInlineImageSize;
266         if (in_line)
267             pdf_put_image_matrix(pdev, &image.ImageMatrix, 1.0);
268         pdf_image_writer_init(&writer);
269         code = pdf_begin_write_image(pdev, &writer, gs_no_id, w, h, NULL, in_line);
270         if (code < 0)
271             return code;
272     }
273   wr:
274     if (image.ImageMask)
275         pcsvalue = NULL;
276     else {
277         /*
278          * We don't have to worry about color space scaling: the color
279          * space is always a Device space.
280          */
281         code = pdf_color_space_named(pdev, &cs_value, NULL, pcs,
282                                &writer.pin->color_spaces, in_line, NULL, 0);
283         if (code < 0)
284             return code;
285         pcsvalue = &cs_value;
286     }
287     /*
288      * There are 3 different cases at this point:
289      *      - Writing an in-line image (pres == 0, writer.pres == 0);
290      *      - Writing an XObject image (pres == 0, writer.pres != 0);
291      *      - Writing the image for a CharProc (pres != 0).
292      * We handle them with in-line code followed by a switch,
293      * rather than making the shared code into a procedure,
294      * simply because there would be an awful lot of parameters
295      * that would need to be passed.
296      */
297     if (pres) {
298         if (!pdev->NoT3CCITT) {
299             /*
300              * Always use CCITTFax 2-D for character bitmaps.  It takes less
301              * space to invert the data with Decode than to set BlackIs1.
302              */
303             float d0 = image.Decode[0];
304 
305             image.Decode[0] = image.Decode[1];
306             image.Decode[1] = d0;
307             psdf_CFE_binary(&writer.binary[0], image.Width, image.Height, true);
308             invert ^= 0xff;
309         }
310     } else {
311         /* Use the Distiller compression parameters. */
312         pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
313         psdf_setup_image_filters((gx_device_psdf *) pdev, &writer.binary[0],
314                                  (gs_pixel_image_t *)&image, NULL, NULL, true, in_line);
315     }
316     pdf_begin_image_data(pdev, &writer, (const gs_pixel_image_t *)&image,
317                          pcsvalue, 0);
318     code = pdf_copy_mask_bits(writer.binary[0].strm, base, sourcex, raster,
319                               w, h, invert);
320     if (code < 0)
321         return code;
322     pdf_end_image_binary(pdev, &writer, writer.height);
323     if (!pres) {
324         switch ((code = pdf_end_write_image(pdev, &writer))) {
325             default:                /* error */
326                 return code;
327             case 1:
328                 return 0;
329             case 0:
330                 return pdf_do_image(pdev, writer.pres, &image.ImageMatrix,
331                                     true);
332         }
333     }
334     writer.end_string = "";        /* no Q */
335     switch ((code = pdf_end_write_image(pdev, &writer))) {
336     default:                /* error */
337         return code;
338     case 0:                        /* not possible */
339         return_error(gs_error_Fatal);
340     case 1:
341         break;
342     }
343     code = pdf_end_char_proc(pdev, &ipos);
344     if (code < 0)
345         return code;
346   rx:{
347         gs_matrix imat;
348 
349         imat = image.ImageMatrix;
350         imat.xx /= w;
351         imat.xy /= h;
352         imat.yx /= w;
353         imat.yy /= h;
354         return pdf_do_char_image(pdev, (const pdf_char_proc_t *)pres, &imat);
355     }
356 }
357 int
gdev_pdf_copy_mono(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)358 gdev_pdf_copy_mono(gx_device * dev,
359                    const byte * base, int sourcex, int raster, gx_bitmap_id id,
360                    int x, int y, int w, int h, gx_color_index zero,
361                    gx_color_index one)
362 {
363     gx_device_pdf *pdev = (gx_device_pdf *) dev;
364 
365     if (w <= 0 || h <= 0)
366         return 0;
367     return pdf_copy_mono(pdev, base, sourcex, raster, id, x, y, w, h,
368                          zero, one, NULL);
369 }
370 
371 /* Copy a color bitmap.  for_pattern = -1 means put the image in-line, */
372 /* 1 means put the image in a resource, 2 means image is a rasterized shading. */
373 int
pdf_copy_color_data(gx_device_pdf * pdev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gs_image_t * pim,pdf_image_writer * piw,int for_pattern)374 pdf_copy_color_data(gx_device_pdf * pdev, const byte * base, int sourcex,
375                     int raster, gx_bitmap_id id, int x, int y, int w, int h,
376                     gs_image_t *pim, pdf_image_writer *piw,
377                     int for_pattern)
378 {
379     int depth = pdev->color_info.depth;
380     int bytes_per_pixel = depth >> 3;
381     gs_color_space *pcs;
382     cos_value_t cs_value;
383     ulong nbytes;
384     int code = pdf_cspace_init_Device(pdev->memory, &pcs, bytes_per_pixel);
385     const byte *row_base;
386     int row_step;
387     bool in_line;
388 
389     if (code < 0)
390         return code;                /* can't happen */
391     gs_image_t_init(pim, pcs);
392     pdf_make_bitmap_image(pim, x, y, w, h);
393     pim->BitsPerComponent = 8;
394     nbytes = (ulong)w * bytes_per_pixel * h;
395 
396     if (for_pattern == 1) {
397         /*
398          * Patterns must be emitted in order of increasing user Y, i.e.,
399          * the opposite of PDF's standard image order.
400          */
401         row_base = base + (h - 1) * raster;
402         row_step = -raster;
403         in_line = for_pattern < 0;
404     } else {
405         row_base = base;
406         row_step = raster;
407         in_line = nbytes < pdev->MaxInlineImageSize;
408         pdf_put_image_matrix(pdev, &pim->ImageMatrix, 1.0);
409         /*
410          * Check whether we've already made an XObject resource for this
411          * image.
412          */
413         if (id != gx_no_bitmap_id) {
414             piw->pres = pdf_find_resource_by_gs_id(pdev, resourceXObject, id);
415             if (piw->pres)
416                 return 0;
417         }
418     }
419     /*
420      * We have to be able to control whether to put Pattern images in line,
421      * to avoid trying to create an XObject resource while we're in the
422      * middle of writing a Pattern resource.
423      */
424     if (for_pattern < 0)
425         stream_puts(pdev->strm, "q ");
426     /*
427      * We don't have to worry about color space scaling: the color
428      * space is always a Device space.
429      */
430     pdf_image_writer_init(piw);
431     pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
432     if ((code = pdf_begin_write_image(pdev, piw, id, w, h, NULL, in_line)) < 0 ||
433         (code = pdf_color_space_named(pdev, &cs_value, NULL, pcs,
434                                 &piw->pin->color_spaces, in_line, NULL, 0)) < 0 ||
435         (for_pattern < 2 || nbytes < 512000 ?
436             (code = psdf_setup_lossless_filters((gx_device_psdf *) pdev,
437                         &piw->binary[0], (gs_pixel_image_t *)pim, false)) :
438             (code = psdf_setup_image_filters((gx_device_psdf *) pdev,
439                         &piw->binary[0], (gs_pixel_image_t *)pim, NULL, NULL, false, false))
440         ) < 0 ||
441         (code = pdf_begin_image_data(pdev, piw, (const gs_pixel_image_t *)pim,
442                                      &cs_value, 0)) < 0
443         )
444         return code;
445     pdf_copy_color_bits(piw->binary[0].strm, row_base, sourcex, row_step, w, h,
446                         bytes_per_pixel);
447     pdf_end_image_binary(pdev, piw, piw->height);
448     return pdf_end_write_image(pdev, piw);
449 }
450 
451 int
gdev_pdf_copy_color(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)452 gdev_pdf_copy_color(gx_device * dev, const byte * base, int sourcex,
453                     int raster, gx_bitmap_id id, int x, int y, int w, int h)
454 {
455     gx_device_pdf *pdev = (gx_device_pdf *) dev;
456     gs_image_t image;
457     pdf_image_writer writer;
458     int code;
459 
460     if (w <= 0 || h <= 0)
461         return 0;
462     code = pdf_open_page(pdev, PDF_IN_STREAM);
463     if (code < 0)
464         return code;
465     /* Make sure we aren't being clipped. */
466     code = pdf_put_clip_path(pdev, NULL);
467     if (code < 0)
468         return code;
469     code = pdf_copy_color_data(pdev, base, sourcex, raster, id, x, y, w, h,
470                                &image, &writer, 0);
471     switch (code) {
472         default:
473             return code;        /* error */
474         case 1:
475             return 0;
476         case 0:
477             return pdf_do_image(pdev, writer.pres, NULL, true);
478     }
479 }
480 
481 /* Fill a mask. */
482 int
gdev_pdf_fill_mask(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,const gx_drawing_color * pdcolor,int depth,gs_logical_operation_t lop,const gx_clip_path * pcpath)483 gdev_pdf_fill_mask(gx_device * dev,
484                  const byte * data, int data_x, int raster, gx_bitmap_id id,
485                    int x, int y, int width, int height,
486                    const gx_drawing_color * pdcolor, int depth,
487                    gs_logical_operation_t lop, const gx_clip_path * pcpath)
488 {
489     gx_device_pdf *pdev = (gx_device_pdf *) dev;
490 
491     if (width <= 0 || height <= 0)
492         return 0;
493     if (depth > 1 || (!gx_dc_is_pure(pdcolor) != 0 && !(gx_dc_is_pattern1_color(pdcolor))))
494         return gx_default_fill_mask(dev, data, data_x, raster, id,
495                                     x, y, width, height, pdcolor, depth, lop,
496                                     pcpath);
497     return pdf_copy_mono(pdev, data, data_x, raster, id, x, y, width, height,
498                          gx_no_color_index, gx_dc_pure_color(pdcolor),
499                          pcpath);
500 }
501 
502 /* Tile with a bitmap.  This is important for pattern fills. */
503 int
gdev_pdf_strip_tile_rectangle(gx_device * dev,const gx_strip_bitmap * tiles,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1,int px,int py)504 gdev_pdf_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
505                               int x, int y, int w, int h,
506                               gx_color_index color0, gx_color_index color1,
507                               int px, int py)
508 {
509     gx_device_pdf *const pdev = (gx_device_pdf *) dev;
510     int tw = tiles->rep_width, th = tiles->rep_height;
511     double xscale = pdev->HWResolution[0] / 72.0,
512         yscale = pdev->HWResolution[1] / 72.0;
513     bool mask;
514     int depth;
515     int (*copy_data)(gx_device_pdf *, const byte *, int, int,
516                      gx_bitmap_id, int, int, int, int,
517                      gs_image_t *, pdf_image_writer *, int);
518     pdf_resource_t *pres;
519     cos_value_t cs_value;
520     int code;
521 
522     if (tiles->id == gx_no_bitmap_id || tiles->shift != 0 ||
523         (w < tw && h < th) ||
524         color0 != gx_no_color_index
525         )
526         goto use_default;
527     if (color1 != gx_no_color_index) {
528         /* This is a mask pattern. */
529         mask = true;
530         depth = 1;
531         copy_data = pdf_copy_mask_data;
532         code = pdf_cs_Pattern_uncolored(pdev, &cs_value);
533     } else {
534         /* This is a colored pattern. */
535         mask = false;
536         depth = pdev->color_info.depth;
537         copy_data = pdf_copy_color_data;
538         code = pdf_cs_Pattern_colored(pdev, &cs_value);
539     }
540     if (code < 0)
541         goto use_default;
542     pres = pdf_find_resource_by_gs_id(pdev, resourcePattern, tiles->id);
543     if (!pres) {
544         /* Create the Pattern resource. */
545         int code;
546         long image_id, length_id, start, end;
547         stream *s;
548         gs_image_t image;
549         pdf_image_writer writer;
550         long image_bytes = ((long)tw * depth + 7) / 8 * th;
551         bool in_line = image_bytes < pdev->MaxInlineImageSize;
552         ulong tile_id =
553             (tw == tiles->size.x && th == tiles->size.y ? tiles->id :
554              gx_no_bitmap_id);
555 
556         if (in_line)
557             image_id = 0;
558         else if (image_bytes > 65500) {
559             /*
560              * Acrobat Reader can't handle image Patterns with more than
561              * 64K of data.  :-(
562              */
563             goto use_default;
564         } else {
565             /* Write the image as an XObject resource now. */
566             code = copy_data(pdev, tiles->data, 0, tiles->raster,
567                              tile_id, 0, 0, tw, th, &image, &writer, 1);
568             if (code < 0)
569                 goto use_default;
570             image_id = pdf_resource_id(writer.pres);
571         }
572         code = pdf_begin_resource(pdev, resourcePattern, tiles->id, &pres);
573         if (code < 0)
574             goto use_default;
575         s = pdev->strm;
576         pprintd1(s, "/PatternType 1/PaintType %d/TilingType 1/Resources<<\n",
577                  (mask ? 2 : 1));
578         if (image_id)
579             pprintld2(s, "/XObject<</R%ld %ld 0 R>>", image_id, image_id);
580         pprints1(s, "/ProcSet[/PDF/Image%s]>>\n", (mask ? "B" : "C"));
581         /*
582          * Because of bugs in Acrobat Reader's Print function, we can't use
583          * the natural BBox and Step here: they have to be 1.
584          */
585         pprintg2(s, "/Matrix[%g 0 0 %g 0 0]", tw / xscale, th / yscale);
586         stream_puts(s, "/BBox[0 0 1 1]/XStep 1/YStep 1/Length ");
587         if (image_id) {
588             char buf[MAX_REF_CHARS + 6 + 1]; /* +6 for /R# Do\n */
589 
590             sprintf(buf, "/R%ld Do\n", image_id);
591             pprintd1(s, "%d>>stream\n", strlen(buf));
592             if (pdev->PDFA != 0)
593                 pprints1(s, "%s\nendstream\n", buf);
594             else
595                 pprints1(s, "%sendstream\n", buf);
596             pdf_end_resource(pdev, resourcePattern);
597         } else {
598             length_id = pdf_obj_ref(pdev);
599             pprintld1(s, "%ld 0 R>>stream\n", length_id);
600             start = pdf_stell(pdev);
601             code = copy_data(pdev, tiles->data, 0, tiles->raster,
602                              tile_id, 0, 0, tw, th, &image, &writer, -1);
603             switch (code) {
604             default:
605                 return code;        /* error */
606             case 1:
607                 break;
608             case 0:                        /* not possible */
609                 return_error(gs_error_Fatal);
610             }
611             end = pdf_stell(pdev);
612             stream_puts(s, "\nendstream\n");
613             pdf_end_resource(pdev, resourcePattern);
614             pdf_open_separate(pdev, length_id, resourceNone);
615             pprintld1(pdev->strm, "%ld\n", end - start);
616             pdf_end_separate(pdev, resourceNone);
617         }
618         pres->object->written = true; /* don't write at end of page */
619     }
620     /* Fill the rectangle with the Pattern. */
621     {
622         int code = pdf_open_page(pdev, PDF_IN_STREAM);
623         stream *s;
624 
625         if (code < 0)
626             goto use_default;
627         /* Make sure we aren't being clipped. */
628         code = pdf_put_clip_path(pdev, NULL);
629         if (code < 0)
630             return code;
631         s = pdev->strm;
632         /*
633          * Because of bugs in Acrobat Reader's Print function, we can't
634          * leave the CTM alone here: we have to reset it to the default.
635          */
636         pprintg2(s, "q %g 0 0 %g 0 0 cm\n", xscale, yscale);
637         cos_value_write(&cs_value, pdev);
638         stream_puts(s, " cs");
639         if (mask)
640             pprintg3(s, " %g %g %g", (int)(color1 >> 16) / 255.0,
641                      (int)((color1 >> 8) & 0xff) / 255.0,
642                      (int)(color1 & 0xff) / 255.0);
643         pprintld1(s, "/R%ld scn", pdf_resource_id(pres));
644         pprintg4(s, " %g %g %g %g re f Q\n",
645                  x / xscale, y / yscale, w / xscale, h / xscale);
646     }
647     return 0;
648 use_default:
649     return gx_default_strip_tile_rectangle(dev, tiles, x, y, w, h,
650                                            color0, color1, px, py);
651 }
652