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