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) 1995, 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: gdevdrop.c,v 1.7 2002/08/22 07:12:28 henrys Exp $ */
18
/* Default and device-independent RasterOp algorithms */
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gsbittab.h"
22
#include "gserrors.h"
23
#include "gsropt.h"
24
#include "gxcindex.h"
25
#include "gxdcolor.h"
26
#include "gxdevice.h"
27
#include "gxdevmem.h"
28
#include "gxdevrop.h"
29
#include "gxgetbit.h"
30
#include "gdevmem.h"		/* for mem_default_strip_copy_rop prototype */
31
#include "gdevmrop.h"
32
 
33
/*
34
 * Define the maximum amount of space we are willing to allocate for a
35
 * multiple-row RasterOp buffer.  (We are always willing to allocate
36
 * one row, no matter how wide.)
37
 */
38
private const uint max_rop_bitmap = 1000;
39
 
40
/* ---------------- Debugging aids ---------------- */
41
 
42
#ifdef DEBUG
43
 
44
void
45
trace_copy_rop(const char *cname, gx_device * dev,
46
	       const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
47
	       const gx_color_index * scolors,
48
	       const gx_strip_bitmap * textures,
49
	       const gx_color_index * tcolors,
50
	       int x, int y, int width, int height,
51
	       int phase_x, int phase_y, gs_logical_operation_t lop)
52
{
53
    dlprintf4("%s: dev=0x%lx(%s) depth=%d\n",
54
	      cname, (ulong) dev, dev->dname, dev->color_info.depth);
55
    dlprintf4("  source data=0x%lx x=%d raster=%u id=%lu colors=",
56
	      (ulong) sdata, sourcex, sraster, (ulong) id);
57
    if (scolors)
58
	dprintf2("(%lu,%lu);\n", scolors[0], scolors[1]);
59
    else
60
	dputs("none;\n");
61
    if (textures)
62
	dlprintf8("  textures=0x%lx size=%dx%d(%dx%d) raster=%u shift=%d(%d)",
63
		  (ulong) textures, textures->size.x, textures->size.y,
64
		  textures->rep_width, textures->rep_height,
65
		  textures->raster, textures->shift, textures->rep_shift);
66
    else
67
	dlputs("  textures=none");
68
    if (tcolors)
69
	dprintf2(" colors=(%lu,%lu)\n", tcolors[0], tcolors[1]);
70
    else
71
	dputs(" colors=none\n");
72
    dlprintf7("  rect=(%d,%d),(%d,%d) phase=(%d,%d) op=0x%x\n",
73
	      x, y, x + width, y + height, phase_x, phase_y,
74
	      (uint) lop);
75
    if (gs_debug_c('B')) {
76
	if (sdata)
77
	    debug_dump_bitmap(sdata, sraster, height, "source bits");
78
	if (textures && textures->data)
79
	    debug_dump_bitmap(textures->data, textures->raster,
80
			      textures->size.y, "textures bits");
81
    }
82
}
83
 
84
#endif
85
 
86
/* ---------------- Default copy_rop implementations ---------------- */
87
 
88
/*
89
 * The default implementation for non-memory devices uses get_bits_rectangle
90
 * to read out the pixels, the memory device implementation to do the
91
 * operation, and copy_color to write the pixels back.
92
 */
93
int
94
gx_default_strip_copy_rop(gx_device * dev,
95
			  const byte * sdata, int sourcex,
96
			  uint sraster, gx_bitmap_id id,
97
			  const gx_color_index * scolors,
98
			  const gx_strip_bitmap * textures,
99
			  const gx_color_index * tcolors,
100
			  int x, int y, int width, int height,
101
			  int phase_x, int phase_y,
102
			  gs_logical_operation_t lop)
