xref: /plan9/sys/src/cmd/gs/src/gdevm32.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1 /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2 
3    This file is part of Aladdin Ghostscript.
4 
5    Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
6    or distributor accepts any responsibility for the consequences of using it,
7    or for whether it serves any particular purpose or works at all, unless he
8    or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
9    License (the "License") for full details.
10 
11    Every copy of Aladdin Ghostscript must include a copy of the License,
12    normally in a plain ASCII text file named PUBLIC.  The License grants you
13    the right to copy, modify and redistribute Aladdin Ghostscript, but only
14    under certain conditions described in the License.  Among other things, the
15    License requires that the copyright notice and this notice be preserved on
16    all copies.
17  */
18 
19 /*$Id: gdevm32.c,v 1.1 2000/03/09 08:40:41 lpd Exp $ */
20 /* 32-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 
32 /* Procedures */
33 declare_mem_procs(mem_true32_copy_mono, mem_true32_copy_color, mem_true32_fill_rectangle);
34 
35 /* The device descriptor. */
36 const gx_device_memory mem_true32_device =
37 mem_full_device("image32", 24, 8, mem_open,
38 		gx_default_map_rgb_color, gx_default_map_color_rgb,
39      mem_true32_copy_mono, mem_true32_copy_color, mem_true32_fill_rectangle,
40 	    gx_default_cmyk_map_cmyk_color, gx_default_strip_tile_rectangle,
41 		mem_default_strip_copy_rop, mem_get_bits_rectangle);
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 /* Swap the bytes of a color if needed. */
48 #define color_swap_bytes(color)\
49   (((color) >> 24) + (((color) >> 8) & 0xff00) +\
50    (((color) & 0xff00) << 8) + ((color) << 24))
51 #if arch_is_big_endian
52 #  define arrange_bytes(color) (color)
53 #else
54 #  define arrange_bytes(color) color_swap_bytes(color)
55 #endif
56 
57 /* Fill a rectangle with a color. */
58 private int
59 mem_true32_fill_rectangle(gx_device * dev,
60 			  int x, int y, int w, int h, gx_color_index color)
61 {
62     gx_device_memory * const mdev = (gx_device_memory *)dev;
63     bits32 a_color;
64 
65     declare_scan_ptr(dest);
66 
67     fit_fill(dev, x, y, w, h);
68     a_color = arrange_bytes(color);
69     setup_rect(dest);
70     if (w <= 4)
71 	switch (w) {
72 		/*case 0: *//* not possible */
73 #define dest32 ((bits32 *)dest)
74 	    case 1:
75 		do {
76 		    dest32[0] = a_color;
77 		    inc_ptr(dest, draster);
78 		}
79 		while (--h > 0);
80 		break;
81 	    case 2:
82 		do {
83 		    dest32[1] = dest32[0] = a_color;
84 		    inc_ptr(dest, draster);
85 		}
86 		while (--h > 0);
87 		break;
88 	    case 3:
89 		do {
90 		    dest32[2] = dest32[1] = dest32[0] = a_color;
91 		    inc_ptr(dest, draster);
92 		}
93 		while (--h > 0);
94 		break;
95 	    case 4:
96 		do {
97 		    dest32[3] = dest32[2] = dest32[1] = dest32[0] = a_color;
98 		    inc_ptr(dest, draster);
99 		}
100 		while (--h > 0);
101 		break;
102 	    default:		/* not possible */
103 		;
104     } else if (a_color == 0)
105 	do {
106 	    memset(dest, 0, w << 2);
107 	    inc_ptr(dest, draster);
108 	}
109 	while (--h > 0);
110     else
111 	do {
112 	    bits32 *pptr = dest32;
113 	    int cnt = w;
114 
115 	    do {
116 		pptr[3] = pptr[2] = pptr[1] = pptr[0] = a_color;
117 		pptr += 4;
118 	    }
119 	    while ((cnt -= 4) > 4);
120 	    do {
121 		*pptr++ = a_color;
122 	    } while (--cnt > 0);
123 	    inc_ptr(dest, draster);
124 	}
125 	while (--h > 0);
126 #undef dest32
127     return 0;
128 }
129 
130 /* Copy a monochrome bitmap. */
131 private int
132 mem_true32_copy_mono(gx_device * dev,
133 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
134 	int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
135 {
136     gx_device_memory * const mdev = (gx_device_memory *)dev;
137     bits32 a_zero = arrange_bytes(zero);
138     bits32 a_one = arrange_bytes(one);
139     const byte *line;
140 
141     declare_scan_ptr(dest);
142     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
143     setup_rect(dest);
144     line = base + (sourcex >> 3);
145     if (zero == gx_no_color_index) {
146 	int first_bit = sourcex & 7;
147 	int w_first = min(w, 8 - first_bit);
148 	int w_rest = w - w_first;
149 
150 	if (one == gx_no_color_index)
151 	    return 0;
152 	/*
153 	 * There are no halftones, so this case -- characters --
154 	 * is the only common one.
155 	 */
156 	while (h-- > 0) {
157 	    bits32 *pptr = (bits32 *) dest;
158 	    const byte *sptr = line;
159 	    int sbyte = (*sptr++ << first_bit) & 0xff;
160 	    int count = w_first;
161 
162 	    if (sbyte)
163 		do {
164 		    if (sbyte & 0x80)
165 			*pptr = a_one;
166 		    sbyte <<= 1;
167 		    pptr++;
168 		}
169 		while (--count > 0);
170 	    else
171 		pptr += count;
172 	    for (count = w_rest; count >= 8; count -= 8, pptr += 8) {
173 		sbyte = *sptr++;
174 		if (sbyte) {
175 		    if (sbyte & 0x80) pptr[0] = a_one;
176 		    if (sbyte & 0x40) pptr[1] = a_one;
177 		    if (sbyte & 0x20) pptr[2] = a_one;
178 		    if (sbyte & 0x10) pptr[3] = a_one;
179 		    if (sbyte & 0x08) pptr[4] = a_one;
180 		    if (sbyte & 0x04) pptr[5] = a_one;
181 		    if (sbyte & 0x02) pptr[6] = a_one;
182 		    if (sbyte & 0x01) pptr[7] = a_one;
183 		}
184 	    }
185 	    if (count) {
186 		sbyte = *sptr;
187 		do {
188 		    if (sbyte & 0x80)
189 			*pptr = a_one;
190 		    sbyte <<= 1;
191 		    pptr++;
192 		}
193 		while (--count > 0);
194 	    }
195 	    line += sraster;
196 	    inc_ptr(dest, draster);
197 	}
198     } else {			/* zero != gx_no_color_index */
199 	int first_bit = 0x80 >> (sourcex & 7);
200 
201 	while (h-- > 0) {
202 	    bits32 *pptr = (bits32 *) dest;
203 	    const byte *sptr = line;
204 	    int sbyte = *sptr++;
205 	    int bit = first_bit;
206 	    int count = w;
207 
208 	    do {
209 		if (sbyte & bit) {
210 		    if (one != gx_no_color_index)
211 			*pptr = a_one;
212 		} else
213 		    *pptr = a_zero;
214 		if ((bit >>= 1) == 0)
215 		    bit = 0x80, sbyte = *sptr++;
216 		pptr++;
217 	    }
218 	    while (--count > 0);
219 	    line += sraster;
220 	    inc_ptr(dest, draster);
221 	}
222     }
223     return 0;
224 }
225 
226 /* Copy a color bitmap. */
227 private int
228 mem_true32_copy_color(gx_device * dev,
229 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
230 		      int x, int y, int w, int h)
231 {
232     gx_device_memory * const mdev = (gx_device_memory *)dev;
233 
234     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
235     mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
236     return 0;
237 }
238 
239 /* ================ "Word"-oriented device ================ */
240 
241 /* Note that on a big-endian machine, this is the same as the */
242 /* standard byte-oriented-device. */
243 
244 #if !arch_is_big_endian
245 
246 /* Procedures */
247 declare_mem_procs(mem32_word_copy_mono, mem32_word_copy_color, mem32_word_fill_rectangle);
248 
249 /* Here is the device descriptor. */
250 const gx_device_memory mem_true32_word_device =
251 mem_full_device("image32w", 24, 8, mem_open,
252 		gx_default_map_rgb_color, gx_default_map_color_rgb,
253      mem32_word_copy_mono, mem32_word_copy_color, mem32_word_fill_rectangle,
254 	    gx_default_cmyk_map_cmyk_color, gx_default_strip_tile_rectangle,
255 		gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
256 
257 /* Fill a rectangle with a color. */
258 private int
259 mem32_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
260 			  gx_color_index color)
261 {
262     return mem_true32_fill_rectangle(dev, x, y, w, h,
263 				     color_swap_bytes(color));
264 }
265 
266 /* Copy a bitmap. */
267 private int
268 mem32_word_copy_mono(gx_device * dev,
269 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
270 	int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
271 {
272     return mem_true32_copy_mono(dev, base, sourcex, sraster, id,
273 				x, y, w, h, color_swap_bytes(zero),
274 				color_swap_bytes(one));
275 }
276 
277 /* Copy a color bitmap. */
278 private int
279 mem32_word_copy_color(gx_device * dev,
280 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
281 		      int x, int y, int w, int h)
282 {
283     gx_device_memory * const mdev = (gx_device_memory *)dev;
284     byte *row;
285     uint raster;
286 
287     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
288     row = scan_line_base(mdev, y);
289     raster = mdev->raster;
290     bytes_copy_rectangle(row + (x << 2), raster, base + (sourcex << 2),
291 			 sraster, w << 2, h);
292     mem_swap_byte_rect(row, raster, x << 5, w << 5, h, false);
293     return 0;
294 }
295 
296 #endif /* !arch_is_big_endian */
297