1 /* Copyright (C) 2002 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: gxoprect.c,v 1.6 2005/06/20 08:59:23 igor Exp $ */
18 /* generic (very slow) overprint fill rectangle implementation */
19
20 #include "memory_.h"
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsutil.h" /* for gs_next_ids */
24 #include "gxdevice.h"
25 #include "gsdevice.h"
26 #include "gxgetbit.h"
27 #include "gxoprect.h"
28 #include "gsbitops.h"
29
30
31 /*
32 * Unpack a scanline for a depth < 8. In this case we know the depth is
33 * divisor of 8 and thus a power of 2, which implies that 8 / depth is
34 * also a power of 2.
35 */
36 private void
unpack_scanline_lt8(gx_color_index * destp,const byte * srcp,int src_offset,int width,int depth)37 unpack_scanline_lt8(
38 gx_color_index * destp,
39 const byte * srcp,
40 int src_offset,
41 int width,
42 int depth )
43 {
44 byte buff = 0;
45 int i = 0, shift = 8 - depth, p_per_byte = 8 / depth;
46
47 /* exit early if nothing to do */
48 if (width == 0)
49 return;
50
51 /* skip over src_offset */
52 if (src_offset >= p_per_byte) {
53 srcp += src_offset / p_per_byte;
54 src_offset &= (p_per_byte - 1);
55 }
56 if (src_offset > 0) {
57 buff = *srcp++ << (src_offset * depth);
58 i = src_offset;
59 width += src_offset;
60 }
61
62 /* process the interesting part of the scanline */
63 for (; i < width; i++, buff <<= depth) {
64 if ((i & (p_per_byte - 1)) == 0)
65 buff = *srcp++;
66 *destp++ = buff >> shift;
67 }
68 }
69
70 /*
71 * Pack a scanline for a depth of < 8. Note that data prior to dest_offset
72 * and any data beyond the width must be left undisturbed.
73 */
74 private void
pack_scanline_lt8(const gx_color_index * srcp,byte * destp,int dest_offset,int width,int depth)75 pack_scanline_lt8(
76 const gx_color_index * srcp,
77 byte * destp,
78 int dest_offset,
79 int width,
80 int depth )
81 {
82 byte buff = 0;
83 int i = 0, p_per_byte = 8 / depth;
84
85 /* exit early if nothing to do */
86 if (width == 0)
87 return;
88
89 /* skip over dest_offset */
90 if (dest_offset >= p_per_byte) {
91 destp += dest_offset / p_per_byte;
92 dest_offset &= (p_per_byte - 1);
93 }
94 if (dest_offset > 0) {
95 buff = *destp++ >> (8 - dest_offset * depth);
96 i = dest_offset;
97 width += dest_offset;
98 }
99
100 /* process the interesting part of the scanline */
101 for (; i < width; i++) {
102 buff = (buff << depth) | *srcp++;
103 if ((i & (p_per_byte - 1)) == p_per_byte - 1)
104 *destp++ = buff;
105 }
106 if ((i &= (p_per_byte - 1)) != 0) {
107 int shift = depth * (p_per_byte - i);
108 int mask = (1 << shift) - 1;
109
110 *destp = (*destp & mask) | (buff << shift);
111 }
112 }
113
114 /*
115 * Unpack a scanline for a depth >= 8. In this case, the depth must be
116 * a multiple of 8.
117 */
118 private void
unpack_scanline_ge8(gx_color_index * destp,const byte * srcp,int src_offset,int width,int depth)119 unpack_scanline_ge8(
120 gx_color_index * destp,
121 const byte * srcp,
122 int src_offset,
123 int width,
124 int depth )
125 {
126 gx_color_index buff = 0;
127 int i, j, bytes_per_p = depth >> 3;
128
129 /* skip over src_offset */
130 srcp += src_offset * bytes_per_p;
131
132 /* process the interesting part of the scanline */
133 width *= bytes_per_p;
134 for (i = 0, j = 0; i < width; i++) {
135 buff = (buff << 8) | *srcp++;
136 if (++j == bytes_per_p) {
137 *destp++ = buff;
138 buff = 0;
139 j = 0;
140 }
141 }
142 }
143
144 /*
145 * Pack a scanline for depth >= 8.
146 */
147 private void
pack_scanline_ge8(const gx_color_index * srcp,byte * destp,int dest_offset,int width,int depth)148 pack_scanline_ge8(
149 const gx_color_index * srcp,
150 byte * destp,
151 int dest_offset,
152 int width,
153 int depth )
154 {
155 gx_color_index buff = 0;
156 int i, j, bytes_per_p = depth >> 3;
157 int shift = depth - 8;
158
159 /* skip over dest_offset */
160 destp += dest_offset;
161
162 /* process the interesting part of the scanline */
163 width *= bytes_per_p;
164 for (i = 0, j = bytes_per_p - 1; i < width; i++, buff <<= 8) {
165 if (++j == bytes_per_p) {
166 buff = *srcp++;
167 j = 0;
168 }
169 *destp++ = buff >> shift;
170 }
171 }
172
173
174 /*
175 * Perform the fill rectangle operation for a non-separable color encoding
176 * that requires overprint support. This situation requires that colors be
177 * decoded, modified, and re-encoded. These steps must be performed per
178 * output pixel, so there is no hope of achieving good performance.
179 * Consequently, only minimal performance optimizations are applied below.
180 *
181 * The overprint device structure is known only in gsovr.c, and thus is not
182 * available here. The required information from the overprint device is,
183 * therefore, provided via explicit operands. The device operand points to
184 * the target of the overprint compositor device, not the compositor device
185 * itself. The drawn_comps bit array and the memory descriptor pointer are
186 * also provided explicitly as operands.
187 *
188 * Returns 0 on success, < 0 in the event of an error.
189 */
190 int
gx_overprint_generic_fill_rectangle(gx_device * tdev,gx_color_index drawn_comps,int x,int y,int w,int h,gx_color_index color,gs_memory_t * mem)191 gx_overprint_generic_fill_rectangle(
192 gx_device * tdev,
193 gx_color_index drawn_comps,
194 int x,
195 int y,
196 int w,
197 int h,
198 gx_color_index color,
199 gs_memory_t * mem )
200 {
201 gx_color_value src_cvals[GX_DEVICE_COLOR_MAX_COMPONENTS];
202 gx_color_index * pcolor_buff = 0;
203 byte * gb_buff = 0;
204 gs_get_bits_params_t gb_params;
205 gs_int_rect gb_rect;
206 int depth = tdev->color_info.depth;
207 int bit_x, start_x, end_x, raster, code;
208 void (*unpack_proc)( gx_color_index *,
209 const byte *,
210 int, int, int );
211 void (*pack_proc)( const gx_color_index *,
212 byte *,
213 int, int, int );
214
215 fit_fill(tdev, x, y, w, h);
216 bit_x = x * depth;
217 start_x = bit_x & ~(8 * align_bitmap_mod - 1);
218 end_x = bit_x + w * depth;
219
220 /* select the appropriate pack/unpack routines */
221 if (depth >= 8) {
222 unpack_proc = unpack_scanline_ge8;
223 pack_proc = pack_scanline_ge8;
224 } else {
225 unpack_proc = unpack_scanline_lt8;
226 pack_proc = pack_scanline_lt8;
227 }
228
229 /* decode the source color */
230 if ((code = dev_proc(tdev, decode_color)(tdev, color, src_cvals)) < 0)
231 return code;
232
233 /* allocate space for a scanline of color indices */
234 pcolor_buff = (gx_color_index *)
235 gs_alloc_bytes( mem,
236 w * arch_sizeof_color_index,
237 "overprint generic fill rectangle" );
238 if (pcolor_buff == 0)
239 return gs_note_error(gs_error_VMerror);
240
241 /* allocate a buffer for the returned data */
242 raster = bitmap_raster(end_x - start_x);
243 gb_buff = gs_alloc_bytes(mem, raster, "overprint generic fill rectangle");
244 if (gb_buff == 0) {
245 gs_free_object( mem,
246 pcolor_buff,
247 "overprint generic fill rectangle" );
248 return gs_note_error(gs_error_VMerror);
249 }
250
251 /*
252 * Initialize the get_bits parameters. The selection of options is
253 * based on the following logic:
254 *
255 * - Overprint is only defined with respect to components of the
256 * process color model, so the retrieved information must be kept
257 * in that color model. The gx_bitmap_format_t bitfield regards
258 * this as the native color space.
259 *
260 * - Overprinting and alpha compositing don't mix, so there is no
261 * reason to retrieve the alpha information.
262 *
263 * - Data should be returned in the depth of the process color
264 * model. Though this depth could be specified explicitly, there
265 * is little reason to do so.
266 *
267 * - Though overprint is much more easily implemented with planar
268 * data, there is no planar version of the copy_color method to
269 * send the modified data back to device. Hence, we must retrieve
270 * data in chunky form.
271 *
272 * - It is not possible to modify the raster data "in place", as
273 * doing so would bypass any other forwarding devices currently
274 * in the device "stack" (e.g.: a bounding box device). Hence,
275 * we must work with a copy of the data, which is passed to the
276 * copy_color method at the end of fill_rectangle operation.
277 *
278 * - Though we only require data for those planes that will not be
279 * modified, there is no benefit to returning less than the full
280 * data for each pixel if the color encoding is not separable.
281 * Since this routine will be used only for encodings that are
282 * not separable, we might as well ask for full information.
283 *
284 * - Though no particular alignment and offset are required, it is
285 * useful to make the copy operation as fast as possible. Ideally
286 * we would calculate an offset so that the data achieves optimal
287 * alignment. Alas, some of the devices work much more slowly if
288 * anything but GB_OFFSET_0 is specified, so that is what we use.
289 */
290 gb_params.options = GB_COLORS_NATIVE
291 | GB_ALPHA_NONE
292 | GB_DEPTH_ALL
293 | GB_PACKING_CHUNKY
294 | GB_RETURN_COPY
295 | GB_ALIGN_STANDARD
296 | GB_OFFSET_0
297 | GB_RASTER_STANDARD;
298 gb_params.x_offset = 0; /* for consistency */
299 gb_params.data[0] = gb_buff;
300 gb_params.raster = raster;
301
302 gb_rect.p.x = x;
303 gb_rect.q.x = x + w;
304
305 /* process each scanline separately */
306 while (h-- > 0 && code >= 0) {
307 gx_color_index * cp = pcolor_buff;
308 int i;
309
310 gb_rect.p.y = y++;
311 gb_rect.q.y = y;
312 code = dev_proc(tdev, get_bits_rectangle)( tdev,
313 &gb_rect,
314 &gb_params,
315 0 );
316 if (code < 0)
317 break;
318 unpack_proc(pcolor_buff, gb_buff, 0, w, depth);
319 for (i = 0; i < w; i++, cp++) {
320 gx_color_index comps;
321 int j;
322 gx_color_value dest_cvals[GX_DEVICE_COLOR_MAX_COMPONENTS];
323
324 if ((code = dev_proc(tdev, decode_color)(tdev, *cp, dest_cvals)) < 0)
325 break;
326 for (j = 0, comps = drawn_comps; comps != 0; ++j, comps >>= 1) {
327 if ((comps & 0x1) != 0)
328 dest_cvals[j] = src_cvals[j];
329 }
330 *cp = dev_proc(tdev, encode_color)(tdev, dest_cvals);
331 }
332 pack_proc(pcolor_buff, gb_buff, 0, w, depth);
333 code = dev_proc(tdev, copy_color)( tdev,
334 gb_buff,
335 0,
336 raster,
337 gs_no_bitmap_id,
338 x, y - 1, w, 1 );
339 }
340
341 gs_free_object( mem,
342 gb_buff,
343 "overprint generic fill rectangle" );
344 gs_free_object( mem,
345 pcolor_buff,
346 "overprint generic fill rectangle" );
347
348 return code;
349 }
350
351
352
353 /*
354 * Replication of 2 and 4 bit patterns to fill a mem_mono_chunk.
355 */
356 private mono_fill_chunk fill_pat_2[4] = {
357 mono_fill_make_pattern(0x00), mono_fill_make_pattern(0x55),
358 mono_fill_make_pattern(0xaa), mono_fill_make_pattern(0xff)
359 };
360
361 private mono_fill_chunk fill_pat_4[16] = {
362 mono_fill_make_pattern(0x00), mono_fill_make_pattern(0x11),
363 mono_fill_make_pattern(0x22), mono_fill_make_pattern(0x33),
364 mono_fill_make_pattern(0x44), mono_fill_make_pattern(0x55),
365 mono_fill_make_pattern(0x66), mono_fill_make_pattern(0x77),
366 mono_fill_make_pattern(0x88), mono_fill_make_pattern(0x99),
367 mono_fill_make_pattern(0xaa), mono_fill_make_pattern(0xbb),
368 mono_fill_make_pattern(0xcc), mono_fill_make_pattern(0xdd),
369 mono_fill_make_pattern(0xee), mono_fill_make_pattern(0xff)
370 };
371
372 /*
373 * Replicate a color or mask as required to fill a mem_mono_fill_chunk.
374 * This is possible if (8 * sizeof(mono_fill_chunk)) % depth == 0.
375 * Since sizeof(mono_fill_chunk) is a power of 2, this will be the case
376 * if depth is a power of 2 and depth <= 8 * sizeof(mono_fill_chunk).
377 */
378 private mono_fill_chunk
replicate_color(int depth,mono_fill_chunk color)379 replicate_color(int depth, mono_fill_chunk color)
380 {
381 switch (depth) {
382
383 case 1:
384 color = (mono_fill_chunk)(-(int)color); break;
385
386 case 2:
387 color = fill_pat_2[color]; break;
388
389 case 4:
390 color = fill_pat_4[color]; break;
391
392 case 8:
393 color= mono_fill_make_pattern(color); break;
394
395 #if mono_fill_chunk_bytes > 2
396 case 16:
397 color = (color << 16) | color;
398 /* fall through */
399 #endif
400 #if mono_fill_chunk_bytes > 4
401 case 32:
402 color = (color << 32) | color;
403 break;
404 #endif
405 }
406
407 return color;
408 }
409
410
411 /*
412 * Perform the fill rectangle operation for a separable color encoding
413 * that requires overprint support.
414 *
415 * This is handled via two separate cases. If
416 *
417 * (8 * sizeof(mono_fill_chunk)) % tdev->color_info.depth = 0,
418 *
419 * then is possible to work via the masked analog of the bits_fill_rectangle
420 * procedure, bits_fill_rectangle_masked. This requires that both the
421 * color and component mask be replicated sufficiently to fill the
422 * mono_fill_chunk. The somewhat elaborate set-up aside, the resulting
423 * algorithm is about as efficient as can be achieved when using
424 * get_bits_rectangle. More efficient algorithms require overprint to be
425 * implemented in the target device itself.
426 *
427 * If the condition is not satisfied, a simple byte-wise algorithm is
428 * used. This requires minimal setup but is not efficient, as it works in
429 * units that are too small. More efficient methods are possible in this
430 * case, but the required setup for a general depth is excessive (even
431 * with the restriction that depth % 8 = 0). Hence, efficiency for these
432 * cases is better addressed by direct implementation of overprint for
433 * memory devices.
434 *
435 * For both cases, the color and retain_mask values passed to this
436 * procedure are expected to be already swapped as required for a byte-
437 * oriented bitmap. This consideration affects only little-endian
438 * machines. For those machines, if depth > 9 the color passed to these
439 * two procedures will not be the same as that passed to
440 * gx_overprint_generic_fill_rectangle.
441 *
442 * Returns 0 on success, < 0 in the event of an error.
443 */
444 int
gx_overprint_sep_fill_rectangle_1(gx_device * tdev,gx_color_index retain_mask,int x,int y,int w,int h,gx_color_index color,gs_memory_t * mem)445 gx_overprint_sep_fill_rectangle_1(
446 gx_device * tdev,
447 gx_color_index retain_mask, /* already swapped */
448 int x,
449 int y,
450 int w,
451 int h,
452 gx_color_index color, /* already swapped */
453 gs_memory_t * mem )
454 {
455 byte * gb_buff = 0;
456 gs_get_bits_params_t gb_params;
457 gs_int_rect gb_rect;
458 int code = 0, bit_w, depth = tdev->color_info.depth;
459 int raster;
460 mono_fill_chunk rep_color, rep_mask;
461
462 fit_fill(tdev, x, y, w, h);
463 bit_w = w * depth;
464
465 /* set up replicated color and retain mask */
466 if (depth < 8 * sizeof(mono_fill_chunk)) {
467 rep_color = replicate_color(depth, (mono_fill_chunk)color);
468 rep_mask = replicate_color(depth, (mono_fill_chunk)retain_mask);
469 } else {
470 rep_color = (mono_fill_chunk)color;
471 rep_mask = (mono_fill_chunk)retain_mask;
472 }
473
474 /* allocate a buffer for the returned data */
475 raster = bitmap_raster(w * depth);
476 gb_buff = gs_alloc_bytes(mem, raster, "overprint sep fill rectangle 1");
477 if (gb_buff == 0)
478 return gs_note_error(gs_error_VMerror);
479
480 /*
481 * Initialize the get_bits parameters. The selection of options is
482 * the same as that for gx_overprint_generic_fill_rectangle (above).
483 */
484 gb_params.options = GB_COLORS_NATIVE
485 | GB_ALPHA_NONE
486 | GB_DEPTH_ALL
487 | GB_PACKING_CHUNKY
488 | GB_RETURN_COPY
489 | GB_ALIGN_STANDARD
490 | GB_OFFSET_0
491 | GB_RASTER_STANDARD;
492 gb_params.x_offset = 0; /* for consistency */
493 gb_params.data[0] = gb_buff;
494 gb_params.raster = raster;
495
496 gb_rect.p.x = x;
497 gb_rect.q.x = x + w;
498
499 /* process each scanline separately */
500 while (h-- > 0 && code >= 0) {
501 gb_rect.p.y = y++;
502 gb_rect.q.y = y;
503 code = dev_proc(tdev, get_bits_rectangle)( tdev,
504 &gb_rect,
505 &gb_params,
506 0 );
507 if (code < 0)
508 break;
509 bits_fill_rectangle_masked( gb_buff,
510 0,
511 raster,
512 rep_color,
513 rep_mask,
514 bit_w,
515 1 );
516 code = dev_proc(tdev, copy_color)( tdev,
517 gb_buff,
518 0,
519 raster,
520 gs_no_bitmap_id,
521 x, y - 1, w, 1 );
522 }
523
524 gs_free_object( mem,
525 gb_buff,
526 "overprint generic fill rectangle" );
527
528 return code;
529 }
530
531
532 int
gx_overprint_sep_fill_rectangle_2(gx_device * tdev,gx_color_index retain_mask,int x,int y,int w,int h,gx_color_index color,gs_memory_t * mem)533 gx_overprint_sep_fill_rectangle_2(
534 gx_device * tdev,
535 gx_color_index retain_mask, /* already swapped */
536 int x,
537 int y,
538 int w,
539 int h,
540 gx_color_index color, /* already swapped */
541 gs_memory_t * mem )
542 {
543 byte * gb_buff = 0;
544 gs_get_bits_params_t gb_params;
545 gs_int_rect gb_rect;
546 int code = 0, byte_w, raster;
547 int byte_depth = tdev->color_info.depth >> 3;
548 byte * pcolor;
549 byte * pmask;
550
551 fit_fill(tdev, x, y, w, h);
552 byte_w = w * byte_depth;
553
554 /* set up color and retain mask pointers */
555 pcolor = (byte *)&color;
556 pmask = (byte *)&retain_mask;
557 #if arch_is_big_endian
558 pcolor += arch_sizeof_color_index - byte_depth;
559 pmask += arch_sizeof_color_index - byte_depth;
560 #endif
561
562 /* allocate a buffer for the returned data */
563 raster = bitmap_raster(w * (byte_depth << 3));
564 gb_buff = gs_alloc_bytes(mem, raster, "overprint sep fill rectangle 2");
565 if (gb_buff == 0)
566 return gs_note_error(gs_error_VMerror);
567
568 /*
569 * Initialize the get_bits parameters. The selection of options is
570 * the same as that for gx_overprint_generic_fill_rectangle (above).
571 */
572 gb_params.options = GB_COLORS_NATIVE
573 | GB_ALPHA_NONE
574 | GB_DEPTH_ALL
575 | GB_PACKING_CHUNKY
576 | GB_RETURN_COPY
577 | GB_ALIGN_STANDARD
578 | GB_OFFSET_0
579 | GB_RASTER_STANDARD;
580 gb_params.x_offset = 0; /* for consistency */
581 gb_params.data[0] = gb_buff;
582 gb_params.raster = raster;
583
584 gb_rect.p.x = x;
585 gb_rect.q.x = x + w;
586
587 /* process each scanline separately */
588 while (h-- > 0 && code >= 0) {
589 int i, j;
590 byte * cp = gb_buff;
591
592 gb_rect.p.y = y++;
593 gb_rect.q.y = y;
594 code = dev_proc(tdev, get_bits_rectangle)( tdev,
595 &gb_rect,
596 &gb_params,
597 0 );
598 if (code < 0)
599 break;
600 for (i = 0, j = 0; i < byte_w; i++, cp++) {
601 *cp = (*cp & pmask[j]) | pcolor[j];
602 if (++j == byte_depth)
603 j = 0;
604 }
605 code = dev_proc(tdev, copy_color)( tdev,
606 gb_buff,
607 0,
608 raster,
609 gs_no_bitmap_id,
610 x, y - 1, w, 1 );
611 }
612
613 gs_free_object( mem,
614 gb_buff,
615 "overprint generic fill rectangle" );
616
617 return code;
618 }
619
620