103
{
104
    int depth = dev->color_info.depth;
105
    gs_memory_t *mem = dev->memory;
106
    const gx_device_memory *mdproto = gdev_mem_device_for_bits(depth);
107
    gx_device_memory mdev;
108
    uint draster;
109
    byte *row = 0;
110
    gs_int_rect rect;
111
    int max_height;
112
    int block_height;
113
    int code;
114
    int py;
115
 
116
#ifdef DEBUG
117
    if (gs_debug_c('b'))
118
	trace_copy_rop("gx_default_strip_copy_rop",
119
		       dev, sdata, sourcex, sraster,
120
		       id, scolors, textures, tcolors,
121
		       x, y, width, height, phase_x, phase_y, lop);
122
#endif
123
    if (mdproto == 0)
124
	return_error(gs_error_rangecheck);
125
    if (sdata == 0) {
126
	fit_fill(dev, x, y, width, height);
127
    } else {
128
	fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height);
129
    }
130
    draster = bitmap_raster(width * depth);
131
    max_height = max_rop_bitmap / draster;
132
    if (max_height == 0)
133
	max_height = 1;
134
    block_height = min(height, max_height);
135
    gs_make_mem_device(&mdev, mdproto, mem, -1, dev);
136
    gx_device_retain((gx_device *)&mdev, true);	/* prevent freeing */
137
    mdev.width = width;
138
    mdev.height = block_height;
139
    mdev.bitmap_memory = mem;
140
    mdev.color_info = dev->color_info;
141
    code = (*dev_proc(&mdev, open_device))((gx_device *)&mdev);
142
    if (code < 0)
143
	return code;
144
    if (rop3_uses_D(gs_transparent_rop(lop))) {
145
	row = gs_alloc_bytes(mem, draster * block_height, "copy_rop row");
146
	if (row == 0) {
147
	    code = gs_note_error(gs_error_VMerror);
148
	    goto out;
149
	}
150
    }
151
    rect.p.x = x;
152
    rect.q.x = x + width;
153
    for (py = y; py < y + height; py += block_height) {
154
	if (block_height > y + height - py)
155
	    block_height = y + height - py;
156
	rect.p.y = py;
157
	rect.q.y = py + block_height;
158
	if (row /*uses_d*/) {
159
	    gs_get_bits_params_t bit_params;
160
 
161
	    bit_params.options =
162
		GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_DEPTH_ALL |
163
		GB_PACKING_CHUNKY | GB_RETURN_ALL | GB_ALIGN_STANDARD |
164
		GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD;
165
	    bit_params.data[0] = row;
166
	    bit_params.x_offset = 0;
167
	    code = (*dev_proc(dev, get_bits_rectangle))
168
		(dev, &rect, &bit_params, NULL);
169
	    if (code < 0)
170
		break;
171
	    code = (*dev_proc(&mdev, copy_color))
172
		((gx_device *)&mdev, bit_params.data[0], bit_params.x_offset,
173
		 draster, gx_no_bitmap_id, 0, 0, width,
174
		 block_height);
175
	    if (code < 0)
176
		return code;
177
	}
178
	code = (*dev_proc(&mdev, strip_copy_rop))
179
	    ((gx_device *)&mdev,
180
	     sdata + (py - y) * sraster, sourcex, sraster,
181
	     gx_no_bitmap_id, scolors, textures, tcolors,
182
	     0, 0, width, block_height, phase_x + x, phase_y + py, lop);
183
	if (code < 0)
184
	    break;
185
	code = (*dev_proc(dev, copy_color))
186
	    (dev, scan_line_base(&mdev, 0), 0, draster, gx_no_bitmap_id,
187
	     x, py, width, block_height);
188
	if (code < 0)
189
	    break;
190
    }
191
out:
192
    gs_free_object(mem, row, "copy_rop row");
193
    (*dev_proc(&mdev, close_device))((gx_device *)&mdev);
194
    return code;
195
}
196
 
197
/* ---------------- Default memory device copy_rop ---------------- */
198
 
