xref: /plan9/sys/src/cmd/gs/src/gdevdrop.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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
trace_copy_rop(const char * cname,gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)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
gx_default_strip_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)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
unpack_colors_to_standard(gx_device * dev,gx_color_index real_colors[2],const gx_color_index * colors,int depth)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
pack_cmyk_1bit_from_standard(gx_device * dev,byte * dest,int destx,const byte * src,int width,int depth,int src_depth)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
map_rgb_to_color_via_cmyk(gx_device * dev,const gx_color_value rgbcv[])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
pack_from_standard(gx_device * dev,byte * dest,int destx,const byte * src,int width,int depth,int src_depth)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
mem_default_strip_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)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
gx_default_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_tile_bitmap * texture,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)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
gx_copy_rop_unaligned(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_tile_bitmap * texture,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)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
gx_strip_copy_rop_unaligned(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)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
gs_transparent_rop(gs_logical_operation_t lop)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 }
730