1 /* Copyright (C) 2001-2019 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 #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
mem_mapped2_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)50 mem_mapped2_fill_rectangle(gx_device * dev,
51 int x, int y, int w, int h, gx_color_index color)
52 {
53 gx_device_memory * const mdev = (gx_device_memory *)dev;
54
55 fit_fill(dev, x, y, w, h);
56 bits_fill_rectangle(scan_line_base(mdev, y), x << 1, mdev->raster,
57 tile_patterns[color], w << 1, h);
58 return 0;
59 }
60
61 /* Copy a bitmap. */
62 static int
mem_mapped2_copy_mono(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)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 {
68 gx_device_memory * const mdev = (gx_device_memory *)dev;
69 const byte *line;
70 int first_bit;
71 byte first_mask, b0, b1, bxor, left_mask, right_mask;
72 static const byte btab[4] = {0, 0x55, 0xaa, 0xff};
73 static const byte bmask[4] = {0xc0, 0x30, 0xc, 3};
74 static const byte lmask[4] = {0, 0xc0, 0xf0, 0xfc};
75
76 declare_scan_ptr(dest);
77
78 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
79 setup_rect(dest);
80 line = base + (sourcex >> 3);
81 first_bit = 0x80 >> (sourcex & 7);
82 first_mask = bmask[x & 3];
83 left_mask = lmask[x & 3];
84 right_mask = ~lmask[(x + w) & 3];
85 if ((x & 3) + w <= 3)
86 left_mask = right_mask = left_mask | right_mask;
87 b0 = btab[zero & 3];
88 b1 = btab[one & 3];
89 bxor = b0 ^ b1;
90 while (h-- > 0) {
91 register byte *pptr = (byte *) dest;
92 const byte *sptr = line;
93 register int sbyte = *sptr++;
94 register int bit = first_bit;
95 register byte mask = first_mask;
96 int count = w;
97
98 /* We have 4 cases, of which only 2 really matter. */
99 if (one != gx_no_color_index) {
100 if (zero != gx_no_color_index) { /* Copying an opaque bitmap. */
101 byte data = (*pptr & left_mask) | (b0 & ~left_mask);
102
103 for ( ; ; ) {
104 if (sbyte & bit)
105 data ^= bxor & mask;
106 if ((bit >>= 1) == 0)
107 bit = 0x80, sbyte = *sptr++;
108 if ((mask >>= 2) == 0)
109 mask = 0xc0, *pptr++ = data, data = b0;
110 if (--count <= 0)
111 break;
112 }
113 if (mask != 0xc0)
114 *pptr =
115 (*pptr & right_mask) | (data & ~right_mask);
116 } else { /* Filling a mask. */
117 for ( ; ; ) {
118 if (sbyte & bit)
119 *pptr = (*pptr & ~mask) | (b1 & mask);
120 if (--count <= 0)
121 break;
122 if ((bit >>= 1) == 0)
123 bit = 0x80, sbyte = *sptr++;
124 if ((mask >>= 2) == 0)
125 mask = 0xc0, pptr++;
126 }
127 }
128 } else { /* Some other case. */
129 for ( ; ; ) {
130 if (!(sbyte & bit)) {
131 if (zero != gx_no_color_index)
132 *pptr = (*pptr & ~mask) | (b0 & mask);
133 }
134 if (--count <= 0)
135 break;
136 if ((bit >>= 1) == 0)
137 bit = 0x80, sbyte = *sptr++;
138 if ((mask >>= 2) == 0)
139 mask = 0xc0, pptr++;
140 }
141 }
142 line += sraster;
143 inc_ptr(dest, draster);
144 }
145 return 0;
146 }
147
148 /* Copy a color bitmap. */
149 static int
mem_mapped2_copy_color(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h)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 {
154 int code;
155
156 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 dev->width <<= 1;
160 code = (*dev_proc(&mem_mono_device, copy_mono))
161 (dev, base, sourcex << 1, sraster, id,
162 x << 1, y, w << 1, h, (gx_color_index) 0, (gx_color_index) 1);
163 /* Restore the correct width. */
164 dev->width >>= 1;
165 return code;
166 }
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
mem2_word_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)189 mem2_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
190 gx_color_index color)
191 {
192 gx_device_memory * const mdev = (gx_device_memory *)dev;
193 byte *base;
194 uint raster;
195
196 fit_fill(dev, x, y, w, h);
197 base = scan_line_base(mdev, y);
198 raster = mdev->raster;
199 mem_swap_byte_rect(base, raster, x << 1, w << 1, h, true);
200 bits_fill_rectangle(base, x << 1, raster,
201 tile_patterns[color], w << 1, h);
202 mem_swap_byte_rect(base, raster, x << 1, w << 1, h, true);
203 return 0;
204 }
205
206 /* Copy a bitmap. */
207 static int
mem2_word_copy_mono(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)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 {
213 gx_device_memory * const mdev = (gx_device_memory *)dev;
214 byte *row;
215 uint raster;
216 bool store;
217
218 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
219 row = scan_line_base(mdev, y);
220 raster = mdev->raster;
221 store = (zero != gx_no_color_index && one != gx_no_color_index);
222 mem_swap_byte_rect(row, raster, x << 1, w << 1, h, store);
223 mem_mapped2_copy_mono(dev, base, sourcex, sraster, id,
224 x, y, w, h, zero, one);
225 mem_swap_byte_rect(row, raster, x << 1, w << 1, h, false);
226 return 0;
227 }
228
229 /* Copy a color bitmap. */
230 static int
mem2_word_copy_color(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h)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 {
235 int code;
236
237 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 dev->width <<= 1;
241 code = (*dev_proc(&mem_mono_word_device, copy_mono))
242 (dev, base, sourcex << 1, sraster, id,
243 x << 1, y, w << 1, h, (gx_color_index) 0, (gx_color_index) 1);
244 /* Restore the correct width. */
245 dev->width >>= 1;
246 return code;
247 }
248
249 #endif /* !ARCH_IS_BIG_ENDIAN */
250