/src/ghostpdl/base/gdevm32.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 | | /* 32-bit-per-pixel "memory" (stored bitmap) device */ |
17 | | #include "memory_.h" |
18 | | #include "gx.h" |
19 | | #include "gxdevice.h" |
20 | | #include "gxdevmem.h" /* semi-public definitions */ |
21 | | #include "gdevmem.h" /* private definitions */ |
22 | | |
23 | | /* ================ Standard (byte-oriented) device ================ */ |
24 | | |
25 | | #undef chunk |
26 | | #define chunk byte |
27 | | |
28 | | /* Procedures */ |
29 | | declare_mem_procs(mem_true32_copy_mono, mem_true32_copy_color, mem_true32_fill_rectangle); |
30 | | |
31 | | /* The device descriptor. */ |
32 | | const gx_device_memory mem_true32_device = |
33 | | mem_device("image32", 24, 8, mem_dev_initialize_device_procs); |
34 | | |
35 | | const gdev_mem_functions gdev_mem_fns_32 = |
36 | | { |
37 | | gx_default_map_rgb_color, |
38 | | gx_default_map_color_rgb, |
39 | | mem_true32_fill_rectangle, |
40 | | mem_true32_copy_mono, |
41 | | mem_true32_copy_color, |
42 | | gx_default_copy_alpha, |
43 | | gx_default_strip_tile_rectangle, |
44 | | mem_default_strip_copy_rop2, |
45 | | mem_get_bits_rectangle |
46 | | }; |
47 | | |
48 | | /* Convert x coordinate to byte offset in scan line. */ |
49 | | #undef x_to_byte |
50 | 0 | #define x_to_byte(x) ((x) << 2) |
51 | | |
52 | | /* Swap the bytes of a color if needed. */ |
53 | | #define color_swap_bytes(color)\ |
54 | 0 | ((((color) >> 24) & 0xff) + (((color) >> 8) & 0xff00) +\ |
55 | 0 | (((color) & 0xff00) << 8) + ((color) << 24)) |
56 | | #if ARCH_IS_BIG_ENDIAN |
57 | | # define arrange_bytes(color) (color) |
58 | | #else |
59 | 0 | # define arrange_bytes(color) color_swap_bytes(color) |
60 | | #endif |
61 | | |
62 | | /* Fill a rectangle with a color. */ |
63 | | static int |
64 | | mem_true32_fill_rectangle(gx_device * dev, |
65 | | int x, int y, int w, int h, gx_color_index color) |
66 | 0 | { |
67 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
68 | 0 | bits32 a_color; |
69 | |
|
70 | 0 | declare_scan_ptr(dest); |
71 | |
|
72 | 0 | fit_fill(dev, x, y, w, h); |
73 | 0 | a_color = arrange_bytes(color); |
74 | 0 | setup_rect(dest); |
75 | 0 | if (w <= 4) |
76 | 0 | switch (w) { |
77 | | /*case 0: *//* not possible */ |
78 | 0 | #define dest32 ((bits32 *)dest) |
79 | 0 | case 1: |
80 | 0 | do { |
81 | 0 | dest32[0] = a_color; |
82 | 0 | inc_ptr(dest, draster); |
83 | 0 | } |
84 | 0 | while (--h > 0); |
85 | 0 | break; |
86 | 0 | case 2: |
87 | 0 | do { |
88 | 0 | dest32[1] = dest32[0] = a_color; |
89 | 0 | inc_ptr(dest, draster); |
90 | 0 | } |
91 | 0 | while (--h > 0); |
92 | 0 | break; |
93 | 0 | case 3: |
94 | 0 | do { |
95 | 0 | dest32[2] = dest32[1] = dest32[0] = a_color; |
96 | 0 | inc_ptr(dest, draster); |
97 | 0 | } |
98 | 0 | while (--h > 0); |
99 | 0 | break; |
100 | 0 | case 4: |
101 | 0 | do { |
102 | 0 | dest32[3] = dest32[2] = dest32[1] = dest32[0] = a_color; |
103 | 0 | inc_ptr(dest, draster); |
104 | 0 | } |
105 | 0 | while (--h > 0); |
106 | 0 | break; |
107 | 0 | default: /* not possible */ |
108 | 0 | ; |
109 | 0 | } else if (a_color == 0) |
110 | 0 | do { |
111 | 0 | memset(dest, 0, w << 2); |
112 | 0 | inc_ptr(dest, draster); |
113 | 0 | } |
114 | 0 | while (--h > 0); |
115 | 0 | else |
116 | 0 | do { |
117 | 0 | bits32 *pptr = dest32; |
118 | 0 | int cnt = w; |
119 | |
|
120 | 0 | do { |
121 | 0 | pptr[3] = pptr[2] = pptr[1] = pptr[0] = a_color; |
122 | 0 | pptr += 4; |
123 | 0 | } |
124 | 0 | while ((cnt -= 4) > 4); |
125 | 0 | do { |
126 | 0 | *pptr++ = a_color; |
127 | 0 | } while (--cnt > 0); |
128 | 0 | inc_ptr(dest, draster); |
129 | 0 | } |
130 | 0 | while (--h > 0); |
131 | 0 | #undef dest32 |
132 | 0 | return 0; |
133 | 0 | } |
134 | | |
135 | | /* Copy a monochrome bitmap. */ |
136 | | static int |
137 | | mem_true32_copy_mono(gx_device * dev, |
138 | | const byte * base, int sourcex, int sraster, gx_bitmap_id id, |
139 | | int x, int y, int w, int h, gx_color_index zero, gx_color_index one) |
140 | 0 | { |
141 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
142 | 0 | bits32 a_zero = arrange_bytes(zero); |
143 | 0 | bits32 a_one = arrange_bytes(one); |
144 | 0 | const byte *line; |
145 | |
|
146 | 0 | declare_scan_ptr(dest); |
147 | 0 | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
148 | 0 | setup_rect(dest); |
149 | 0 | line = base + (sourcex >> 3); |
150 | 0 | if (zero == gx_no_color_index) { |
151 | 0 | int first_bit = sourcex & 7; |
152 | 0 | int w_first = min(w, 8 - first_bit); |
153 | 0 | int w_rest = w - w_first; |
154 | |
|
155 | 0 | if (one == gx_no_color_index) |
156 | 0 | return 0; |
157 | | /* |
158 | | * There are no halftones, so this case -- characters -- |
159 | | * is the only common one. |
160 | | */ |
161 | 0 | while (h-- > 0) { |
162 | 0 | bits32 *pptr = (bits32 *) dest; |
163 | 0 | const byte *sptr = line; |
164 | 0 | int sbyte = (*sptr++ << first_bit) & 0xff; |
165 | 0 | int count = w_first; |
166 | |
|
167 | 0 | #ifdef PACIFY_VALGRIND |
168 | 0 | sbyte &= 0x100-(0x100>>w_first); |
169 | 0 | #endif |
170 | |
|
171 | 0 | if (sbyte) |
172 | 0 | do { |
173 | 0 | if (sbyte & 0x80) |
174 | 0 | *pptr = a_one; |
175 | 0 | sbyte <<= 1; |
176 | 0 | pptr++; |
177 | 0 | } |
178 | 0 | while (--count > 0); |
179 | 0 | else |
180 | 0 | pptr += count; |
181 | 0 | for (count = w_rest; count >= 8; count -= 8, pptr += 8) { |
182 | 0 | sbyte = *sptr++; |
183 | 0 | if (sbyte) { |
184 | 0 | if (sbyte & 0x80) pptr[0] = a_one; |
185 | 0 | if (sbyte & 0x40) pptr[1] = a_one; |
186 | 0 | if (sbyte & 0x20) pptr[2] = a_one; |
187 | 0 | if (sbyte & 0x10) pptr[3] = a_one; |
188 | 0 | if (sbyte & 0x08) pptr[4] = a_one; |
189 | 0 | if (sbyte & 0x04) pptr[5] = a_one; |
190 | 0 | if (sbyte & 0x02) pptr[6] = a_one; |
191 | 0 | if (sbyte & 0x01) pptr[7] = a_one; |
192 | 0 | } |
193 | 0 | } |
194 | 0 | if (count) { |
195 | 0 | sbyte = *sptr; |
196 | 0 | do { |
197 | 0 | if (sbyte & 0x80) |
198 | 0 | *pptr = a_one; |
199 | 0 | sbyte <<= 1; |
200 | 0 | pptr++; |
201 | 0 | } |
202 | 0 | while (--count > 0); |
203 | 0 | } |
204 | 0 | line += sraster; |
205 | 0 | inc_ptr(dest, draster); |
206 | 0 | } |
207 | 0 | } else { /* zero != gx_no_color_index */ |
208 | 0 | int first_bit = 0x80 >> (sourcex & 7); |
209 | |
|
210 | 0 | while (h-- > 0) { |
211 | 0 | bits32 *pptr = (bits32 *) dest; |
212 | 0 | const byte *sptr = line; |
213 | 0 | int sbyte = *sptr++; |
214 | 0 | int bit = first_bit; |
215 | 0 | int count = w; |
216 | |
|
217 | 0 | do { |
218 | 0 | if (sbyte & bit) { |
219 | 0 | if (one != gx_no_color_index) |
220 | 0 | *pptr = a_one; |
221 | 0 | } else |
222 | 0 | *pptr = a_zero; |
223 | 0 | if ((bit >>= 1) == 0) |
224 | 0 | bit = 0x80, sbyte = *sptr++; |
225 | 0 | pptr++; |
226 | 0 | } |
227 | 0 | while (--count > 0); |
228 | 0 | line += sraster; |
229 | 0 | inc_ptr(dest, draster); |
230 | 0 | } |
231 | 0 | } |
232 | 0 | return 0; |
233 | 0 | } |
234 | | |
235 | | /* Copy a color bitmap. */ |
236 | | static int |
237 | | mem_true32_copy_color(gx_device * dev, |
238 | | const byte * base, int sourcex, int sraster, gx_bitmap_id id, |
239 | | int x, int y, int w, int h) |
240 | 0 | { |
241 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
242 | |
|
243 | 0 | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
244 | 0 | mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h); |
245 | 0 | return 0; |
246 | 0 | } |
247 | | |
248 | | /* ================ "Word"-oriented device ================ */ |
249 | | |
250 | | /* Note that on a big-endian machine, this is the same as the */ |
251 | | /* standard byte-oriented-device. */ |
252 | | |
253 | | #if !ARCH_IS_BIG_ENDIAN |
254 | | |
255 | | /* Procedures */ |
256 | | declare_mem_procs(mem32_word_copy_mono, mem32_word_copy_color, mem32_word_fill_rectangle); |
257 | | |
258 | | /* Here is the device descriptor. */ |
259 | | const gx_device_memory mem_true32_word_device = |
260 | | mem_device("image32w", 24, 8, mem_word_dev_initialize_device_procs); |
261 | | |
262 | | const gdev_mem_functions gdev_mem_fns_32w = |
263 | | { |
264 | | gx_default_map_rgb_color, |
265 | | gx_default_map_color_rgb, |
266 | | mem32_word_fill_rectangle, |
267 | | mem32_word_copy_mono, |
268 | | mem32_word_copy_color, |
269 | | gx_default_copy_alpha, |
270 | | gx_default_strip_tile_rectangle, |
271 | | gx_no_strip_copy_rop2, |
272 | | mem_word_get_bits_rectangle |
273 | | }; |
274 | | |
275 | | /* Fill a rectangle with a color. */ |
276 | | static int |
277 | | mem32_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h, |
278 | | gx_color_index color) |
279 | 0 | { |
280 | 0 | return mem_true32_fill_rectangle(dev, x, y, w, h, |
281 | 0 | color_swap_bytes(color)); |
282 | 0 | } |
283 | | |
284 | | /* Copy a bitmap. */ |
285 | | static int |
286 | | mem32_word_copy_mono(gx_device * dev, |
287 | | const byte * base, int sourcex, int sraster, gx_bitmap_id id, |
288 | | int x, int y, int w, int h, gx_color_index zero, gx_color_index one) |
289 | 0 | { |
290 | 0 | return mem_true32_copy_mono(dev, base, sourcex, sraster, id, |
291 | 0 | x, y, w, h, color_swap_bytes(zero), |
292 | 0 | color_swap_bytes(one)); |
293 | 0 | } |
294 | | |
295 | | /* Copy a color bitmap. */ |
296 | | static int |
297 | | mem32_word_copy_color(gx_device * dev, |
298 | | const byte * base, int sourcex, int sraster, gx_bitmap_id id, |
299 | | int x, int y, int w, int h) |
300 | 0 | { |
301 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
302 | 0 | byte *row; |
303 | 0 | size_t raster; |
304 | |
|
305 | 0 | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
306 | 0 | row = scan_line_base(mdev, y); |
307 | 0 | raster = mdev->raster; |
308 | 0 | bytes_copy_rectangle(row + (x << 2), raster, base + (sourcex << 2), |
309 | 0 | sraster, w << 2, h); |
310 | 0 | mem_swap_byte_rect(row, raster, x << 5, w << 5, h, false); |
311 | 0 | return 0; |
312 | 0 | } |
313 | | |
314 | | #endif /* !ARCH_IS_BIG_ENDIAN */ |