199
/* Convert color constants to standard RGB representation. */
200
private void
201
unpack_colors_to_standard(gx_device * dev, gx_color_index real_colors[2],
202
			  const gx_color_index * colors, int depth)
203
{
204
    int i;
205
 
206
    for (i = 0; i < 2; ++i) {
207
	gx_color_value rgb[3];
208
	gx_color_index pixel;
209
 
210
	(*dev_proc(dev, map_color_rgb)) (dev, colors[i], rgb);
211
	pixel = gx_color_value_to_byte(rgb[0]);
212
	if (depth > 8) {
213
	    pixel = (pixel << 16) +
214
		(gx_color_value_to_byte(rgb[1]) << 8) +
215
		gx_color_value_to_byte(rgb[2]);
216
	}
217
	real_colors[i] = pixel;
218
    }
219
}
220
 
221
/*
222
 * Convert RGB to the device's native format.  We special-case this for
223
 * 1-bit CMYK devices.
224
 */
225
private void
226
pack_cmyk_1bit_from_standard(gx_device * dev, byte * dest, int destx,
227
			     const byte * src, int width, int depth,
228
			     int src_depth)
229
{
230
    /*
231
     * This routine is only called if dev_proc(dev, map_cmyk_color) ==
232
     * cmyk_1bit_map_cmyk_color (implying depth == 4) and src_depth == 24.
233
     */
234
    int bit_x = destx * 4;
235
    byte *dp = dest + (bit_x >> 3);
236
    bool hi = (bit_x & 4) != 0;	 /* true if last nibble filled was hi */
237
    byte buf = (hi ? *dp & 0xf0 : 0);
238
    const byte *sp = src;
239
    int x;
240
 
241
    for (x = width; --x >= 0; sp += 3) {
242
	byte r = sp[0], g = sp[1], b = sp[2];
243
	byte pixel =
244
	    (r | g | b ?
245
	     (((r >> 4) & 8) | ((g >> 5) & 4) | ((b >> 6) & 2)) ^ 0xe : 1);
246
 
247
	if ((hi = !hi))
248
	    buf = pixel << 4;
249
	else
250
	    *dp++ = buf | pixel;
251
    }
252
    if (hi && width > 0)
253
	*dp = buf | (*dp & 0xf);
254
 
255
}
256
 
257
private gx_color_index
258
map_rgb_to_color_via_cmyk(gx_device * dev, const gx_color_value rgbcv[])
259
{
260
    gx_color_value cmykcv[4];
261
 
262
    cmykcv[0] = gx_max_color_value - rgbcv[0];
263
    cmykcv[1] = gx_max_color_value - rgbcv[1];
264
    cmykcv[2] = gx_max_color_value - rgbcv[2];
265
    cmykcv[3] = (cmykcv[0] < cmykcv[1] ? min(cmykcv[0], cmykcv[2]) : min(cmykcv[1], cmykcv[2]));
266
 
267
    cmykcv[0] -= cmykcv[3];
268
    cmykcv[1] -= cmykcv[3];
269
    cmykcv[2] -= cmykcv[3];
270
 
271
    return (*dev_proc(dev, map_cmyk_color)) (dev, cmykcv);
272
}
273
private void
274
pack_from_standard(gx_device * dev, byte * dest, int destx, const byte * src,
275
		   int width, int depth, int src_depth)
