xref: /plan9/sys/src/cmd/gs/src/gdevm32.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: gdevm32.c,v 1.5 2003/05/24 17:19:58 dan Exp $ */
18 /* 32-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 
30 /* Procedures */
31 declare_mem_procs(mem_true32_copy_mono, mem_true32_copy_color, mem_true32_fill_rectangle);
32 
33 /* The device descriptor. */
34 const gx_device_memory mem_true32_device =
35 mem_full_device("image32", 24, 8, mem_open,
36 		gx_default_map_rgb_color, gx_default_map_color_rgb,
37      mem_true32_copy_mono, mem_true32_copy_color, mem_true32_fill_rectangle,
38 	    gx_default_cmyk_map_cmyk_color, gx_default_strip_tile_rectangle,
39 		mem_default_strip_copy_rop, mem_get_bits_rectangle);
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 /* Swap the bytes of a color if needed. */
46 #define color_swap_bytes(color)\
47   ((((color) >> 24) & 0xff) + (((color) >> 8) & 0xff00) +\
48    (((color) & 0xff00) << 8) + ((color) << 24))
49 #if arch_is_big_endian
50 #  define arrange_bytes(color) (color)
51 #else
52 #  define arrange_bytes(color) color_swap_bytes(color)
53 #endif
54 
55 /* Fill a rectangle with a color. */
56 private int
mem_true32_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)57 mem_true32_fill_rectangle(gx_device * dev,
58 			  int x, int y, int w, int h, gx_color_index color)
59 {
60     gx_device_memory * const mdev = (gx_device_memory *)dev;
61     bits32 a_color;
62 
63     declare_scan_ptr(dest);
64 
65     fit_fill(dev, x, y, w, h);
66     a_color = arrange_bytes(color);
67     setup_rect(dest);
68     if (w <= 4)
69 	switch (w) {
70 		/*case 0: *//* not possible */
71 #define dest32 ((bits32 *)dest)
72 	    case 1:
73 		do {
74 		    dest32[0] = a_color;
75 		    inc_ptr(dest, draster);
76 		}
77 		while (--h > 0);
78 		break;
79 	    case 2:
80 		do {
81 		    dest32[1] = dest32[0] = a_color;
82 		    inc_ptr(dest, draster);
83 		}
84 		while (--h > 0);
85 		break;
86 	    case 3:
87 		do {
88 		    dest32[2] = dest32[1] = dest32[0] = a_color;
89 		    inc_ptr(dest, draster);
90 		}
91 		while (--h > 0);
92 		break;
93 	    case 4:
94 		do {
95 		    dest32[3] = dest32[2] = dest32[1] = dest32[0] = a_color;
96 		    inc_ptr(dest, draster);
97 		}
98 		while (--h > 0);
99 		break;
100 	    default:		/* not possible */
101 		;
102     } else if (a_color == 0)
103 	do {
104 	    memset(dest, 0, w << 2);
105 	    inc_ptr(dest, draster);
106 	}
107 	while (--h > 0);
108     else
109 	do {
110 	    bits32 *pptr = dest32;
111 	    int cnt = w;
112 
113 	    do {
114 		pptr[3] = pptr[2] = pptr[1] = pptr[0] = a_color;
115 		pptr += 4;
116 	    }
117 	    while ((cnt -= 4) > 4);
118 	    do {
119 		*pptr++ = a_color;
120 	    } while (--cnt > 0);
121 	    inc_ptr(dest, draster);
122 	}
123 	while (--h > 0);
124 #undef dest32
125     return 0;
126 }
127 
128 /* Copy a monochrome bitmap. */
129 private int
mem_true32_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)130 mem_true32_copy_mono(gx_device * dev,
131 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
132 	int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
133 {
134     gx_device_memory * const mdev = (gx_device_memory *)dev;
135     bits32 a_zero = arrange_bytes(zero);
136     bits32 a_one = arrange_bytes(one);
137     const byte *line;
138 
139     declare_scan_ptr(dest);
140     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
141     setup_rect(dest);
142     line = base + (sourcex >> 3);
143     if (zero == gx_no_color_index) {
144 	int first_bit = sourcex & 7;
145 	int w_first = min(w, 8 - first_bit);
146 	int w_rest = w - w_first;
147 
148 	if (one == gx_no_color_index)
149 	    return 0;
150 	/*
151 	 * There are no halftones, so this case -- characters --
152 	 * is the only common one.
153 	 */
154 	while (h-- > 0) {
155 	    bits32 *pptr = (bits32 *) dest;
156 	    const byte *sptr = line;
157 	    int sbyte = (*sptr++ << first_bit) & 0xff;
158 	    int count = w_first;
159 
160 	    if (sbyte)
161 		do {
162 		    if (sbyte & 0x80)
163 			*pptr = a_one;
164 		    sbyte <<= 1;
165 		    pptr++;
166 		}
167 		while (--count > 0);
168 	    else
169 		pptr += count;
170 	    for (count = w_rest; count >= 8; count -= 8, pptr += 8) {
171 		sbyte = *sptr++;
172 		if (sbyte) {
173 		    if (sbyte & 0x80) pptr[0] = a_one;
174 		    if (sbyte & 0x40) pptr[1] = a_one;
175 		    if (sbyte & 0x20) pptr[2] = a_one;
176 		    if (sbyte & 0x10) pptr[3] = a_one;
177 		    if (sbyte & 0x08) pptr[4] = a_one;
178 		    if (sbyte & 0x04) pptr[5] = a_one;
179 		    if (sbyte & 0x02) pptr[6] = a_one;
180 		    if (sbyte & 0x01) pptr[7] = a_one;
181 		}
182 	    }
183 	    if (count) {
184 		sbyte = *sptr;
185 		do {
186 		    if (sbyte & 0x80)
187 			*pptr = a_one;
188 		    sbyte <<= 1;
189 		    pptr++;
190 		}
191 		while (--count > 0);
192 	    }
193 	    line += sraster;
194 	    inc_ptr(dest, draster);
195 	}
196     } else {			/* zero != gx_no_color_index */
197 	int first_bit = 0x80 >> (sourcex & 7);
198 
199 	while (h-- > 0) {
200 	    bits32 *pptr = (bits32 *) dest;
201 	    const byte *sptr = line;
202 	    int sbyte = *sptr++;
203 	    int bit = first_bit;
204 	    int count = w;
205 
206 	    do {
207 		if (sbyte & bit) {
208 		    if (one != gx_no_color_index)
209 			*pptr = a_one;
210 		} else
211 		    *pptr = a_zero;
212 		if ((bit >>= 1) == 0)
213 		    bit = 0x80, sbyte = *sptr++;
214 		pptr++;
215 	    }
216 	    while (--count > 0);
217 	    line += sraster;
218 	    inc_ptr(dest, draster);
219 	}
220     }
221     return 0;
222 }
223 
224 /* Copy a color bitmap. */
225 private int
mem_true32_copy_color(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h)226 mem_true32_copy_color(gx_device * dev,
227 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
228 		      int x, int y, int w, int h)
229 {
230     gx_device_memory * const mdev = (gx_device_memory *)dev;
231 
232     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
233     mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
234     return 0;
235 }
236 
237 /* ================ "Word"-oriented device ================ */
238 
239 /* Note that on a big-endian machine, this is the same as the */
240 /* standard byte-oriented-device. */
241 
242 #if !arch_is_big_endian
243 
244 /* Procedures */
245 declare_mem_procs(mem32_word_copy_mono, mem32_word_copy_color, mem32_word_fill_rectangle);
246 
247 /* Here is the device descriptor. */
248 const gx_device_memory mem_true32_word_device =
249 mem_full_device("image32w", 24, 8, mem_open,
250 		gx_default_map_rgb_color, gx_default_map_color_rgb,
251      mem32_word_copy_mono, mem32_word_copy_color, mem32_word_fill_rectangle,
252 	    gx_default_cmyk_map_cmyk_color, gx_default_strip_tile_rectangle,
253 		gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
254 
255 /* Fill a rectangle with a color. */
256 private int
mem32_word_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)257 mem32_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
258 			  gx_color_index color)
259 {
260     return mem_true32_fill_rectangle(dev, x, y, w, h,
261 				     color_swap_bytes(color));
262 }
263 
264 /* Copy a bitmap. */
265 private int
mem32_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)266 mem32_word_copy_mono(gx_device * dev,
267 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
268 	int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
269 {
270     return mem_true32_copy_mono(dev, base, sourcex, sraster, id,
271 				x, y, w, h, color_swap_bytes(zero),
272 				color_swap_bytes(one));
273 }
274 
275 /* Copy a color bitmap. */
276 private int
mem32_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)277 mem32_word_copy_color(gx_device * dev,
278 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
279 		      int x, int y, int w, int h)
280 {
281     gx_device_memory * const mdev = (gx_device_memory *)dev;
282     byte *row;
283     uint raster;
284 
285     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
286     row = scan_line_base(mdev, y);
287     raster = mdev->raster;
288     bytes_copy_rectangle(row + (x << 2), raster, base + (sourcex << 2),
289 			 sraster, w << 2, h);
290     mem_swap_byte_rect(row, raster, x << 5, w << 5, h, false);
291     return 0;
292 }
293 
294 #endif /* !arch_is_big_endian */
295