/src/ghostpdl/base/gdevm2.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 | | /* 2-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 | | #define fpat(byt) mono_fill_make_pattern(byt) |
28 | | |
29 | | /* Procedures */ |
30 | | declare_mem_procs(mem_mapped2_copy_mono, mem_mapped2_copy_color, mem_mapped2_fill_rectangle); |
31 | | |
32 | | /* The device descriptor. */ |
33 | | const gx_device_memory mem_mapped2_device = |
34 | | mem_device("image2", 2, 0, mem_dev_initialize_device_procs); |
35 | | |
36 | | const gdev_mem_functions gdev_mem_fns_2 = |
37 | | { |
38 | | mem_mapped_map_rgb_color, |
39 | | mem_mapped_map_color_rgb, |
40 | | mem_mapped2_fill_rectangle, |
41 | | mem_mapped2_copy_mono, |
42 | | mem_mapped2_copy_color, |
43 | | gx_default_copy_alpha, |
44 | | gx_default_strip_tile_rectangle, |
45 | | mem_gray_strip_copy_rop2, |
46 | | mem_get_bits_rectangle |
47 | | }; |
48 | | |
49 | | /* Convert x coordinate to byte offset in scan line. */ |
50 | | #undef x_to_byte |
51 | 0 | #define x_to_byte(x) ((x) >> 2) |
52 | | |
53 | | /* Define the 2-bit fill patterns. */ |
54 | | static const mono_fill_chunk tile_patterns[4] = { |
55 | | fpat(0x00), fpat(0x55), fpat(0xaa), fpat(0xff) |
56 | | }; |
57 | | |
58 | | /* Fill a rectangle with a color. */ |
59 | | static int |
60 | | mem_mapped2_fill_rectangle(gx_device * dev, |
61 | | int x, int y, int w, int h, gx_color_index color) |
62 | 0 | { |
63 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
64 | |
|
65 | 0 | fit_fill(dev, x, y, w, h); |
66 | 0 | bits_fill_rectangle(scan_line_base(mdev, y), x << 1, mdev->raster, |
67 | 0 | tile_patterns[color], w << 1, h); |
68 | 0 | return 0; |
69 | 0 | } |
70 | | |
71 | | /* Copy a bitmap. */ |
72 | | static int |
73 | | mem_mapped2_copy_mono(gx_device * dev, |
74 | | const byte * base, int sourcex, int sraster, |
75 | | gx_bitmap_id id, int x, int y, int w, int h, |
76 | | gx_color_index zero, gx_color_index one) |
77 | 0 | { |
78 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
79 | 0 | const byte *line; |
80 | 0 | int first_bit; |
81 | 0 | byte first_mask, b0, b1, bxor, left_mask, right_mask; |
82 | 0 | static const byte btab[4] = {0, 0x55, 0xaa, 0xff}; |
83 | 0 | static const byte bmask[4] = {0xc0, 0x30, 0xc, 3}; |
84 | 0 | static const byte lmask[4] = {0, 0xc0, 0xf0, 0xfc}; |
85 | |
|
86 | 0 | declare_scan_ptr(dest); |
87 | |
|
88 | 0 | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
89 | 0 | setup_rect(dest); |
90 | 0 | line = base + (sourcex >> 3); |
91 | 0 | first_bit = 0x80 >> (sourcex & 7); |
92 | 0 | first_mask = bmask[x & 3]; |
93 | 0 | left_mask = lmask[x & 3]; |
94 | 0 | right_mask = ~lmask[(x + w) & 3]; |
95 | 0 | if ((x & 3) + w <= 3) |
96 | 0 | left_mask = right_mask = left_mask | right_mask; |
97 | 0 | b0 = btab[zero & 3]; |
98 | 0 | b1 = btab[one & 3]; |
99 | 0 | bxor = b0 ^ b1; |
100 | 0 | while (h-- > 0) { |
101 | 0 | register byte *pptr = (byte *) dest; |
102 | 0 | const byte *sptr = line; |
103 | 0 | register int sbyte = *sptr++; |
104 | 0 | register int bit = first_bit; |
105 | 0 | register byte mask = first_mask; |
106 | 0 | int count = w; |
107 | | |
108 | | /* We have 4 cases, of which only 2 really matter. */ |
109 | 0 | if (one != gx_no_color_index) { |
110 | 0 | if (zero != gx_no_color_index) { /* Copying an opaque bitmap. */ |
111 | 0 | byte data = (*pptr & left_mask) | (b0 & ~left_mask); |
112 | |
|
113 | 0 | for ( ; ; ) { |
114 | 0 | if (sbyte & bit) |
115 | 0 | data ^= bxor & mask; |
116 | 0 | if ((bit >>= 1) == 0) |
117 | 0 | bit = 0x80, sbyte = *sptr++; |
118 | 0 | if ((mask >>= 2) == 0) |
119 | 0 | mask = 0xc0, *pptr++ = data, data = b0; |
120 | 0 | if (--count <= 0) |
121 | 0 | break; |
122 | 0 | } |
123 | 0 | if (mask != 0xc0) |
124 | 0 | *pptr = |
125 | 0 | (*pptr & right_mask) | (data & ~right_mask); |
126 | 0 | } else { /* Filling a mask. */ |
127 | 0 | for ( ; ; ) { |
128 | 0 | if (sbyte & bit) |
129 | 0 | *pptr = (*pptr & ~mask) | (b1 & mask); |
130 | 0 | if (--count <= 0) |
131 | 0 | break; |
132 | 0 | if ((bit >>= 1) == 0) |
133 | 0 | bit = 0x80, sbyte = *sptr++; |
134 | 0 | if ((mask >>= 2) == 0) |
135 | 0 | mask = 0xc0, pptr++; |
136 | 0 | } |
137 | 0 | } |
138 | 0 | } else { /* Some other case. */ |
139 | 0 | for ( ; ; ) { |
140 | 0 | if (!(sbyte & bit)) { |
141 | 0 | if (zero != gx_no_color_index) |
142 | 0 | *pptr = (*pptr & ~mask) | (b0 & mask); |
143 | 0 | } |
144 | 0 | if (--count <= 0) |
145 | 0 | break; |
146 | 0 | if ((bit >>= 1) == 0) |
147 | 0 | bit = 0x80, sbyte = *sptr++; |
148 | 0 | if ((mask >>= 2) == 0) |
149 | 0 | mask = 0xc0, pptr++; |
150 | 0 | } |
151 | 0 | } |
152 | 0 | line += sraster; |
153 | 0 | inc_ptr(dest, draster); |
154 | 0 | } |
155 | 0 | return 0; |
156 | 0 | } |
157 | | |
158 | | /* Copy a color bitmap. */ |
159 | | static int |
160 | | mem_mapped2_copy_color(gx_device * dev, |
161 | | const byte * base, int sourcex, int sraster, |
162 | | gx_bitmap_id id, int x, int y, int w, int h) |
163 | 0 | { |
164 | 0 | int code; |
165 | |
|
166 | 0 | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
167 | | /* Use monobit copy_mono. */ |
168 | | /* Patch the width in the device temporarily. */ |
169 | 0 | dev->width <<= 1; |
170 | 0 | code = mem_mono_copy_mono(dev, base, sourcex << 1, sraster, id, |
171 | 0 | x << 1, y, w << 1, h, |
172 | 0 | (gx_color_index) 0, (gx_color_index) 1); |
173 | | /* Restore the correct width. */ |
174 | 0 | dev->width >>= 1; |
175 | 0 | return code; |
176 | 0 | } |
177 | | |
178 | | /* ================ "Word"-oriented device ================ */ |
179 | | |
180 | | /* Note that on a big-endian machine, this is the same as the */ |
181 | | /* standard byte-oriented-device. */ |
182 | | |
183 | | #if !ARCH_IS_BIG_ENDIAN |
184 | | |
185 | | /* Procedures */ |
186 | | declare_mem_procs(mem2_word_copy_mono, mem2_word_copy_color, mem2_word_fill_rectangle); |
187 | | |
188 | | /* Here is the device descriptor. */ |
189 | | const gx_device_memory mem_mapped2_word_device = |
190 | | mem_device("image2w", 2, 0, mem_word_dev_initialize_device_procs); |
191 | | |
192 | | const gdev_mem_functions gdev_mem_fns_2w = |
193 | | { |
194 | | mem_mapped_map_rgb_color, |
195 | | mem_mapped_map_color_rgb, |
196 | | mem2_word_fill_rectangle, |
197 | | mem2_word_copy_mono, |
198 | | mem2_word_copy_color, |
199 | | gx_default_copy_alpha, |
200 | | gx_default_strip_tile_rectangle, |
201 | | gx_no_strip_copy_rop2, |
202 | | mem_word_get_bits_rectangle |
203 | | }; |
204 | | |
205 | | /* Fill a rectangle with a color. */ |
206 | | static int |
207 | | mem2_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h, |
208 | | gx_color_index color) |
209 | 0 | { |
210 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
211 | 0 | byte *base; |
212 | 0 | size_t raster; |
213 | |
|
214 | 0 | fit_fill(dev, x, y, w, h); |
215 | 0 | base = scan_line_base(mdev, y); |
216 | 0 | raster = mdev->raster; |
217 | 0 | mem_swap_byte_rect(base, raster, x << 1, w << 1, h, true); |
218 | 0 | bits_fill_rectangle(base, x << 1, raster, |
219 | 0 | tile_patterns[color], w << 1, h); |
220 | 0 | mem_swap_byte_rect(base, raster, x << 1, w << 1, h, true); |
221 | 0 | return 0; |
222 | 0 | } |
223 | | |
224 | | /* Copy a bitmap. */ |
225 | | static int |
226 | | mem2_word_copy_mono(gx_device * dev, |
227 | | const byte * base, int sourcex, int sraster, |
228 | | gx_bitmap_id id, int x, int y, int w, int h, |
229 | | gx_color_index zero, gx_color_index one) |
230 | 0 | { |
231 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
232 | 0 | byte *row; |
233 | 0 | size_t raster; |
234 | 0 | bool store; |
235 | |
|
236 | 0 | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
237 | 0 | row = scan_line_base(mdev, y); |
238 | 0 | raster = mdev->raster; |
239 | 0 | store = (zero != gx_no_color_index && one != gx_no_color_index); |
240 | 0 | mem_swap_byte_rect(row, raster, x << 1, w << 1, h, store); |
241 | 0 | mem_mapped2_copy_mono(dev, base, sourcex, sraster, id, |
242 | 0 | x, y, w, h, zero, one); |
243 | 0 | mem_swap_byte_rect(row, raster, x << 1, w << 1, h, false); |
244 | 0 | return 0; |
245 | 0 | } |
246 | | |
247 | | /* Copy a color bitmap. */ |
248 | | static int |
249 | | mem2_word_copy_color(gx_device * dev, |
250 | | const byte * base, int sourcex, int sraster, |
251 | | gx_bitmap_id id, int x, int y, int w, int h) |
252 | 0 | { |
253 | 0 | int code; |
254 | |
|
255 | 0 | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
256 | | /* Use monobit copy_mono. */ |
257 | | /* Patch the width in the device temporarily. */ |
258 | 0 | dev->width <<= 1; |
259 | 0 | code = gdev_mem_word_functions_for_bits(1)->copy_mono |
260 | 0 | (dev, base, sourcex << 1, sraster, id, |
261 | 0 | x << 1, y, w << 1, h, (gx_color_index) 0, (gx_color_index) 1); |
262 | | /* Restore the correct width. */ |
263 | 0 | dev->width >>= 1; |
264 | 0 | return code; |
265 | 0 | } |
266 | | |
267 | | #endif /* !ARCH_IS_BIG_ENDIAN */ |