276
{
277
    dev_proc_map_rgb_color((*map)) =
278
	(dev->color_info.num_components == 4 ?
279
	 map_rgb_to_color_via_cmyk : dev_proc(dev, map_rgb_color));
280
    int bit_x = destx * depth;
281
    byte *dp = dest + (bit_x >> 3);
282
    int shift = (~bit_x & 7) + 1;
283
    byte buf = (shift == 8 ? 0 : *dp & (0xff00 >> shift));
284
    const byte *sp = src;
285
    int x;
286
 
287
    for (x = width; --x >= 0;) {
288
	byte vr, vg, vb;
289
	gx_color_index pixel;
290
	byte chop = 0x1;
291
 
292
	vr = *sp++;
293
	if (src_depth > 8) {
294
	    vg = *sp++;
295
	    vb = *sp++;
296
	} else
297
	    vb = vg = vr;
298
	/*
299
	 * We have to map back to some pixel value, even if the color
300
	 * isn't accurate.
301
	 */
302
	for (;;) {
303
            gx_color_value cv[3];
304
	    cv[0] = gx_color_value_from_byte(vr);
305
	    cv[1] = gx_color_value_from_byte(vg);
306
	    cv[2] = gx_color_value_from_byte(vb);
307
	    pixel = (*map) (dev, cv);
308
	    if (pixel != gx_no_color_index)
309
		break;
310
	    /* Reduce the color accuracy and try again. */
311
	    vr = (vr >= 0x80 ? vr | chop : vr & ~chop);
312
	    vg = (vg >= 0x80 ? vg | chop : vg & ~chop);
313
	    vb = (vb >= 0x80 ? vb | chop : vb & ~chop);
314
	    chop <<= 1;
315
	}
316
	if ((shift -= depth) >= 0)
317
	    buf += (byte)(pixel << shift);
318
	else {
319
	    switch (depth) {
320
	    default:		/* 1, 2, 4, 8 */
321
		*dp++ = buf;
322
		shift += 8;
323
		buf = (byte)(pixel << shift);
324
		break;
325
	    case 32:
326
		*dp++ = (byte)(pixel >> 24);
327
		*dp++ = (byte)(pixel >> 16);
328
	    case 16:
329
		*dp++ = (byte)(pixel >> 8);
330
		*dp++ = (byte)pixel;
331
		shift = 0;
332
	    }
333
	}
334
    }
335
    if (width > 0 && depth <= 8)
336
	*dp = (shift == 0 ? buf : buf + (*dp & ((1 << shift) - 1)));
337
}
338
 
339
/*
340
 * The default implementation for memory devices uses get_bits_rectangle to
341
 * read out the pixels and convert them to standard (8-bit gray or 24-bit
342
 * RGB) representation, the standard memory device implementation to do the
343
 * operation, pack_from_standard to convert them back to the device
344
 * representation, and copy_color to write the pixels back.
345
 */
346
int
347
mem_default_strip_copy_rop(gx_device * dev,
348
			  const byte * sdata, int sourcex,
349
			  uint sraster, gx_bitmap_id id,
350
			  const gx_color_index * scolors,
351
			  const gx_strip_bitmap * textures,
352
			  const gx_color_index * tcolors,
353
			  int x, int y, int width, int height,
354
			  int phase_x, int phase_y,
355
			  gs_logical_operation_t lop)
