Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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 
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
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
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
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
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
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
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
}