/src/ghostpdl/base/gxcht.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 | | /* Color halftone rendering for Ghostscript imaging library */ |
18 | | #include "memory_.h" |
19 | | #include "gx.h" |
20 | | #include "gserrors.h" |
21 | | #include "gsutil.h" /* for id generation */ |
22 | | #include "gxarith.h" |
23 | | #include "gxfixed.h" |
24 | | #include "gxmatrix.h" |
25 | | #include "gxdevice.h" |
26 | | #include "gxcmap.h" |
27 | | #include "gxdcolor.h" |
28 | | #include "gxgstate.h" |
29 | | #include "gzht.h" |
30 | | #include "gsserial.h" |
31 | | #include "gxdevsop.h" |
32 | | |
33 | | /* Define whether to force use of the slow code, for testing. */ |
34 | | #define USE_SLOW_CODE 0 |
35 | | |
36 | | /* Define the size of the tile buffer allocated on the stack. */ |
37 | 410M | #define tile_longs_LARGE 256 |
38 | | #define tile_longs_SMALL 64 |
39 | | #if ARCH_SMALL_MEMORY |
40 | | # define tile_longs_allocated tile_longs_SMALL |
41 | | # define tile_longs tile_longs_SMALL |
42 | | #else |
43 | | # define tile_longs_allocated tile_longs_LARGE |
44 | | # ifdef DEBUG |
45 | | # define tile_longs\ |
46 | | (gs_debug_c('.') ? tile_longs_SMALL : tile_longs_LARGE) |
47 | | # else |
48 | 410M | # define tile_longs tile_longs_LARGE |
49 | | # endif |
50 | | #endif |
51 | | |
52 | | /* Define the colored halftone device color type. */ |
53 | | gs_private_st_ptrs1(st_dc_ht_colored, gx_device_color, "dc_ht_colored", |
54 | | dc_ht_colored_enum_ptrs, dc_ht_colored_reloc_ptrs, colors.colored.c_ht); |
55 | | static dev_color_proc_save_dc(gx_dc_ht_colored_save_dc); |
56 | | static dev_color_proc_get_dev_halftone(gx_dc_ht_colored_get_dev_halftone); |
57 | | static dev_color_proc_load(gx_dc_ht_colored_load); |
58 | | static dev_color_proc_fill_rectangle(gx_dc_ht_colored_fill_rectangle); |
59 | | static dev_color_proc_equal(gx_dc_ht_colored_equal); |
60 | | static dev_color_proc_write(gx_dc_ht_colored_write); |
61 | | static dev_color_proc_read(gx_dc_ht_colored_read); |
62 | | const gx_device_color_type_t gx_dc_type_data_ht_colored = { |
63 | | &st_dc_ht_colored, |
64 | | gx_dc_ht_colored_save_dc, gx_dc_ht_colored_get_dev_halftone, |
65 | | gx_dc_ht_get_phase, |
66 | | gx_dc_ht_colored_load, gx_dc_ht_colored_fill_rectangle, |
67 | | gx_dc_default_fill_masked, gx_dc_ht_colored_equal, |
68 | | gx_dc_ht_colored_write, gx_dc_ht_colored_read, |
69 | | gx_dc_ht_colored_get_nonzero_comps |
70 | | }; |
71 | | #undef gx_dc_type_ht_colored |
72 | | const gx_device_color_type_t *const gx_dc_type_ht_colored = |
73 | | &gx_dc_type_data_ht_colored; |
74 | 8.09M | #define gx_dc_type_ht_colored (&gx_dc_type_data_ht_colored) |
75 | | |
76 | | /* save information about the operand device color */ |
77 | | static void |
78 | | gx_dc_ht_colored_save_dc(const gx_device_color * pdevc, |
79 | | gx_device_color_saved * psdc) |
80 | 4.14M | { |
81 | 4.14M | psdc->type = pdevc->type; |
82 | 4.14M | memcpy( psdc->colors.colored.c_base, |
83 | 4.14M | pdevc->colors.colored.c_base, |
84 | 4.14M | sizeof(psdc->colors.colored.c_base) ); |
85 | 4.14M | memcpy( psdc->colors.colored.c_level, |
86 | 4.14M | pdevc->colors.colored.c_level, |
87 | 4.14M | sizeof(psdc->colors.colored.c_base) ); |
88 | 4.14M | psdc->phase = pdevc->phase; |
89 | 4.14M | } |
90 | | |
91 | | /* get the halftone used for the operand device color */ |
92 | | static const gx_device_halftone * |
93 | | gx_dc_ht_colored_get_dev_halftone(const gx_device_color * pdevc) |
94 | 38.6M | { |
95 | 38.6M | return pdevc->colors.colored.c_ht; |
96 | 38.6M | } |
97 | | |
98 | | /* Compare two colored halftones for equality. */ |
99 | | static bool |
100 | | gx_dc_ht_colored_equal(const gx_device_color * pdevc1, |
101 | | const gx_device_color * pdevc2) |
102 | 114M | { |
103 | 114M | uint num_comp = pdevc1->colors.colored.num_components; |
104 | | |
105 | 114M | if (pdevc2->type != pdevc1->type || |
106 | 114M | pdevc1->colors.colored.c_ht != pdevc2->colors.colored.c_ht || |
107 | 114M | pdevc1->phase.x != pdevc2->phase.x || |
108 | 114M | pdevc1->phase.y != pdevc2->phase.y || |
109 | 114M | num_comp != pdevc2->colors.colored.num_components |
110 | 114M | ) |
111 | 8.49M | return false; |
112 | 106M | return |
113 | 106M | !memcmp(pdevc1->colors.colored.c_base, |
114 | 106M | pdevc2->colors.colored.c_base, |
115 | 106M | num_comp * sizeof(pdevc1->colors.colored.c_base[0])) && |
116 | 106M | !memcmp(pdevc1->colors.colored.c_level, |
117 | 104M | pdevc2->colors.colored.c_level, |
118 | 104M | num_comp * sizeof(pdevc1->colors.colored.c_level[0])); |
119 | 114M | } |
120 | | |
121 | | /* |
122 | | * Flags to indicate the pieces of a colored halftone that are included |
123 | | * in its string representation. The first byte of the string holds this |
124 | | * set of flags. |
125 | | * |
126 | | * The case alpha = gx_max_color_value is by far the most common, so |
127 | | * special treatment is provided for this case. |
128 | | * |
129 | | * The halftone is never transmitted as part of a device color, so there |
130 | | * is no flag for it. |
131 | | */ |
132 | | enum { |
133 | | dc_ht_colored_has_base = 0x01, |
134 | | dc_ht_colored_has_level = 0x02, |
135 | | dc_ht_colored_has_phase_x = 0x04, |
136 | | dc_ht_colored_has_phase_y = 0x08, |
137 | | }; |
138 | | |
139 | | /* |
140 | | * Serialize a device color that uses a traditional colored halftone. |
141 | | * |
142 | | * The number of components of a device color must match that of the |
143 | | * process color model, so it is not transmitted. |
144 | | * |
145 | | * The most common situation in which this routine is used is for 1-bit |
146 | | * per component devices. In that case, base[i] will always be 0 or 1, |
147 | | * and thus may be fit in a single bit. |
148 | | * |
149 | | * In many situations, one or more of the color component intensity |
150 | | * levels will be 0. The plane_mask field identifies those components |
151 | | * where this is not the case. By tansmitting the plane_mask, only those |
152 | | * components with non-zero levels need be transmitted. |
153 | | * |
154 | | * The case alpha = gx_max_color_value is by far the most common, so |
155 | | * special treatment is provided for this case. |
156 | | * |
157 | | * |
158 | | * Operands: |
159 | | * |
160 | | * pdevc pointer to device color to be serialized |
161 | | * |
162 | | * psdc pointer ot saved version of last serialized color (for |
163 | | * this band) |
164 | | * |
165 | | * dev pointer to the current device, used to retrieve process |
166 | | * color model information |
167 | | * |
168 | | * pdata pointer to buffer in which to write the data |
169 | | * |
170 | | * psize pointer to a location that, on entry, contains the size of |
171 | | * the buffer pointed to by pdata; on return, the size of |
172 | | * the data required or actually used will be written here. |
173 | | * |
174 | | * Returns: |
175 | | * 1, with *psize set to 0, if *psdc and *pdevc represent the same color |
176 | | * |
177 | | * 0, with *psize set to the amount of data written, if everything OK |
178 | | * |
179 | | * gs_error_rangecheck, with *psize set to the size of buffer required, |
180 | | * if *psize was not large enough |
181 | | * |
182 | | * < 0, != gs_error_rangecheck, in the event of some other error |
183 | | * (currently none); in this case *psize is not changed. |
184 | | */ |
185 | | static int |
186 | | gx_dc_ht_colored_write( |
187 | | const gx_device_color * pdevc, |
188 | | const gx_device_color_saved * psdc0, |
189 | | const gx_device * dev, |
190 | | int64_t offset, |
191 | | byte * pdata, |
192 | | uint * psize ) |
193 | 42.7M | { |
194 | 42.7M | int req_size = 1; |
195 | 42.7M | int flag_bits = 0; |
196 | 42.7M | int num_comps = dev->color_info.num_components; |
197 | 42.7M | int depth = dev->color_info.depth; |
198 | 42.7M | gx_color_index plane_mask = pdevc->colors.colored.plane_mask; |
199 | 42.7M | const gx_device_color_saved * psdc = psdc0; |
200 | 42.7M | byte * pdata0 = pdata; |
201 | | |
202 | 42.7M | if (offset != 0) |
203 | 0 | return_error(gs_error_unregistered); /* Not implemented yet. */ |
204 | | |
205 | | /* sanity check */ |
206 | 42.7M | if (pdevc->colors.colored.num_components != num_comps) |
207 | 0 | return_error(gs_error_unregistered); /* Must not happen. */ |
208 | | |
209 | | /* check if saved color is of the same type */ |
210 | 42.7M | if (psdc != 0 && psdc->type != pdevc->type) |
211 | 553k | psdc = 0; |
212 | | |
213 | | /* calculate the size required */ |
214 | 42.7M | if ( psdc == 0 || |
215 | 42.7M | memcmp( pdevc->colors.colored.c_base, |
216 | 42.2M | psdc->colors.colored.c_base, |
217 | 42.2M | num_comps * sizeof(pdevc->colors.colored.c_base[0]) ) != 0 ) { |
218 | 669k | flag_bits |= dc_ht_colored_has_base; |
219 | 669k | if (num_comps == depth) /* 1 bit / component */ |
220 | 159k | req_size += (num_comps + 7) >> 3; |
221 | 509k | else |
222 | 509k | req_size += num_comps * sizeof(pdevc->colors.colored.c_base[0]); |
223 | 669k | } |
224 | | |
225 | 42.7M | plane_mask = pdevc->colors.colored.plane_mask; |
226 | 42.7M | if ( psdc == NULL || |
227 | 42.7M | memcmp( pdevc->colors.colored.c_level, |
228 | 42.2M | psdc->colors.colored.c_level, |
229 | 42.2M | num_comps * sizeof(pdevc->colors.colored.c_level[0]) ) != 0 ) { |
230 | 8.28M | gx_color_index comp_bit; |
231 | 8.28M | int i; |
232 | 8.28M | uint tmp_mask; |
233 | | |
234 | 8.28M | flag_bits |= dc_ht_colored_has_level; |
235 | 8.28M | if (num_comps > 8 * sizeof(uint)) { |
236 | 0 | tmp_mask = (uint)plane_mask; |
237 | 0 | req_size += enc_u_sizew(tmp_mask); |
238 | 0 | tmp_mask = (uint)((plane_mask >> (8*sizeof(uint)-1)) >> 1); |
239 | 0 | req_size += enc_u_sizew(tmp_mask); |
240 | 8.28M | } else { |
241 | 8.28M | tmp_mask = (uint)plane_mask; |
242 | 8.28M | req_size += enc_u_sizew(tmp_mask); |
243 | 8.28M | } |
244 | 35.0M | for (i = 0, comp_bit = 0x1; i < num_comps; i++, comp_bit <<= 1) { |
245 | 26.7M | if ((plane_mask & comp_bit) != 0) |
246 | 22.5M | req_size += enc_u_sizew(pdevc->colors.colored.c_level[i]); |
247 | 26.7M | } |
248 | 8.28M | } |
249 | | |
250 | 42.7M | if (psdc == NULL || psdc->phase.x != pdevc->phase.x) |
251 | 553k | flag_bits |= dc_ht_colored_has_phase_x, req_size += enc_u_sizew(pdevc->phase.x); |
252 | 42.7M | if (psdc == NULL || psdc->phase.y != pdevc->phase.y) |
253 | 553k | flag_bits |= dc_ht_colored_has_phase_y, req_size += enc_u_sizew(pdevc->phase.y); |
254 | | |
255 | | /* see if there is anything to do */ |
256 | 42.7M | if (flag_bits == 0) { |
257 | 34.5M | *psize = 0; |
258 | 34.5M | return 1; |
259 | 34.5M | } |
260 | | |
261 | | /* see if enough space is available */ |
262 | 8.28M | if (req_size > *psize) { |
263 | 4.14M | *psize = req_size; |
264 | 4.14M | return_error(gs_error_rangecheck); |
265 | 4.14M | } |
266 | | |
267 | | /* write out the flag byte */ |
268 | 4.14M | *pdata++ = (byte)flag_bits; |
269 | | |
270 | | /* write out such other parts of the device color as required */ |
271 | 4.14M | if ((flag_bits & dc_ht_colored_has_base) != 0) { |
272 | 334k | if (num_comps == depth) { |
273 | 79.7k | gx_color_index base_mask = 0; |
274 | 79.7k | int num_bytes = (num_comps + 7) >> 3; |
275 | 79.7k | int i; |
276 | | |
277 | 398k | for (i = 0; i < num_comps; i++) { |
278 | 318k | if (pdevc->colors.colored.c_base[i] != 0) |
279 | 17.6k | base_mask |= (gx_color_index)1 << i; |
280 | 318k | } |
281 | 159k | for (i = 0; i < num_bytes; i++, base_mask >>= 8) |
282 | 79.7k | *pdata++ = (byte)base_mask; |
283 | 254k | } else { |
284 | 254k | memcpy( pdata, |
285 | 254k | pdevc->colors.colored.c_base, |
286 | 254k | num_comps * sizeof(pdevc->colors.colored.c_base[0]) ); |
287 | 254k | pdata += num_comps * sizeof(pdevc->colors.colored.c_base[0]); |
288 | 254k | } |
289 | 334k | } |
290 | | |
291 | 4.14M | if ((flag_bits & dc_ht_colored_has_level) != 0) { |
292 | 4.14M | gx_color_index code_bit; |
293 | 4.14M | int i; |
294 | 4.14M | uint tmp_mask; |
295 | | |
296 | 4.14M | if (num_comps > 8 * sizeof(uint)) { |
297 | 0 | tmp_mask = (uint)plane_mask; |
298 | 0 | enc_u_putw(tmp_mask, pdata); |
299 | 0 | tmp_mask = (uint)((plane_mask >> (8*sizeof(uint)-1))>>1); |
300 | 0 | enc_u_putw(tmp_mask, pdata); |
301 | 4.14M | } else { |
302 | 4.14M | tmp_mask = (uint)plane_mask; |
303 | 4.14M | enc_u_putw(tmp_mask, pdata); |
304 | 4.14M | } |
305 | 17.5M | for (i = 0, code_bit = 0x1; i < num_comps; i++, code_bit <<= 1) { |
306 | 13.3M | if ((plane_mask & code_bit) != 0) |
307 | 13.3M | enc_u_putw(pdevc->colors.colored.c_level[i], pdata); |
308 | 13.3M | } |
309 | 4.14M | } |
310 | | |
311 | 4.14M | if ((flag_bits & dc_ht_colored_has_phase_x) != 0) { |
312 | 276k | enc_u_putw(pdevc->phase.x, pdata); |
313 | 276k | } |
314 | 4.14M | if ((flag_bits & dc_ht_colored_has_phase_x) != 0) { |
315 | 276k | enc_u_putw(pdevc->phase.y, pdata); |
316 | 276k | } |
317 | | |
318 | 4.14M | *psize = pdata - pdata0; |
319 | 4.14M | return 0; |
320 | 8.28M | } |
321 | | |
322 | | /* |
323 | | * Reconstruct a device color from its serial representation. |
324 | | * |
325 | | * Operands: |
326 | | * |
327 | | * pdevc pointer to the location in which to write the |
328 | | * reconstructed device color |
329 | | * |
330 | | * pgs pointer to the current gs_gstate (to access the |
331 | | * current halftone) |
332 | | * |
333 | | * prior_devc pointer to the current device color (this is provided |
334 | | * separately because the device color is not part of the |
335 | | * gs_gstate) |
336 | | * |
337 | | * dev pointer to the current device, used to retrieve process |
338 | | * color model information |
339 | | * |
340 | | * pdata pointer to the buffer to be read |
341 | | * |
342 | | * size size of the buffer to be read; this should be large |
343 | | * enough to hold the entire color description |
344 | | * |
345 | | * mem pointer to the memory to be used for allocations |
346 | | * (ignored here) |
347 | | * |
348 | | * Returns: |
349 | | * |
350 | | * # of bytes read if everthing OK, < 0 in the event of an error |
351 | | */ |
352 | | static int |
353 | | gx_dc_ht_colored_read( |
354 | | gx_device_color * pdevc, |
355 | | const gs_gstate * pgs, |
356 | | const gx_device_color * prior_devc, |
357 | | const gx_device * dev, |
358 | | int64_t offset, |
359 | | const byte * pdata, |
360 | | uint size, |
361 | | gs_memory_t * mem, /* ignored */ |
362 | | int x0, |
363 | | int y0) |
364 | 4.04M | { |
365 | 4.04M | gx_device_color devc; |
366 | 4.04M | int num_comps = dev->color_info.num_components; |
367 | 4.04M | int depth = dev->color_info.depth; |
368 | 4.04M | const byte * pdata0 = pdata; |
369 | 4.04M | int flag_bits; |
370 | | |
371 | 4.04M | if (offset != 0) |
372 | 0 | return_error(gs_error_unregistered); /* Not implemented yet. */ |
373 | | |
374 | | /* if prior information is available, use it */ |
375 | 4.04M | if (prior_devc != 0 && prior_devc->type == gx_dc_type_ht_colored) |
376 | 3.85M | devc = *prior_devc; |
377 | 191k | else |
378 | 191k | memset(&devc, 0, sizeof(devc)); /* clear pointers */ |
379 | 4.04M | devc.type = gx_dc_type_ht_colored; |
380 | | |
381 | | /* the number of components is determined by the color model */ |
382 | 4.04M | devc.colors.colored.num_components = num_comps; |
383 | 4.04M | devc.colors.colored.c_ht = pgs->dev_ht[HT_OBJTYPE_DEFAULT]; |
384 | | |
385 | | /* |
386 | | * Verify that we have at least the flag bits. For performance |
387 | | * reasons, the routines that convert serialized representations |
388 | | * of integers do not check buffer size. Hence, in many cases below, |
389 | | * only a very rough check is made to verify that we have not |
390 | | * exhausted the buffer. This should not cause a problem in |
391 | | * practice. |
392 | | */ |
393 | 4.04M | if (size == 0) |
394 | 0 | return_error(gs_error_rangecheck); |
395 | 4.04M | size--; |
396 | 4.04M | flag_bits = *pdata++; |
397 | | |
398 | | /* read the other components provided */ |
399 | 4.04M | if ((flag_bits & dc_ht_colored_has_base) != 0) { |
400 | 298k | if (depth == num_comps) { |
401 | 70.5k | gx_color_index base_mask = 0; |
402 | 70.5k | int num_bytes = (num_comps + 7) >> 3; |
403 | 70.5k | int i, shift = 0; |
404 | | |
405 | 70.5k | if (size < num_bytes) |
406 | 0 | return_error(gs_error_rangecheck); |
407 | 70.5k | size -= num_bytes; |
408 | 141k | for (i = 0; i < num_bytes; i++, shift += 8) |
409 | 70.5k | base_mask |= (gx_color_index)(*pdata++) << shift; |
410 | 352k | for (i = 0; i < num_comps; i++, base_mask >>= 1) |
411 | 282k | devc.colors.colored.c_base[i] = base_mask & 0x1; |
412 | 228k | } else { |
413 | 228k | if (size < num_comps) |
414 | 0 | return_error(gs_error_rangecheck); |
415 | 228k | size -= num_comps; |
416 | 228k | memcpy(devc.colors.colored.c_base, pdata, num_comps); |
417 | 228k | pdata += num_comps; |
418 | 228k | } |
419 | 298k | } |
420 | | |
421 | 4.04M | if ((flag_bits & dc_ht_colored_has_level) != 0) { |
422 | 4.04M | const byte * pdata_start = pdata; |
423 | 4.04M | gx_color_index plane_mask; |
424 | 4.04M | uint tmp_mask; |
425 | 4.04M | int i; |
426 | | |
427 | 4.04M | if (size < 1) |
428 | 0 | return_error(gs_error_rangecheck); |
429 | | |
430 | 4.04M | if (num_comps > 8 * sizeof(uint)) { |
431 | 0 | enc_u_getw(tmp_mask, pdata); |
432 | 0 | plane_mask = (gx_color_index)tmp_mask; |
433 | 0 | enc_u_getw(tmp_mask, pdata); |
434 | 0 | plane_mask = (((gx_color_index)tmp_mask)<<(8 * sizeof(uint)-1))<<1; |
435 | 4.04M | } else { |
436 | 4.04M | enc_u_getw(tmp_mask, pdata); |
437 | 4.04M | plane_mask = (gx_color_index)tmp_mask; |
438 | 4.04M | } |
439 | 4.04M | devc.colors.colored.plane_mask = plane_mask; |
440 | 17.1M | for (i = 0; i < num_comps; i++, plane_mask >>= 1) { |
441 | 13.0M | if ((plane_mask & 0x1) != 0) { |
442 | 11.0M | if (size - (pdata - pdata_start) < 1) |
443 | 0 | return_error(gs_error_rangecheck); |
444 | 11.0M | enc_u_getw(devc.colors.colored.c_level[i], pdata); |
445 | 11.0M | } else |
446 | 1.99M | devc.colors.colored.c_level[i] = 0; |
447 | 13.0M | } |
448 | 4.04M | size -= pdata - pdata_start; |
449 | 4.04M | } |
450 | | |
451 | 4.04M | if ((flag_bits & dc_ht_colored_has_phase_x) != 0) { |
452 | 244k | enc_u_getw(devc.phase.x, pdata); |
453 | 244k | devc.phase.x += x0; |
454 | 244k | } |
455 | 4.04M | if ((flag_bits & dc_ht_colored_has_phase_y) != 0) { |
456 | 244k | enc_u_getw(devc.phase.y, pdata); |
457 | 244k | devc.phase.y += y0; |
458 | 244k | } |
459 | | |
460 | | /* everything looks OK */ |
461 | 4.04M | *pdevc = devc; |
462 | 4.04M | return pdata - pdata0; |
463 | 4.04M | } |
464 | | |
465 | | /* |
466 | | * Get the nonzero components of a coloredhalftone. This is used to |
467 | | * distinguish components that are given zero intensity due to halftoning |
468 | | * from those for which the original color intensity was in fact zero. |
469 | | * |
470 | | * An original component intensity of zero will yield a c_base value of |
471 | | * 0 and a c_level of 0. The plane_mask field already contains the latter |
472 | | * information, so we need only add those components for which c_base is |
473 | | * non-zero. |
474 | | */ |
475 | | int |
476 | | gx_dc_ht_colored_get_nonzero_comps( |
477 | | const gx_device_color * pdevc, |
478 | | const gx_device * dev_ignored, |
479 | | gx_color_index * pcomp_bits ) |
480 | 0 | { |
481 | 0 | int i, ncomps = pdevc->colors.colored.num_components; |
482 | 0 | gx_color_index comp_bits = pdevc->colors.colored.plane_mask; |
483 | |
|
484 | 0 | for (i = 0; i < ncomps; i++) { |
485 | 0 | if (pdevc->colors.colored.c_base[i] != 0) |
486 | 0 | comp_bits |= ((gx_color_index)1) << i; |
487 | 0 | } |
488 | 0 | *pcomp_bits = comp_bits; |
489 | |
|
490 | 0 | return 0; |
491 | 0 | } |
492 | | |
493 | | /* |
494 | | * Define an abbreviation for a heavily used value: the maximum number of |
495 | | * of device colorants (device colors). |
496 | | */ |
497 | | #define MAX_DCC GX_DEVICE_COLOR_MAX_COMPONENTS |
498 | | /* |
499 | | * Define a size for the "colors" array. For less than 5 colors, there are |
500 | | * 2**n values stored (for a maximum of 16 values). For 5 or more colors, we |
501 | | * only store 2 values per color so the array size can be 2 * MAX_DCC. Use which |
502 | | * ever is larger for the array size. |
503 | | */ |
504 | | #define MAX_DCC_16 (2 * MAX_DCC < 16 ? 16 : 2 * MAX_DCC) |
505 | | |
506 | | /* Forward references. */ |
507 | | /* Use a typedef to attempt to work around overly picky compilers. */ |
508 | | typedef gx_color_value gx_color_value_array[MAX_DCC]; |
509 | | typedef struct color_values_pair_s { |
510 | | gx_color_value_array values[2]; |
511 | | } color_values_pair_t; |
512 | | #define SET_HT_COLORS_PROC(proc)\ |
513 | 410M | int proc(\ |
514 | 410M | color_values_pair_t *pvp,\ |
515 | 410M | gx_color_index colors[MAX_DCC_16],\ |
516 | 410M | const gx_const_strip_bitmap *sbits[MAX_DCC],\ |
517 | 410M | const gx_device_color *pdevc,\ |
518 | 410M | gx_device *dev,\ |
519 | 410M | gx_ht_cache *caches[MAX_DCC],\ |
520 | 410M | int nplanes\ |
521 | 410M | ) |
522 | | |
523 | | static SET_HT_COLORS_PROC(set_ht_colors_le_4); |
524 | | static SET_HT_COLORS_PROC(set_cmyk_1bit_colors); |
525 | | static SET_HT_COLORS_PROC(set_ht_colors_gt_4); |
526 | | |
527 | | #define SET_COLOR_HT_PROC(proc)\ |
528 | 410M | void proc(\ |
529 | 410M | byte *dest_data, /* the output tile */\ |
530 | 410M | uint dest_raster, /* ibid. */\ |
531 | 410M | int px, /* the initial phase of the output tile */\ |
532 | 410M | int py,\ |
533 | 410M | int w, /* how much of the tile to set */\ |
534 | 410M | int h,\ |
535 | 410M | int depth, /* depth of tile (4, 8, 16, 24, 32) */\ |
536 | 410M | int special, /* >0 means special 1-bit CMYK */\ |
537 | 410M | int nplanes,\ |
538 | 410M | gx_color_index plane_mask, /* which planes are halftoned */\ |
539 | 410M | gx_device *dev, /* in case we are mapping lazily */\ |
540 | 410M | const color_values_pair_t *pvp, /* color values ditto */\ |
541 | 410M | gx_color_index colors[MAX_DCC_16], /* the actual colors for the tile, */\ |
542 | 410M | /* actually [nplanes] */\ |
543 | 410M | const gx_const_strip_bitmap * sbits[MAX_DCC_16] /* the bitmaps for the planes, */\ |
544 | 410M | /* actually [nplanes] */\ |
545 | 410M | ) |
546 | | |
547 | | static SET_COLOR_HT_PROC(set_color_ht_le_4); |
548 | | static SET_COLOR_HT_PROC(set_color_ht_gt_4); |
549 | | |
550 | | /* Prepare to use a colored halftone, by loading the default cache. */ |
551 | | static int |
552 | | gx_dc_ht_colored_load(gx_device_color * pdevc, const gs_gstate * pgs, |
553 | | gx_device * ignore_dev, gs_color_select_t select) |
554 | 172M | { |
555 | | /* TO_DO_DEVICEN */ |
556 | | |
557 | 172M | return 0; |
558 | 172M | } |
559 | | |
560 | | /* Fill a rectangle with a colored halftone. */ |
561 | | /* Note that we treat this as "texture" for RasterOp. */ |
562 | | static int |
563 | | gx_dc_ht_colored_fill_rectangle(const gx_device_color * pdevc, |
564 | | int x, int y, int w, int h, |
565 | | gx_device * dev, gs_logical_operation_t lop, |
566 | | const gx_rop_source_t * source) |
567 | 410M | { |
568 | 410M | #if defined(PACIFY_VALGRIND) || defined(MEMENTO) |
569 | 410M | ulong tbits[tile_longs_allocated] = { 0 }; |
570 | | #else |
571 | | ulong tbits[tile_longs_allocated]; |
572 | | #endif |
573 | 410M | const uint tile_bytes = tile_longs * size_of(long); |
574 | 410M | gx_strip_bitmap tiles; |
575 | 410M | gx_rop_source_t no_source; |
576 | 410M | const gx_device_halftone *pdht = pdevc->colors.colored.c_ht; |
577 | 410M | int depth = dev->color_info.depth; |
578 | 410M | int nplanes = dev->color_info.num_components; |
579 | | |
580 | 410M | SET_HT_COLORS_PROC((*set_ht_colors)) = |
581 | 410M | ( |
582 | | #if USE_SLOW_CODE |
583 | | set_ht_colors_gt_4 |
584 | | #else |
585 | 410M | (dev_proc(dev, dev_spec_op)(dev, gxdso_is_std_cmyk_1bit, NULL, 0) > 0) ? |
586 | 31.2M | set_cmyk_1bit_colors : |
587 | 410M | nplanes <= 4 ? set_ht_colors_le_4 : |
588 | 378M | set_ht_colors_gt_4 |
589 | 410M | #endif |
590 | 410M | ); |
591 | 410M | SET_COLOR_HT_PROC((*set_color_ht)) = |
592 | 410M | ( |
593 | 410M | #if !USE_SLOW_CODE |
594 | 410M | !(pdevc->colors.colored.plane_mask & ~(gx_color_index)15) && |
595 | 410M | set_ht_colors != set_ht_colors_gt_4 ? |
596 | 410M | set_color_ht_le_4 : |
597 | 410M | #endif |
598 | 410M | set_color_ht_gt_4); |
599 | 410M | color_values_pair_t vp; |
600 | 410M | gx_color_index colors[MAX_DCC_16]; |
601 | 410M | const gx_const_strip_bitmap *sbits[MAX_DCC]; |
602 | 410M | gx_ht_cache *caches[MAX_DCC]; |
603 | 410M | int special; |
604 | 410M | int code = 0; |
605 | 410M | int raster; |
606 | 410M | uint size_x; |
607 | 410M | int dw, dh; |
608 | 410M | int lw = pdht->lcm_width, lh = pdht->lcm_height; |
609 | 410M | bool no_rop; |
610 | 410M | int i; |
611 | 410M | int origx, origy; |
612 | | |
613 | | /* This routine cannot build 3bit chunky halftones, as 3 bit |
614 | | * things don't pack nicely into bytes or words. Accordingly |
615 | | * treat 3 bit things as 4 bit things. This is appropriate when |
616 | | * generating halftones for planar. */ |
617 | 410M | if (depth == 3) |
618 | 0 | depth = 4; |
619 | | |
620 | 410M | if (w <= 0 || h <= 0) |
621 | 219M | return 0; |
622 | 190M | origx = x; |
623 | 190M | origy = y; |
624 | 190M | if ((w | h) >= 16) { |
625 | | /* It's worth taking the trouble to check the clipping box. */ |
626 | 32.2M | gs_fixed_rect cbox; |
627 | 32.2M | int t; |
628 | | |
629 | 32.2M | dev_proc(dev, get_clipping_box)(dev, &cbox); |
630 | 32.2M | if ((t = fixed2int(cbox.p.x)) > x) { |
631 | 14.1M | if ((w += x - t) <= 0) |
632 | 13.8M | return 0; |
633 | 246k | x = t; |
634 | 246k | } |
635 | 18.3M | if ((t = fixed2int(cbox.p.y)) > y) { |
636 | 733k | if ((h += y - t) <= 0) |
637 | 720k | return 0; |
638 | 12.8k | y = t; |
639 | 12.8k | } |
640 | 17.6M | if ((t = fixed2int(cbox.q.x)) < x + w) |
641 | 5.36M | if ((w = t - x) <= 0) |
642 | 5.07M | return 0; |
643 | 12.5M | if ((t = fixed2int(cbox.q.y)) < y + h) |
644 | 597k | if ((h = t - y) <= 0) |
645 | 590k | return 0; |
646 | 12.5M | } |
647 | | /* Colored halftone patterns are unconditionally opaque. */ |
648 | 170M | lop &= ~lop_T_transparent; |
649 | 170M | if (pdht->components == 0) { |
650 | 0 | caches[0] = caches[1] = caches[2] = caches[3] = pdht->order.cache; |
651 | 0 | for (i = 4; i < nplanes; ++i) |
652 | 0 | caches[i] = pdht->order.cache; |
653 | 170M | } else { |
654 | 170M | gx_ht_order_component *pocs = pdht->components; |
655 | | |
656 | 703M | for (i = 0; i < nplanes; ++i) |
657 | 532M | caches[i] = pocs[i].corder.cache; |
658 | 170M | } |
659 | 170M | special = set_ht_colors(&vp, colors, sbits, pdevc, dev, caches, nplanes); |
660 | 170M | no_rop = source == NULL && lop_no_S_is_T(lop); |
661 | 170M | if ((!no_rop) && (source == NULL)) |
662 | 0 | set_rop_no_source(source, no_source, dev); |
663 | | |
664 | | /* |
665 | | * If the LCM of the plane cell sizes is smaller than the rectangle |
666 | | * being filled, compute a single tile and let strip_tile_rectangle |
667 | | * do the replication. |
668 | | */ |
669 | 170M | if ((w > lw || h > lh) && |
670 | 170M | (raster = bitmap_raster(lw * depth)) <= tile_bytes / lh |
671 | 170M | ) { |
672 | | /* |
673 | | * The only reason we need to do fit_fill here is that if the |
674 | | * device is a clipper, the caller might be counting on it to do |
675 | | * all necessary clipping. Actually, we should clip against the |
676 | | * device's clipping box, not the default.... |
677 | | */ |
678 | 143k | fit_fill(dev, x, y, w, h); |
679 | | /* Check to make sure we still have a big rectangle. */ |
680 | 143k | if (w > lw || h > lh) { |
681 | 143k | tiles.data = (byte *)tbits; |
682 | 143k | tiles.raster = raster; |
683 | 143k | tiles.rep_width = tiles.size.x = lw; |
684 | 143k | tiles.rep_height = tiles.size.y = lh; |
685 | 143k | tiles.id = gs_next_ids(pdht->rc.memory, 1); |
686 | 143k | tiles.rep_shift = tiles.shift = 0; |
687 | 143k | tiles.num_planes = 1; |
688 | 143k | set_color_ht((byte *)tbits, raster, 0, 0, lw, lh, depth, |
689 | 143k | special, nplanes, pdevc->colors.colored.plane_mask, |
690 | 143k | dev, &vp, colors, sbits); |
691 | 143k | if (no_rop) |
692 | 143k | return (*dev_proc(dev, strip_tile_rectangle)) (dev, &tiles, |
693 | 143k | x, y, w, h, |
694 | 143k | gx_no_color_index, |
695 | 143k | gx_no_color_index, |
696 | 143k | pdevc->phase.x, |
697 | 143k | pdevc->phase.y); |
698 | 0 | return (*dev_proc(dev, strip_copy_rop2)) |
699 | 0 | (dev, |
700 | 0 | source->sdata + (y - origy) * source->sraster, |
701 | 0 | source->sourcex + (x - origx), |
702 | 0 | source->sraster, source->id, |
703 | 0 | (source->use_scolors ? source->scolors : NULL), |
704 | 0 | &tiles, NULL, |
705 | 0 | x, y, w, h, |
706 | 0 | pdevc->phase.x, pdevc->phase.y, lop, |
707 | 0 | source->planar_height); |
708 | 143k | } |
709 | 143k | } |
710 | 170M | size_x = w * depth; |
711 | 170M | raster = bitmap_raster(size_x); |
712 | 170M | if (raster > tile_bytes) { |
713 | | /* |
714 | | * We can't even do an entire line at once. See above for |
715 | | * why we do the X equivalent of fit_fill here. |
716 | | */ |
717 | 1.10k | if (x < 0) |
718 | 0 | w += x, x = 0; |
719 | 1.10k | if (x > dev->width - w) |
720 | 0 | w = dev->width - x; |
721 | 1.10k | if (w <= 0) |
722 | 0 | return 0; |
723 | 1.10k | size_x = w * depth; |
724 | 1.10k | raster = bitmap_raster(size_x); |
725 | 1.10k | if (raster > tile_bytes) { |
726 | | /* We'll have to do a partial line. */ |
727 | 1.10k | dw = tile_bytes * 8 / depth; |
728 | 1.10k | size_x = dw * depth; |
729 | 1.10k | raster = bitmap_raster(size_x); |
730 | 1.10k | dh = 1; |
731 | 1.10k | goto fit; |
732 | 1.10k | } |
733 | 1.10k | } |
734 | | /* Do as many lines as will fit. */ |
735 | 170M | dw = w; |
736 | 170M | dh = tile_bytes / raster; |
737 | 170M | if (dh > h) |
738 | 170M | dh = h; |
739 | 170M | fit: /* Now the tile will definitely fit. */ |
740 | 170M | if (!no_rop) { |
741 | 0 | tiles.data = (byte *)tbits; |
742 | 0 | tiles.id = gx_no_bitmap_id; |
743 | 0 | tiles.raster = raster; |
744 | 0 | tiles.rep_width = tiles.size.x = size_x / depth; |
745 | 0 | tiles.rep_shift = tiles.shift = 0; |
746 | 0 | tiles.num_planes = 1; |
747 | 0 | } |
748 | 170M | while (w) { |
749 | 170M | int cy = y, ch = dh, left = h; |
750 | | |
751 | 173M | for (;;) { |
752 | 173M | set_color_ht((byte *)tbits, raster, |
753 | 173M | x + pdevc->phase.x, cy + pdevc->phase.y, |
754 | 173M | dw, ch, depth, special, nplanes, |
755 | 173M | pdevc->colors.colored.plane_mask, |
756 | 173M | dev, &vp, colors, sbits); |
757 | 173M | if (no_rop) { |
758 | 173M | code = (*dev_proc(dev, copy_color)) |
759 | 173M | (dev, (byte *)tbits, 0, raster, gx_no_bitmap_id, |
760 | 173M | x, cy, dw, ch); |
761 | 173M | } else { |
762 | 0 | tiles.rep_height = tiles.size.y = ch; |
763 | 0 | code = (*dev_proc(dev, strip_copy_rop2)) |
764 | 0 | (dev, source->sdata + source->sraster * (cy-origy), |
765 | 0 | source->sourcex + (x - origx), |
766 | 0 | source->sraster, |
767 | 0 | source->id, |
768 | 0 | (source->use_scolors ? source->scolors : NULL), |
769 | 0 | &tiles, NULL, x, cy, dw, ch, 0, 0, lop, |
770 | 0 | source->planar_height); |
771 | 0 | } |
772 | 173M | if (code < 0) |
773 | 0 | return code; |
774 | 173M | if (!(left -= ch)) |
775 | 170M | break; |
776 | 2.90M | cy += ch; |
777 | 2.90M | if (ch > left) |
778 | 79.3k | ch = left; |
779 | 2.90M | } |
780 | 170M | if (!(w -= dw)) |
781 | 170M | break; |
782 | 1.10k | x += dw; |
783 | 1.10k | if (dw > w) |
784 | 1.10k | dw = w; |
785 | 1.10k | } |
786 | 170M | return code; |
787 | 170M | } |
788 | | |
789 | | /* ---------------- Color table setup ---------------- */ |
790 | | |
791 | | /* |
792 | | * We could cache this if we had a place to store it. Even a 1-element |
793 | | * cache would help performance substantially. |
794 | | * Key: device + c_base/c_level of device color |
795 | | * Value: colors table |
796 | | */ |
797 | | |
798 | | /* |
799 | | * We construct color halftone tiles out of multiple "planes". |
800 | | * Each plane specifies halftoning for one component (R/G/B, C/M/Y/K, |
801 | | * or DeviceN components). |
802 | | */ |
803 | | |
804 | | static const struct { |
805 | | ulong pad; /* to get bytes aligned properly */ |
806 | | byte bytes[sizeof(ulong) * 8]; /* 8 is arbitrary */ |
807 | | } ht_no_bitmap_data = { 0 }; |
808 | | static const gx_const_strip_bitmap ht_no_bitmap = { |
809 | | &ht_no_bitmap_data.bytes[0], sizeof(ulong), |
810 | | {sizeof(ulong) * 8, sizeof(ht_no_bitmap_data.bytes) / sizeof(ulong)}, |
811 | | gx_no_bitmap_id, 1, 1, 0, 0 |
812 | | }; |
813 | | |
814 | | /* Set the color value(s) and halftone mask for one plane. */ |
815 | | static inline void set_plane_color(int i, color_values_pair_t *pvp, const gx_device_color * pdc, |
816 | | const gx_const_strip_bitmap * sbits[MAX_DCC], gx_ht_cache * caches[MAX_DCC], |
817 | | gx_color_value max_color, bool invert) |
818 | 458M | { |
819 | 458M | uint q = pdc->colors.colored.c_base[i]; |
820 | 458M | uint r = pdc->colors.colored.c_level[i]; |
821 | | |
822 | 458M | pvp->values[0][i] = fractional_color(q, max_color); |
823 | 458M | if (r == 0) |
824 | 23.6M | pvp->values[1][i] = pvp->values[0][i], sbits[i] = &ht_no_bitmap; |
825 | 435M | else if (!invert) { |
826 | 429M | pvp->values[1][i] = fractional_color(q + 1, max_color); |
827 | 429M | sbits[i] = (const gx_const_strip_bitmap *) &gx_render_ht(caches[i], r)->tiles; |
828 | 429M | } else { |
829 | 5.67M | const gx_device_halftone *pdht = pdc->colors.colored.c_ht; |
830 | 5.67M | int nlevels = |
831 | 5.67M | (pdht->components ? pdht->components[i].corder.num_levels : pdht->order.num_levels); |
832 | 5.67M | pvp->values[1][i] = pvp->values[0][i]; |
833 | 5.67M | pvp->values[0][i] = fractional_color(q + 1, max_color); |
834 | 5.67M | sbits[i] = (const gx_const_strip_bitmap *) &gx_render_ht(caches[i], nlevels - r)->tiles; |
835 | 5.67M | } |
836 | 458M | } |
837 | | |
838 | | /* Set up the colors and the individual plane halftone bitmaps. */ |
839 | | static int |
840 | | set_ht_colors_le_4(color_values_pair_t *pvp /* only used internally */, |
841 | | gx_color_index colors[MAX_DCC_16] /* 16 used */, |
842 | | const gx_const_strip_bitmap * sbits[MAX_DCC], |
843 | | const gx_device_color * pdc, gx_device * dev, |
844 | | gx_ht_cache * caches[MAX_DCC], int nplanes) |
845 | 152M | { |
846 | 152M | gx_color_value max_color = dev->color_info.dither_colors - 1; |
847 | 152M | gx_color_value cvalues[4]; |
848 | | /* |
849 | | * NB: the halftone orders are all set up for an additive color space. |
850 | | * To make these work with a subtractive device space such as CMYK, |
851 | | * it is necessary to invert both the color level and the color |
852 | | * pair. Note that if the original color was provided an additive |
853 | | * space, this will reverse (in an approximate sense) the color |
854 | | * conversion performed to express the color in the device space. |
855 | | */ |
856 | 152M | bool invert = dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE; |
857 | | |
858 | 152M | set_plane_color(0, pvp, pdc, sbits, caches, max_color, invert); |
859 | 152M | if (nplanes >= 2) { |
860 | 152M | set_plane_color(1, pvp, pdc, sbits, caches, max_color, invert); |
861 | 152M | } |
862 | 152M | if (nplanes >= 3) { |
863 | 152M | set_plane_color(2, pvp, pdc, sbits, caches, max_color, invert); |
864 | 152M | } |
865 | 152M | if (nplanes == 3) { |
866 | 149M | #define M(i)\ |
867 | 1.19G | cvalues[0] = pvp->values[(i) & 1][0];\ |
868 | 1.19G | cvalues[1] = pvp->values[((i) & 2) >> 1][1];\ |
869 | 1.19G | cvalues[2] = pvp->values[(i) >> 2][2];\ |
870 | 1.19G | colors[i] = dev_proc(dev, encode_color)(dev, cvalues); |
871 | | |
872 | 149M | M(0); M(1); M(2); M(3); M(4); M(5); M(6); M(7); |
873 | 149M | #undef M |
874 | 149M | } else if (nplanes > 3){ |
875 | 2.25M | set_plane_color(3, pvp, pdc, sbits, caches, max_color, invert); |
876 | 2.25M | if (nplanes > 4) { |
877 | | /* |
878 | | * Set colors for any planes beyond the 4th. Since this code |
879 | | * only handles the case of at most 4 active planes, we know |
880 | | * that any further planes are constant. |
881 | | */ |
882 | | /****** DOESN'T MAP COLORS RIGHT, DOESN'T HANDLE ALPHA ******/ |
883 | 0 | int pi; |
884 | |
|
885 | 0 | for (pi = 4; pi < nplanes; ++pi) { |
886 | 0 | pvp->values[1][pi] = pvp->values[0][pi] = |
887 | 0 | fractional_color(pdc->colors.colored.c_base[pi], max_color); |
888 | 0 | sbits[pi] = &ht_no_bitmap; |
889 | 0 | } |
890 | 0 | } |
891 | | /* |
892 | | * For CMYK output, especially if the input was RGB, it's |
893 | | * common for one or more of the components to be zero. |
894 | | * Each zero component can cut the cost of color mapping in |
895 | | * half, so it's worth doing a little checking here. |
896 | | */ |
897 | 2.25M | #define M(i)\ |
898 | 14.9M | cvalues[0] = pvp->values[(i) & 1][0];\ |
899 | 14.9M | cvalues[1] = pvp->values[((i) & 2) >> 1][1];\ |
900 | 14.9M | cvalues[2] = pvp->values[((i) & 4) >> 2][2];\ |
901 | 14.9M | cvalues[3] = pvp->values[(i) >> 3][3];\ |
902 | 14.9M | colors[i] = dev_proc(dev, encode_color)(dev, cvalues) |
903 | | |
904 | | /* We know that plane_mask <= 15. */ |
905 | 2.25M | switch ((int)pdc->colors.colored.plane_mask) { |
906 | 418k | case 15: |
907 | 418k | M(15); M(14); M(13); M(12); |
908 | 418k | M(11); M(10); M(9); M(8); |
909 | 599k | case 7: |
910 | 599k | M(7); M(6); M(5); M(4); |
911 | 830k | c3: case 3: |
912 | 830k | M(3); M(2); |
913 | 1.82M | c1: case 1: |
914 | 1.82M | M(1); |
915 | 1.82M | break; |
916 | 4.75k | case 14: |
917 | 4.75k | M(14); M(12); M(10); M(8); |
918 | 425k | case 6: |
919 | 425k | M(6); M(4); |
920 | 425k | c2: case 2: |
921 | 425k | M(2); |
922 | 425k | break; |
923 | 27.1k | case 13: |
924 | 27.1k | M(13); M(12); M(9); M(8); |
925 | 915k | case 5: |
926 | 915k | M(5); M(4); |
927 | 915k | goto c1; |
928 | 1.79k | case 12: |
929 | 1.79k | M(12); M(8); |
930 | 1.79k | case 4: |
931 | 1.79k | M(4); |
932 | 1.79k | break; |
933 | 24.5k | case 11: |
934 | 24.5k | M(11); M(10); M(9); M(8); |
935 | 24.5k | goto c3; |
936 | 0 | case 10: |
937 | 0 | M(10); M(8); |
938 | 0 | goto c2; |
939 | 84.2k | case 9: |
940 | 84.2k | M(9); M(8); |
941 | 84.2k | goto c1; |
942 | 0 | case 8: |
943 | 0 | M(8); |
944 | 0 | break; |
945 | 0 | case 0:; |
946 | 2.25M | } |
947 | 2.25M | M(0); |
948 | | |
949 | 2.25M | #undef M |
950 | 2.25M | } |
951 | 152M | return 0; |
952 | 152M | } |
953 | | |
954 | | /* Set up colors using the standard 1-bit CMYK mapping. */ |
955 | | static int |
956 | | set_cmyk_1bit_colors(color_values_pair_t *ignore_pvp, |
957 | | gx_color_index colors[MAX_DCC_16] /*2 used*/, |
958 | | const gx_const_strip_bitmap * sbits[MAX_DCC /*4 used*/], |
959 | | const gx_device_color * pdc, gx_device * dev, |
960 | | gx_ht_cache * caches[MAX_DCC /*4 used*/], |
961 | | int nplanes /*4*/) |
962 | 18.4M | { |
963 | 18.4M | const gx_device_halftone *pdht = pdc->colors.colored.c_ht; |
964 | | /* |
965 | | * By reversing the order of the planes, we make the pixel values |
966 | | * line up with the color indices. Then instead of a lookup, we |
967 | | * can compute the pixels directly using a Boolean function. |
968 | | * |
969 | | * We compute each output bit |
970 | | * out[i] = (in[i] & mask1) | (~in[i] & mask0) |
971 | | * We store the two masks in colors[0] and colors[1], since the |
972 | | * colors array is otherwise unused in this case. We duplicate |
973 | | * the values in all the nibbles so we can do several pixels at a time. |
974 | | */ |
975 | 18.4M | bits32 mask0 = 0, mask1 = 0; |
976 | 18.4M | #define SET_PLANE_COLOR_CMYK(i, mask)\ |
977 | 73.7M | BEGIN\ |
978 | 73.7M | uint r = pdc->colors.colored.c_level[i];\ |
979 | 73.7M | \ |
980 | 73.7M | if (r == 0) {\ |
981 | 16.4M | if (pdc->colors.colored.c_base[i])\ |
982 | 16.4M | mask0 |= mask, mask1 |= mask;\ |
983 | 16.4M | sbits[3 - i] = &ht_no_bitmap;\ |
984 | 57.2M | } else {\ |
985 | 57.2M | int nlevels =\ |
986 | 57.2M | (pdht->components ?\ |
987 | 57.2M | pdht->components[i].corder.num_levels :\ |
988 | 57.2M | pdht->order.num_levels);\ |
989 | 57.2M | \ |
990 | 57.2M | mask0 |= mask;\ |
991 | 57.2M | sbits[3 - i] = (const gx_const_strip_bitmap *)\ |
992 | 57.2M | &gx_render_ht(caches[i], nlevels - r)->tiles;\ |
993 | 57.2M | }\ |
994 | 73.7M | END |
995 | | /* Suppress a compiler warning about signed/unsigned constants. */ |
996 | 18.4M | SET_PLANE_COLOR_CMYK(0, /*0x88888888*/ (bits32)~0x77777777); |
997 | 18.4M | SET_PLANE_COLOR_CMYK(1, 0x44444444); |
998 | 18.4M | SET_PLANE_COLOR_CMYK(2, 0x22222222); |
999 | 18.4M | SET_PLANE_COLOR_CMYK(3, 0x11111111); |
1000 | | |
1001 | 18.4M | #undef SET_PLANE_COLOR_CMYK |
1002 | 18.4M | { |
1003 | 18.4M | gx_ht_cache *ctemp; |
1004 | | |
1005 | 18.4M | ctemp = caches[0], caches[0] = caches[3], caches[3] = ctemp; |
1006 | 18.4M | ctemp = caches[1], caches[1] = caches[2], caches[2] = ctemp; |
1007 | 18.4M | } |
1008 | 18.4M | colors[0] = mask0; |
1009 | 18.4M | colors[1] = mask1; |
1010 | 18.4M | return 1; |
1011 | 18.4M | } |
1012 | | |
1013 | | /* |
1014 | | * Set up colors for >4 planes. In this case, we assume that the color |
1015 | | * component values are "separable". (That we can form a gx_color_index value |
1016 | | * for a color by a bit wise or of the gx_color_index values of the individual |
1017 | | * components.) |
1018 | | */ |
1019 | | static int |
1020 | | set_ht_colors_gt_4(color_values_pair_t *pvp, |
1021 | | gx_color_index colors[MAX_DCC_16 /* 2 * nplanes */], |
1022 | | const gx_const_strip_bitmap * sbits[MAX_DCC], |
1023 | | const gx_device_color * pdc, gx_device * dev, |
1024 | | gx_ht_cache * caches[MAX_DCC], int nplanes) |
1025 | 36.3k | { |
1026 | 36.3k | gx_color_value max_color = dev->color_info.dither_colors - 1; |
1027 | 36.3k | bool invert = dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE; |
1028 | 36.3k | gx_color_index plane_mask = pdc->colors.colored.plane_mask; |
1029 | 36.3k | int i; |
1030 | 36.3k | gx_color_value cv[MAX_DCC] = {0}; |
1031 | | |
1032 | | /* Set the color values and halftone caches. */ |
1033 | 280k | for (i = 0; i < nplanes; ++i) { |
1034 | 244k | if ((plane_mask >> i) & 1) |
1035 | 83.6k | set_plane_color(i, pvp, pdc, sbits, caches, max_color, invert); |
1036 | 160k | else { |
1037 | 160k | pvp->values[1][i] = pvp->values[0][i] = |
1038 | 160k | fractional_color(pdc->colors.colored.c_base[i], max_color); |
1039 | 160k | sbits[i] = &ht_no_bitmap; |
1040 | 160k | } |
1041 | 244k | } |
1042 | | /* |
1043 | | * Determine a gs_color_index value for each pair of component values. |
1044 | | * We assume that an overall index value can be formed from the |
1045 | | * bitwise or of each component. We calculate a value for both |
1046 | | * the high and low value of each component. These are stored |
1047 | | * in adjacent locations in 'colors'. |
1048 | | */ |
1049 | 280k | for (i = 0; i < nplanes; i++ ) { |
1050 | 244k | cv[i] = pvp->values[0][i]; |
1051 | 244k | colors[2 * i] = dev_proc(dev, encode_color)(dev, cv); |
1052 | | /* We only need both values for components being halftoned */ |
1053 | 244k | if ((plane_mask >> i) & 1) { |
1054 | 83.6k | cv[i] = pvp->values[1][i]; |
1055 | 83.6k | colors[2 * i + 1] = dev_proc(dev, encode_color)(dev, cv); |
1056 | 83.6k | } |
1057 | 244k | cv[i] = 0; |
1058 | 244k | } |
1059 | | |
1060 | 36.3k | return 0; |
1061 | 36.3k | } |
1062 | | |
1063 | | /* ---------------- Color rendering ---------------- */ |
1064 | | |
1065 | | /* Define the bookkeeping structure for each plane of halftone rendering. */ |
1066 | | typedef struct tile_cursor_s { |
1067 | | int tile_shift; /* X shift per copy of tile */ |
1068 | | int xoffset; |
1069 | | int xshift; |
1070 | | uint xbytes; |
1071 | | int xbits; |
1072 | | const byte *row; |
1073 | | const byte *tdata; |
1074 | | uint raster; |
1075 | | const byte *data; |
1076 | | int bit_shift; |
1077 | | } tile_cursor_t; |
1078 | | |
1079 | | /* |
1080 | | * Initialize one plane cursor, including setting up for the first row |
1081 | | * (data and bit_shift). |
1082 | | */ |
1083 | | static void |
1084 | | init_tile_cursor(int i, tile_cursor_t *ptc, const gx_const_strip_bitmap *btile, |
1085 | | int endx, int lasty) |
1086 | 500M | { |
1087 | 500M | int tw = btile->size.x; |
1088 | 500M | int bx = ((ptc->tile_shift = btile->shift) == 0 ? endx : |
1089 | 500M | endx + lasty / btile->size.y * ptc->tile_shift) % tw; |
1090 | 500M | int by = lasty % btile->size.y; |
1091 | | |
1092 | 500M | ptc->xoffset = bx >> 3; |
1093 | 500M | ptc->xshift = 8 - (bx & 7); |
1094 | 500M | ptc->xbytes = (tw - 1) >> 3; |
1095 | 500M | ptc->xbits = ((tw - 1) & 7) + 1; |
1096 | 500M | ptc->tdata = btile->data; |
1097 | 500M | ptc->raster = btile->raster; |
1098 | 500M | ptc->row = ptc->tdata + by * (int)ptc->raster; |
1099 | 500M | ptc->data = ptc->row + ptc->xoffset; |
1100 | 500M | ptc->bit_shift = ptc->xshift; |
1101 | 500M | if_debug6('h', "[h]plane %d: size=%d,%d shift=%d bx=%d by=%d\n", |
1102 | 500M | i, tw, btile->size.y, btile->shift, bx, by); |
1103 | 500M | } |
1104 | | |
1105 | | /* Step a cursor to the next row. */ |
1106 | | static void |
1107 | | wrap_shifted_cursor(tile_cursor_t *ptc, const gx_const_strip_bitmap *psbit) |
1108 | 24.8M | { |
1109 | 24.8M | ptc->row += ptc->raster * (psbit->size.y - 1); |
1110 | 24.8M | if (ptc->tile_shift) { |
1111 | 0 | if ((ptc->xshift += ptc->tile_shift) >= 8) { |
1112 | 0 | if ((ptc->xoffset -= ptc->xshift >> 3) < 0) { |
1113 | | /* wrap around in X */ |
1114 | 0 | int bx = (ptc->xoffset << 3) + 8 - (ptc->xshift & 7) + |
1115 | 0 | psbit->size.x; |
1116 | |
|
1117 | 0 | ptc->xoffset = bx >> 3; |
1118 | 0 | ptc->xshift = 8 - (bx & 7); |
1119 | 0 | } else |
1120 | 0 | ptc->xshift &= 7; |
1121 | 0 | } |
1122 | 0 | } |
1123 | 24.8M | } |
1124 | | #define STEP_ROW(c, i)\ |
1125 | 419M | BEGIN\ |
1126 | 419M | if (c.row > c.tdata)\ |
1127 | 419M | c.row -= c.raster;\ |
1128 | 419M | else { /* wrap around to end of tile */\ |
1129 | 24.8M | wrap_shifted_cursor(&c, sbits[i]);\ |
1130 | 24.8M | }\ |
1131 | 419M | c.data = c.row + c.xoffset;\ |
1132 | 419M | c.bit_shift = c.xshift;\ |
1133 | 419M | END |
1134 | | |
1135 | | /* Define a table for expanding 8x1 bits to 8x4. */ |
1136 | | static const bits32 expand_8x1_to_8x4[256] = { |
1137 | | #define X16(c)\ |
1138 | | c+0, c+1, c+0x10, c+0x11, c+0x100, c+0x101, c+0x110, c+0x111,\ |
1139 | | c+0x1000, c+0x1001, c+0x1010, c+0x1011, c+0x1100, c+0x1101, c+0x1110, c+0x1111 |
1140 | | X16(0x00000000), X16(0x00010000), X16(0x00100000), X16(0x00110000), |
1141 | | X16(0x01000000), X16(0x01010000), X16(0x01100000), X16(0x01110000), |
1142 | | X16(0x10000000), X16(0x10010000), X16(0x10100000), X16(0x10110000), |
1143 | | X16(0x11000000), X16(0x11010000), X16(0x11100000), X16(0x11110000) |
1144 | | #undef X16 |
1145 | | }; |
1146 | | |
1147 | | /* |
1148 | | * Render the combined halftone for nplanes <= 4. |
1149 | | */ |
1150 | | static void |
1151 | | set_color_ht_le_4(byte *dest_data, uint dest_raster, int px, int py, |
1152 | | int w, int h, int depth, int special, int nplanes, |
1153 | | gx_color_index plane_mask, gx_device *ignore_dev, |
1154 | | const color_values_pair_t *ignore_pvp, |
1155 | | gx_color_index colors[MAX_DCC_16], |
1156 | | const gx_const_strip_bitmap * sbits[MAX_DCC_16]) |
1157 | 173M | { |
1158 | | /* |
1159 | | * Note that the planes are specified in the order RGB or CMYK, but |
1160 | | * the indices used for the internal colors array are BGR or KYMC, |
1161 | | * except for the special 1-bit CMYK case. |
1162 | | */ |
1163 | 173M | int x, y; |
1164 | 173M | tile_cursor_t cursor[MAX_DCC]; |
1165 | 173M | int dbytes = depth >> 3; |
1166 | 173M | byte *dest_row = |
1167 | 173M | dest_data + dest_raster * (h - 1) + (w * depth) / 8; |
1168 | | |
1169 | 173M | if (special > 0) { |
1170 | | /* Planes are in reverse order. */ |
1171 | 18.7M | plane_mask = |
1172 | 18.7M | "\000\010\004\014\002\012\006\016\001\011\005\015\003\013\007\017"[plane_mask]; |
1173 | 18.7M | } |
1174 | 173M | if_debug6('h', |
1175 | 173M | "[h]color_ht_le_4: x=%d y=%d w=%d h=%d plane_mask=0x%lu depth=%d\n", |
1176 | 173M | px, py, w, h, (ulong)plane_mask, depth); |
1177 | | |
1178 | | /* Do one-time cursor initialization. */ |
1179 | 173M | { |
1180 | 173M | int endx = w + px; |
1181 | 173M | int lasty = h - 1 + py; |
1182 | | |
1183 | 173M | if (plane_mask & 1) |
1184 | 151M | init_tile_cursor(0, &cursor[0], sbits[0], endx, lasty); |
1185 | 173M | if (plane_mask & 2) |
1186 | 164M | init_tile_cursor(1, &cursor[1], sbits[1], endx, lasty); |
1187 | 173M | if (plane_mask & 4) |
1188 | 166M | init_tile_cursor(2, &cursor[2], sbits[2], endx, lasty); |
1189 | 173M | if (plane_mask & 8) |
1190 | 18.7M | init_tile_cursor(3, &cursor[3], sbits[3], endx, lasty); |
1191 | 173M | } |
1192 | | |
1193 | | /* Now compute the actual tile. */ |
1194 | 246M | for (y = h; ; dest_row -= dest_raster) { |
1195 | 246M | byte *dest = dest_row; |
1196 | | |
1197 | 246M | --y; |
1198 | 1.94G | for (x = w; x > 0;) { |
1199 | 1.69G | bits32 indices; |
1200 | 1.69G | int nx, i; |
1201 | 1.69G | register uint bits; |
1202 | | |
1203 | | /* Get the next byte's worth of bits. Note that there may be */ |
1204 | | /* excess bits set beyond the 8th. */ |
1205 | 1.69G | #define NEXT_BITS(c)\ |
1206 | 4.83G | BEGIN\ |
1207 | 4.83G | if (c.data > c.row) {\ |
1208 | 4.74G | bits = ((c.data[-1] << 8) | *c.data) >> c.bit_shift;\ |
1209 | 4.74G | c.data--;\ |
1210 | 4.74G | } else {\ |
1211 | 88.3M | bits = *c.data >> c.bit_shift;\ |
1212 | 88.3M | c.data += c.xbytes;\ |
1213 | 88.3M | if ((c.bit_shift -= c.xbits) < 0) {\ |
1214 | 81.3M | bits |= *c.data << -c.bit_shift;\ |
1215 | 81.3M | c.bit_shift += 8;\ |
1216 | 81.3M | } else {\ |
1217 | 6.98M | bits |= ((c.data[-1] << 8) | *c.data) >> c.bit_shift;\ |
1218 | 6.98M | c.data--;\ |
1219 | 6.98M | }\ |
1220 | 88.3M | }\ |
1221 | 4.83G | END |
1222 | 1.69G | if (plane_mask & 1) { |
1223 | 1.51G | NEXT_BITS(cursor[0]); |
1224 | 1.51G | indices = expand_8x1_to_8x4[bits & 0xff]; |
1225 | 1.51G | } else |
1226 | 177M | indices = 0; |
1227 | 1.69G | if (plane_mask & 2) { |
1228 | 1.53G | NEXT_BITS(cursor[1]); |
1229 | 1.53G | indices |= expand_8x1_to_8x4[bits & 0xff] << 1; |
1230 | 1.53G | } |
1231 | 1.69G | if (plane_mask & 4) { |
1232 | 1.59G | NEXT_BITS(cursor[2]); |
1233 | 1.59G | indices |= expand_8x1_to_8x4[bits & 0xff] << 2; |
1234 | 1.59G | } |
1235 | 1.69G | if (plane_mask & 8) { |
1236 | 197M | NEXT_BITS(cursor[3]); |
1237 | 197M | indices |= expand_8x1_to_8x4[bits & 0xff] << 3; |
1238 | 197M | } |
1239 | 1.69G | #undef NEXT_BITS |
1240 | 1.69G | nx = min(x, 8); /* 1 <= nx <= 8 */ |
1241 | 1.69G | x -= nx; |
1242 | 1.69G | switch (dbytes) { |
1243 | 1.69G | case 0: /* 4 */ |
1244 | 1.69G | if (special > 0) { |
1245 | | /* Special 1-bit CMYK. */ |
1246 | | /* Compute all the pixels at once! */ |
1247 | 179M | indices = |
1248 | 179M | (indices & colors[1]) | (~indices & colors[0]); |
1249 | 179M | i = nx; |
1250 | 179M | if ((x + nx) & 1) { |
1251 | | /* First pixel is even nibble. */ |
1252 | 57.7M | *dest = (*dest & 0xf) + |
1253 | 57.7M | ((indices & 0xf) << 4); |
1254 | 57.7M | indices >>= 4; |
1255 | 57.7M | --i; |
1256 | 57.7M | } |
1257 | | /* Now 0 <= i <= 8. */ |
1258 | 794M | for (; (i -= 2) >= 0; indices >>= 8) |
1259 | 615M | *--dest = (byte)indices; |
1260 | | /* Check for final odd nibble. */ |
1261 | 179M | if (i & 1) |
1262 | 45.6M | *--dest = indices & 0xf; |
1263 | 1.51G | } else { |
1264 | | /* Other 4-bit pixel */ |
1265 | 1.51G | i = nx; |
1266 | 1.51G | if ((x + nx) & 1) { |
1267 | | /* First pixel is even nibble. */ |
1268 | 687M | *dest = (*dest & 0xf) + |
1269 | 687M | ((byte)colors[indices & 0xf] << 4); |
1270 | 687M | indices >>= 4; |
1271 | 687M | --i; |
1272 | 687M | } |
1273 | | /* Now 0 <= i <= 8. */ |
1274 | 6.39G | for (; (i -= 2) >= 0; indices >>= 8) |
1275 | 4.87G | *--dest = |
1276 | 4.87G | (byte)colors[indices & 0xf] + |
1277 | 4.87G | ((byte)colors[(indices >> 4) & 0xf] |
1278 | 4.87G | << 4); |
1279 | | /* Check for final odd nibble. */ |
1280 | 1.51G | if (i & 1) |
1281 | 552M | *--dest = (byte)colors[indices & 0xf]; |
1282 | 1.51G | } |
1283 | 1.69G | break; |
1284 | 0 | case 4: /* 32 */ |
1285 | 0 | for (i = nx; --i >= 0; indices >>= 4) { |
1286 | 0 | bits32 tcolor = (bits32)colors[indices & 0xf]; |
1287 | |
|
1288 | 0 | dest -= 4; |
1289 | 0 | dest[3] = (byte)tcolor; |
1290 | 0 | dest[2] = (byte)(tcolor >> 8); |
1291 | 0 | tcolor >>= 16; |
1292 | 0 | dest[1] = (byte)tcolor; |
1293 | 0 | dest[0] = (byte)(tcolor >> 8); |
1294 | 0 | } |
1295 | 0 | break; |
1296 | 0 | case 3: /* 24 */ |
1297 | 0 | for (i = nx; --i >= 0; indices >>= 4) { |
1298 | 0 | bits32 tcolor = (bits32)colors[indices & 0xf]; |
1299 | |
|
1300 | 0 | dest -= 3; |
1301 | 0 | dest[2] = (byte) tcolor; |
1302 | 0 | dest[1] = (byte)(tcolor >> 8); |
1303 | 0 | dest[0] = (byte)(tcolor >> 16); |
1304 | 0 | } |
1305 | 0 | break; |
1306 | 0 | case 2: /* 16 */ |
1307 | 0 | for (i = nx; --i >= 0; indices >>= 4) { |
1308 | 0 | uint tcolor = |
1309 | 0 | (uint)colors[indices & 0xf]; |
1310 | |
|
1311 | 0 | dest -= 2; |
1312 | 0 | dest[1] = (byte)tcolor; |
1313 | 0 | dest[0] = (byte)(tcolor >> 8); |
1314 | 0 | } |
1315 | 0 | break; |
1316 | 20.0k | case 1: /* 8 */ |
1317 | 172k | for (i = nx; --i >= 0; indices >>= 4) |
1318 | 152k | *--dest = (byte)colors[indices & 0xf]; |
1319 | 20.0k | break; |
1320 | 1.69G | } |
1321 | 1.69G | } |
1322 | 246M | if (y == 0) |
1323 | 173M | break; |
1324 | | |
1325 | 73.2M | if (plane_mask & 1) |
1326 | 73.2M | STEP_ROW(cursor[0], 0); |
1327 | 73.2M | if (plane_mask & 2) |
1328 | 73.2M | STEP_ROW(cursor[1], 1); |
1329 | 73.2M | if (plane_mask & 4) |
1330 | 73.2M | STEP_ROW(cursor[2], 2); |
1331 | 73.2M | if (plane_mask & 8) |
1332 | 73.2M | STEP_ROW(cursor[3], 3); |
1333 | 73.2M | } |
1334 | 173M | } |
1335 | | |
1336 | | /* |
1337 | | * Render the combined halftone for nplanes > 4. This routine assumes |
1338 | | * that we can form a gx_color_index value by the bitwise or index values |
1339 | | * for each of the individual components. |
1340 | | */ |
1341 | | static void |
1342 | | set_color_ht_gt_4(byte *dest_data, uint dest_raster, int px, int py, |
1343 | | int w, int h, int depth, int special, int num_planes, |
1344 | | gx_color_index plane_mask, gx_device *dev, |
1345 | | const color_values_pair_t *pvp, |
1346 | | gx_color_index colors[MAX_DCC_16], |
1347 | | const gx_const_strip_bitmap * sbits[MAX_DCC_16]) |
1348 | 36.4k | { |
1349 | 36.4k | int x, y; |
1350 | 36.4k | tile_cursor_t cursor[MAX_DCC]; |
1351 | 36.4k | int dbytes = depth >> 3; |
1352 | 36.4k | byte *dest_row = |
1353 | 36.4k | dest_data + dest_raster * (h - 1) + (w * depth) / 8; |
1354 | 36.4k | int pmin, pmax; |
1355 | 36.4k | gx_color_index base_color = 0; |
1356 | | |
1357 | | /* Compute the range of active planes. */ |
1358 | 36.4k | if (plane_mask == 0) |
1359 | 0 | pmin = 0, pmax = -1; |
1360 | 36.4k | else { |
1361 | 167k | for (pmin = 0; !((plane_mask >> pmin) & 1); ) |
1362 | 131k | ++pmin; |
1363 | 228k | for (pmax = 0; (plane_mask >> pmax) > 1; ) |
1364 | 192k | ++pmax; |
1365 | 36.4k | } |
1366 | 36.4k | if_debug6('h', |
1367 | 36.4k | "[h]color_ht_gt_4: x=%d y=%d w=%d h=%d plane_mask=0x%lu depth=%d\n", |
1368 | 36.4k | px, py, w, h, (ulong)plane_mask, depth); |
1369 | | |
1370 | | /* Do one-time cursor initialization. */ |
1371 | 36.4k | { |
1372 | 36.4k | int endx = w + px; |
1373 | 36.4k | int lasty = h - 1 + py; |
1374 | 36.4k | int i; |
1375 | | |
1376 | 133k | for (i = pmin; i <= pmax; ++i) |
1377 | 97.3k | if ((plane_mask >> i) & 1) |
1378 | 83.9k | init_tile_cursor(i, &cursor[i], sbits[i], endx, lasty); |
1379 | 36.4k | } |
1380 | | |
1381 | | /* Pre-load the color value for the non halftoning planes. */ |
1382 | 36.4k | { |
1383 | 36.4k | int i; |
1384 | | |
1385 | 281k | for (i = 0; i < num_planes; ++i) |
1386 | 245k | if ((~plane_mask >> i) & 1) |
1387 | 161k | base_color |= colors[2 * i]; |
1388 | 36.4k | } |
1389 | | |
1390 | | /* Now compute the actual tile. */ |
1391 | 139k | for (y = h; ; dest_row -= dest_raster) { |
1392 | 139k | byte *dest = dest_row; |
1393 | 139k | int i; |
1394 | | |
1395 | 139k | --y; |
1396 | 2.64M | for (x = w; x > 0;) { |
1397 | 2.50M | gx_color_index tcolor = base_color; |
1398 | | |
1399 | 8.98M | for (i = pmin; i <= pmax; ++i) |
1400 | 6.47M | if ((plane_mask >> i) & 1) { |
1401 | | /* Get the next bit from an individual mask. */ |
1402 | 5.43M | tile_cursor_t *ptc = &cursor[i]; |
1403 | 5.43M | byte tile_bit; |
1404 | | |
1405 | 5.44M | b: if (ptc->bit_shift < 8) |
1406 | 4.76M | tile_bit = *ptc->data >> ptc->bit_shift++; |
1407 | 678k | else if (ptc->data > ptc->row) { |
1408 | 669k | tile_bit = *--(ptc->data); |
1409 | 669k | ptc->bit_shift = 1; |
1410 | 669k | } else { |
1411 | | /* Wrap around. */ |
1412 | 8.98k | ptc->data += ptc->xbytes; |
1413 | 8.98k | ptc->bit_shift = 8 - ptc->xbits; |
1414 | 8.98k | goto b; |
1415 | 8.98k | } |
1416 | 5.43M | tcolor |= colors[2 * i + (tile_bit & 1)]; |
1417 | 5.43M | } |
1418 | 2.50M | --x; |
1419 | 2.50M | switch (dbytes) { |
1420 | 0 | case 0: /* 4 -- might be 2, but we don't support this */ |
1421 | 0 | if (x & 1) { /* odd nibble */ |
1422 | 0 | *--dest = (byte)tcolor; |
1423 | 0 | } else { /* even nibble */ |
1424 | 0 | *dest = (*dest & 0xf) + ((byte)tcolor << 4); |
1425 | 0 | } |
1426 | 0 | break; |
1427 | 0 | case 4: /* 32 */ |
1428 | 0 | dest[-4] = (byte)(tcolor >> 24); |
1429 | 0 | case 3: /* 24 */ |
1430 | 0 | dest[-3] = (byte)(tcolor >> 16); |
1431 | 0 | case 2: /* 16 */ |
1432 | 0 | dest[-2] = (byte)(tcolor >> 8); |
1433 | 2.50M | case 1: /* 8 */ |
1434 | 2.50M | dest[-1] = (byte)tcolor; |
1435 | 2.50M | dest -= dbytes; |
1436 | 2.50M | break; |
1437 | 2.50M | } |
1438 | 2.50M | } |
1439 | 139k | if (y == 0) |
1440 | 36.4k | break; |
1441 | 382k | for (i = pmin; i <= pmax; ++i) |
1442 | 279k | if ((plane_mask >> i) & 1) |
1443 | 279k | STEP_ROW(cursor[i], i); |
1444 | 103k | } |
1445 | 36.4k | } |