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