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