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