356
{
357
    int depth = dev->color_info.depth;
358
    int rop_depth = (gx_device_has_color(dev) ? 24 : 8);
359
    void (*pack)(gx_device *, byte *, int, const byte *, int, int, int) =
360
	(dev_proc(dev, map_cmyk_color) == cmyk_1bit_map_cmyk_color &&
361
	 rop_depth == 24 ? pack_cmyk_1bit_from_standard : pack_from_standard);
362
    const gx_bitmap_format_t no_expand_options =
363
	GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_DEPTH_ALL |
364
	GB_PACKING_CHUNKY | GB_RETURN_ALL | GB_ALIGN_STANDARD |
365
	GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD;
366
    const gx_bitmap_format_t expand_options =
367
	(rop_depth > 8 ? GB_COLORS_RGB : GB_COLORS_GRAY) |
368
	GB_ALPHA_NONE | GB_DEPTH_8 |
369
	GB_PACKING_CHUNKY | GB_RETURN_COPY | GB_ALIGN_STANDARD |
370
	GB_OFFSET_0 | GB_RASTER_STANDARD;
371
    gs_memory_t *mem = dev->memory;
372
    const gx_device_memory *mdproto = gdev_mem_device_for_bits(rop_depth);
373
    gx_device_memory mdev;
374
    union { long l; void *p; } mdev_storage[20];
375
    uint row_raster = bitmap_raster(width * depth);
376
    gs_rop3_t trans_rop = gs_transparent_rop(lop);
377
    bool uses_d = rop3_uses_D(trans_rop);
378
    bool uses_s = rop3_uses_S(trans_rop);
379
    bool uses_t = rop3_uses_T(trans_rop);
380
    bool expand_s, expand_t;
381
    byte *row = 0;
382
    union { long l; void *p; } dest_buffer[16];
383
    byte *source_row = 0;
384
    uint source_row_raster;
385
    union { long l; void *p; } source_buffer[16];
386
    byte *texture_row = 0;
387
    uint texture_row_raster;
388
    union { long l; void *p; } texture_buffer[16];
389
    gx_color_index source_colors[2];
390
    const gx_color_index *real_scolors = scolors;
391
    gx_color_index texture_colors[2];
392
    const gx_color_index *real_tcolors = tcolors;
393
    gx_strip_bitmap rop_texture;
394
    const gx_strip_bitmap *real_texture = textures;
395
    gs_int_rect rect;
396
    gs_get_bits_params_t bit_params;
397
    gs_get_bits_params_t expand_params;
398
    gs_get_bits_params_t no_expand_params;
399
    int max_height;
400
    int block_height, loop_height;
401
    int code;
402
    int py;
403
 
404
/*
405
 * Allocate a temporary row buffer.  Free variables: mem, block_height.
406
 * Labels used: out.
407
 */
408
#define ALLOC_BUF(buf, prebuf, size, cname)\
409
	BEGIN\
410
	  uint num_bytes = (size) * block_height;\
411
\
412
	  if (num_bytes <= sizeof(prebuf))\
413
	    buf = (byte *)prebuf;\
414
	  else {\
415
	    buf = gs_alloc_bytes(mem, num_bytes, cname);\
416
	    if (buf == 0) {\
417
	      code = gs_note_error(gs_error_VMerror);\
418
	      goto out;\
419
	    }\
420
	  }\
421
	END
422
 
423
#ifdef DEBUG
424
    if (gs_debug_c('b'))
425
	trace_copy_rop("mem_default_strip_copy_rop",
426
		       dev, sdata, sourcex, sraster,
427
		       id, scolors, textures, tcolors,
428
		       x, y, width, height, phase_x, phase_y, lop);
429
#endif
430
    if (mdproto == 0)
431
	return_error(gs_error_rangecheck);
432
    if (sdata == 0) {
433
	fit_fill(dev, x, y, width, height);
434
    } else {
435
	fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height);
436
    }
437
    /* Compute max_height conservatively. */
438
    max_height = max_rop_bitmap / (width * rop_depth);
439
    if (max_height == 0)
440
	max_height = 1;
441
    block_height = min(height, max_height);
442
    expand_s = scolors == 0 && uses_s;
443
    expand_t = tcolors == 0 && uses_t;
444
    no_expand_params.options = no_expand_options;
445
    if (expand_t) {
446
	/*
447
	 * We don't want to wrap around more than once in Y when
448
	 * copying the texture to the intermediate buffer.
449
	 */
450
	if (textures->size.y < block_height)
451
	    block_height = textures->size.y;
452
    }
453
    gs_make_mem_device(&mdev, mdproto, mem, -1, NULL);
454
    gx_device_retain((gx_device *)&mdev, true);	/* prevent freeing */
455
    mdev.width = width;
456
    mdev.height = block_height;
457
    mdev.color_info.num_components = rop_depth >> 3;
