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