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