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