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