458
    if (gdev_mem_data_size(&mdev, width, block_height) <= sizeof(mdev_storage)) {
459
	/* Use the locally allocated storage. */
460
	mdev.base = (byte *)mdev_storage;
461
	mdev.line_ptrs = (byte **)
462
	    (mdev.base + gdev_mem_bits_size(&mdev, mdev.width, mdev.height));
463
    } else {
464
	mdev.bitmap_memory = mem;
465
    }
466
    code = (*dev_proc(&mdev, open_device))((gx_device *)&mdev);
467
    if (code < 0)
468
	return code;
469
    ALLOC_BUF(row, dest_buffer, row_raster, "copy_rop row");
470
    /* We may need intermediate buffers for all 3 operands. */
471
    if (expand_s) {
472
	source_row_raster = bitmap_raster(width * rop_depth);
473
	ALLOC_BUF(source_row, source_buffer, source_row_raster,
474
		  "copy_rop source_row");
475
    }
476
    if (scolors && uses_s) {
477
	unpack_colors_to_standard(dev, source_colors, scolors, rop_depth);
478
	real_scolors = source_colors;
479
    }
480
    if (expand_t) {
481
	texture_row_raster = bitmap_raster(textures->rep_width * rop_depth);
482
	ALLOC_BUF(texture_row, texture_buffer, texture_row_raster,
483
		  "copy_rop texture_row");
484
	rop_texture = *textures;
485
	rop_texture.data = texture_row;
486
	rop_texture.raster = texture_row_raster;
487
	rop_texture.size.x = rop_texture.rep_width;
488
	rop_texture.id = gs_no_bitmap_id;
489
	real_texture = &rop_texture;
490
    }
491
    if (tcolors && uses_t) {
492
	unpack_colors_to_standard(dev, texture_colors, tcolors, rop_depth);
493
	real_tcolors = texture_colors;
494
    }
495
    expand_params.options = expand_options;
496
    expand_params.x_offset = 0;
497
    rect.p.x = x;
498
    rect.q.x = x + width;
499
    for (py = y; py < y + height; py += loop_height) {
500
	int sx = sourcex;
501
	const byte *source_data = sdata + (py - y) * sraster;
502
	uint source_raster = sraster;
503
 
504
	if (block_height > y + height - py)
505
	    block_height = y + height - py;
506
	rect.p.y = py;
507
	if (expand_t) {
508
	    int rep_y = (phase_y + py) % rop_texture.rep_height;
509
 
510
	    loop_height = min(block_height, rop_texture.size.y - rep_y);
511
	    rect.q.y = py + loop_height;
512
	    expand_params.data[0] = texture_row;
513
	    gx_get_bits_copy(dev, 0, textures->rep_width, loop_height,
514
			     &expand_params, &no_expand_params,
515
			     textures->data + rep_y * textures->raster,
516
			     textures->raster);
517
	    /*
518
	     * Compensate for the addition of rep_y * raster
519
	     * in the subsidiary strip_copy_rop call.
520
	     */
521
	    rop_texture.data = texture_row - rep_y * rop_texture.raster;
522
	} else {
523
	    loop_height = block_height;
524
	    rect.q.y = py + block_height;
525
	}
526
	if (uses_d) {
527
	    bit_params.options = expand_options;
528
	    bit_params.data[0] = scan_line_base(&mdev, 0);
529
	    bit_params.x_offset = 0;
530
	    code = (*dev_proc(dev, get_bits_rectangle))
531
		(dev, &rect, &bit_params, NULL);
532
	    if (code < 0)
533
		break;
534
	}
535
	/* Convert the source and texture to standard format. */
536
	if (expand_s) {
537
	    expand_params.data[0] = source_row;
538
	    gx_get_bits_copy(dev, sx, width, loop_height, &expand_params,
539
			     &no_expand_params, source_data, sraster);
540
	    sx = 0;
541
	    source_data = source_row;
542
	    source_raster = source_row_raster;
543
	}
544
	code = (*dev_proc(&mdev, strip_copy_rop))
545
	    ((gx_device *)&mdev, source_data, sx, source_raster,
546
	     gx_no_bitmap_id, real_scolors, real_texture, real_tcolors,
547
	     0, 0, width, loop_height, phase_x + x, phase_y + py, lop);
548
	if (code < 0)
549
	    break;
550
	{
551
	    /*
552
	     * Convert the result back to the device's format.  We know
553
	     * the device is a memory device, so we can store the result
554
	     * directly into its scan lines.
555
	     */
556
	    int i;
557
	    const byte *unpacked = scan_line_base(&mdev, 0);
558
 
559
	    for (i = 0; i < loop_height; unpacked += mdev.raster, ++i) {
560
		byte *packed = scan_line_base((gx_device_memory *)dev, py + i);
561
 
562
		pack(dev, packed, x, unpacked, width, depth, rop_depth);
563
	    }
564
	}
565
    }
