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