566
out:
567
    if (texture_row != 0 && texture_row != (byte *)texture_buffer)
568
	gs_free_object(mem, texture_row, "copy_rop texture_row");
569
    if (source_row != 0 && source_row != (byte *)source_buffer)
570
	gs_free_object(mem, source_row, "copy_rop source_row");
571
    if (row != 0 && row != (byte *)dest_buffer)
572
	gs_free_object(mem, row, "copy_rop row");
573
    (*dev_proc(&mdev, close_device)) ((gx_device *) & mdev);
574
    return code;
575
}
576
 
577
/* ------ Implementation of related functions ------ */
578
 
579
int
580
gx_default_copy_rop(gx_device * dev,
581
	     const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
582
		    const gx_color_index * scolors,
583
	     const gx_tile_bitmap * texture, const gx_color_index * tcolors,
584
		    int x, int y, int width, int height,
585
		    int phase_x, int phase_y, gs_logical_operation_t lop)
586
{
587
    const gx_strip_bitmap *textures;
588
    gx_strip_bitmap tiles;
589
 
590
    if (texture == 0)
591
	textures = 0;
592
    else {
593
	*(gx_tile_bitmap *) & tiles = *texture;
594
	tiles.rep_shift = tiles.shift = 0;
595
	textures = &tiles;
596
    }
597
    return (*dev_proc(dev, strip_copy_rop))
598
	(dev, sdata, sourcex, sraster, id, scolors, textures, tcolors,
599
	 x, y, width, height, phase_x, phase_y, lop);
600
}
601
 
602
int
603
gx_copy_rop_unaligned(gx_device * dev,
604
	     const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
605
		      const gx_color_index * scolors,
606
	     const gx_tile_bitmap * texture, const gx_color_index * tcolors,
607
		      int x, int y, int width, int height,
608
		      int phase_x, int phase_y, gs_logical_operation_t lop)
609
{
610
    const gx_strip_bitmap *textures;
611
    gx_strip_bitmap tiles;
612
 
613
    if (texture == 0)
614
	textures = 0;
615
    else {
616
	*(gx_tile_bitmap *) & tiles = *texture;
617
	tiles.rep_shift = tiles.shift = 0;
618
	textures = &tiles;
619
    }
620
    return gx_strip_copy_rop_unaligned
621
	(dev, sdata, sourcex, sraster, id, scolors, textures, tcolors,
622
	 x, y, width, height, phase_x, phase_y, lop);
623
}
624
 
625
int
626
gx_strip_copy_rop_unaligned(gx_device * dev,
627
	     const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
628
			    const gx_color_index * scolors,
629
	   const gx_strip_bitmap * textures, const gx_color_index * tcolors,
630
			    int x, int y, int width, int height,
631
		       int phase_x, int phase_y, gs_logical_operation_t lop)
632
{
633
    dev_proc_strip_copy_rop((*copy_rop)) = dev_proc(dev, strip_copy_rop);
634
    int depth = (scolors == 0 ? dev->color_info.depth : 1);
635
    int step = sraster & (align_bitmap_mod - 1);
636
 
637
    /* Adjust the origin. */
638
    if (sdata != 0) {
639
	uint offset =
640
	(uint) (sdata - (const byte *)0) & (align_bitmap_mod - 1);
641
 
642
	/* See copy_color above re the following statement. */
643
	if (depth == 24)
644
	    offset += (offset % 3) *
645
		(align_bitmap_mod * (3 - (align_bitmap_mod % 3)));
646
	sdata -= offset;
647
	sourcex += (offset << 3) / depth;
648
    }
649
    /* Adjust the raster. */
650
    if (!step || sdata == 0 ||
651
	(scolors != 0 && scolors[0] == scolors[1])
652
	) {			/* No adjustment needed. */
653
	return (*copy_rop) (dev, sdata, sourcex, sraster, id, scolors,
654
			    textures, tcolors, x, y, width, height,
655
			    phase_x, phase_y, lop);
656
    }
657
    /* Do the transfer one scan line at a time. */
658
    {
659
	const byte *p = sdata;
660
	int d = sourcex;
661
	int dstep = (step << 3) / depth;
662
	int code = 0;
663
	int i;
664
 
665
	for (i = 0; i < height && code >= 0;
666
	     ++i, p += sraster - step, d += dstep
667
	    )
668
	    code = (*copy_rop) (dev, p, d, sraster, gx_no_bitmap_id, scolors,
669
				textures, tcolors, x, y + i, width, 1,
670
				phase_x, phase_y, lop);
671
	return code;
672
    }
673
}
674
 
675
/* ---------------- Internal routines ---------------- */
676
 
677
/* Compute the effective RasterOp for the 1-bit case, */
678
/* taking transparency into account. */
679
gs_rop3_t
680
gs_transparent_rop(gs_logical_operation_t lop)
681
{
682
    gs_rop3_t rop = lop_rop(lop);
683
 
684
    /*
685
     * The algorithm for computing an effective RasterOp is presented,
686
     * albeit obfuscated, in the H-P PCL5 technical documentation.
687
     * Define So ("source opaque") and Po ("pattern opaque") as masks
688
     * that have 1-bits precisely where the source or pattern
689
     * respectively are not white (transparent).
690
     * One applies the original RasterOp to compute an intermediate
691
     * result R, and then computes the final result as
692
     * (R & M) | (D & ~M) where M depends on transparencies as follows:
693
     *      s_tr    p_tr    M
694
     *       0       0      1
695
     *       0       1      ~So | Po (? Po ?)
696
     *       1       0      So
697
     *       1       1      So & Po
698
     * The s_tr = 0, p_tr = 1 case seems wrong, but it's clearly
699
     * specified that way in the "PCL 5 Color Technical Reference
700
     * Manual."
701
     *
702
     * In the 1-bit case, So = ~S and Po = ~P, so we can apply the
703
     * above table directly.
704
     */
705
#define So rop3_not(rop3_S)
706
#define Po rop3_not(rop3_T)
707
#ifdef TRANSPARENCY_PER_H_P
708
/*
709
 * Believe it or not, MPo depends on S in this case even if the original
710
 * RasterOp didn't depend on S.
711
 */
712
#  define MPo (rop3_not(So) | Po)
713
#else
714
#  define MPo Po
715
#endif
716
    /*
717
     * If the operation doesn't use S or T, we must disregard the
718
     * corresponding transparency flag.
719
     */
720
#define source_transparent ((lop & lop_S_transparent) && rop3_uses_S(rop))
721
#define pattern_transparent ((lop & lop_T_transparent) && rop3_uses_T(rop))
722
    gs_rop3_t mask =
723
    (source_transparent ?
724
     (pattern_transparent ? So & Po : So) :
725
     (pattern_transparent ? MPo : rop3_1));
726
 
727
#undef MPo
728
    return (rop & mask) | (rop3_D & ~mask);
729
}