xref: /plan9/sys/src/cmd/gs/src/gsbitops.h (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1991, 1995, 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: gsbitops.h,v 1.7 2002/09/21 00:26:04 dan Exp $ */
18 /* Interface for bitmap operations */
19 
20 #ifndef gsbitops_INCLUDED
21 #  define gsbitops_INCLUDED
22 
23 /* ---------------- Pixel processing macros ---------------- */
24 
25 /*
26  * These macros support code that processes data pixel-by-pixel (or, to be
27  * more accurate, packed arrays of values -- they may be complete pixels
28  * or individual components of pixels).
29  *
30  * Supported #s of bits per value (bpv) are 1, 2, 4, or n * 8, where n <= 8.
31  * The suffix 8, 12, 16, 32, or 64 on a macro name indicates the maximum
32  * value of bpv that the macro is prepared to handle.
33  *
34  * The setup macros number bits within a byte in big-endian order, i.e.,
35  * 0x80 is bit 0, 0x01 is bit 7.  However, sbit/dbit may use a different
36  * representation for better performance.  ****** NYI ******
37  */
38 
39 #define sample_end_\
40   default: return_error(gs_error_rangecheck);\
41   } END
42 
43 /* Declare variables for loading. */
44 #define sample_load_declare(sptr, sbit)\
45   const byte *sptr;\
46   int sbit
47 #define sample_load_declare_setup(sptr, sbit, ptr, bitno, sbpv)\
48   const byte *sptr = (ptr);\
49   int sample_load_setup(sbit, bitno, sbpv)
50 
51 /* Set up to load starting at a given bit number. */
52 #define sample_load_setup(sbit, bitno, sbpv)\
53   sbit = (bitno)
54 
55 /* macro to eliminate compiler warning message */
56 #define sample_bound_shift(value, shift)\
57     ((shift) >= 8 * sizeof(value) ? (shift) & (8 * sizeof(value) - 1) : (shift))
58 
59 /* Load a value from memory, without incrementing. */
60 #define sample_load8_(value, sptr, sbit, sbpv)\
61   BEGIN\
62   switch ( (sbpv) >> 2 ) {\
63   case 0: value = (*(sptr) >> (8 - (sbit) - (sbpv))) & ((sbpv) | 1); break;\
64   case 1: value = (*(sptr) >> (4 - (sbit))) & 0xf; break;\
65   case 2: value = *(sptr); break;
66 #define sample_load8(value, sptr, sbit, sbpv)\
67   sample_load8_(value, sptr, sbit, sbpv)\
68   sample_end_
69 #define sample_load_next8(value, sptr, sbit, sbpv)\
70   sample_load8(value, sptr, sbit, sbpv);\
71   sample_next(sptr, sbit, sbpv)
72 #define sample_load12_(value, sptr, sbit, sbpv)\
73   sample_load8_(value, sptr, sbit, sbpv)\
74   case 3:\
75     value = ((sbit) ? ((*(sptr) & 0xf) << 8) | (sptr)[1] :\
76 	      (*(sptr) << 4) | ((sptr)[1] >> 4));\
77     break;
78 #define sample_load12(value, sptr, sbit, sbpv)\
79   sample_load12_(value, sptr, sbit, sbpv)\
80   sample_end_
81 #define sample_load_next12(value, sptr, sbit, sbpv)\
82   sample_load12(value, sptr, sbit, sbpv);\
83   sample_next(sptr, sbit, sbpv)
84 #define sample_load16_(value, sptr, sbit, sbpv)\
85   sample_load12_(value, sptr, sbit, sbpv)\
86   case 4: value = (*(sptr) << 8) | (sptr)[1]; break;
87 #define sample_load16(value, sptr, sbit, sbpv)\
88   sample_load16_(value, sptr, sbit, sbpv)\
89   sample_end_
90 #define sample_load_next16(value, sptr, sbit, sbpv)\
91   sample_load16(value, sptr, sbit, sbpv);\
92   sample_next(sptr, sbit, sbpv)
93 #define sample_load32_(value, sptr, sbit, sbpv)\
94   sample_load16_(value, sptr, sbit, sbpv)\
95   case 6: value = (*(sptr) << 16) | ((sptr)[1] << 8) | (sptr)[2]; break;\
96   case 8:\
97     value = (*(sptr) << 24) | ((sptr)[1] << 16) | ((sptr)[2] << 8) | sptr[3];\
98     break;
99 #define sample_load32(value, sptr, sbit, sbpv)\
100   sample_load32_(value, sptr, sbit, sbpv);\
101   sample_end_
102 #define sample_load_next32(value, sptr, sbit, sbpv)\
103   sample_load32(value, sptr, sbit, sbpv);\
104   sample_next(sptr, sbit, sbpv)
105 #define sample_load64_(value, sptr, sbit, sbpv)\
106   sample_load32_(value, sptr, sbit, sbpv);\
107   case 10:\
108     value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 32)) |\
109             ((gx_color_index)((sptr)[1]) << 24) |\
110             ((gx_color_index)((sptr)[2]) << 16) |\
111             ((gx_color_index)((sptr)[3]) << 8) |\
112             (gx_color_index)((sptr)[4]);\
113     break;\
114   case 12:\
115     value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 40)) |\
116             ((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 32)) |\
117             ((gx_color_index)((sptr)[2]) << 24) |\
118             ((gx_color_index)((sptr)[3]) << 16) |\
119             ((gx_color_index)((sptr)[4]) << 8) |\
120             (gx_color_index)((sptr)[5]);\
121     break;\
122   case 14:\
123     value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 48)) |\
124             ((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 40)) |\
125             ((gx_color_index)((sptr)[2]) << sample_bound_shift((value), 32)) |\
126             ((gx_color_index)((sptr)[3]) << 24) |\
127             ((gx_color_index)((sptr)[4]) << 16) |\
128             ((gx_color_index)((sptr)[5]) << 8) |\
129             (gx_color_index)((sptr)[6]);\
130     break;\
131   case 16:\
132     value = ((gx_color_index)((sptr)[0]) << sample_bound_shift((value), 56)) |\
133             ((gx_color_index)((sptr)[1]) << sample_bound_shift((value), 48)) |\
134             ((gx_color_index)((sptr)[2]) << sample_bound_shift((value), 40)) |\
135             ((gx_color_index)((sptr)[3]) << sample_bound_shift((value), 32)) |\
136             ((gx_color_index)((sptr)[4]) << 24) |\
137             ((gx_color_index)((sptr)[5]) << 16) |\
138             ((gx_color_index)((sptr)[6]) << 8) |\
139             (gx_color_index)((sptr)[7]);\
140     break;
141 #define sample_load64(value, sptr, sbit, sbpv)\
142   sample_load64_(value, sptr, sbit, sbpv);\
143   sample_end_
144 #define sample_load_next64(value, sptr, sbit, sbpv)\
145   sample_load64(value, sptr, sbit, sbpv);\
146   sample_next(sptr, sbit, sbpv)
147 #define sample_load_any(value, sptr, sbit, sbpv)\
148   if (sizeof(value) > 4)\
149     sample_load64(value, sptr, sbit, sbpv);\
150   else\
151     sample_load32(value, sptr, sbit, sbpv)
152 #define sample_load_next_any(value, sptr, sbit, sbpv)\
153   sample_load_any(value, sptr, sbit, sbpv);\
154   sample_next(sptr, sbit, sbpv)
155 
156 /* Declare variables for storing. */
157 #define sample_store_declare(dptr, dbit, dbbyte)\
158   byte *dptr;\
159   int dbit;\
160   byte dbbyte			/* maybe should be uint? */
161 #define sample_store_declare_setup(dptr, dbit, dbbyte, ptr, bitno, dbpv)\
162   byte *dptr = (ptr);\
163   int sample_store_setup(dbit, bitno, dbpv);\
164   byte /* maybe should be uint? */\
165     sample_store_preload(dbbyte, dptr, dbit, dbpv)
166 
167 /* Set up to store starting at a given bit number. */
168 #define sample_store_setup(dbit, bitno, dbpv)\
169   dbit = (bitno)
170 
171 /* Prepare for storing by preloading any partial byte. */
172 #define sample_store_preload(dbbyte, dptr, dbit, dbpv)\
173   dbbyte = ((dbit) ? (byte)(*(dptr) & (0xff00 >> (dbit))) : 0)
174 
175 /* Store a value and increment the pointer. */
176 #define sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
177   BEGIN\
178   switch ( (dbpv) >> 2 ) {\
179   case 0:\
180     if ( (dbit += (dbpv)) == 8 )\
181        *(dptr)++ = dbbyte | (byte)(value), dbbyte = 0, dbit = 0;\
182     else dbbyte |= (byte)((value) << (8 - dbit));\
183     break;\
184   case 1:\
185     if ( dbit ^= 4 ) dbbyte = (byte)((value) << 4);\
186     else *(dptr)++ = dbbyte | ((byte)(value));\
187     break;\
188   /* case 2 is deliberately omitted */
189 #define sample_store_next8(value, dptr, dbit, dbpv, dbbyte)\
190   sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
191   case 2: *(dptr)++ = (byte)(value); break;\
192   sample_end_
193 #define sample_store_next_12_(value, dptr, dbit, dbbyte)\
194     if ( dbit ^= 4 ) *(dptr)++ = (byte)((value) >> 4), dbbyte = (byte)((value) << 4);\
195     else\
196       *(dptr) = dbbyte | (byte)((value) >> 8), (dptr)[1] = (byte)(value), dptr += 2;
197 #define sample_store_next_12(value, dptr, dbit, dbbyte)\
198   BEGIN sample_store_next_12_(value, dptr, dbit, dbbyte) END
199 #define sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
200   sample_store_next8_(value, dptr, dbit, dbpv, dbbyte)\
201   /* case 2 is deliberately omitted */\
202   case 3: sample_store_next_12_(value, dptr, dbit, dbbyte) break;
203 #define sample_store_next12(value, dptr, dbit, dbpv, dbbyte)\
204   sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
205   case 2: *(dptr)++ = (byte)(value); break;\
206   sample_end_
207 #define sample_store_next16(value, dptr, dbit, dbpv, dbbyte)\
208   sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
209   case 4: *(dptr)++ = (byte)((value) >> 8);\
210   case 2: *(dptr)++ = (byte)(value); break;\
211   sample_end_
212 #define sample_store_next32(value, dptr, dbit, dbpv, dbbyte)\
213   sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
214   case 8: *(dptr)++ = (byte)((value) >> 24);\
215   case 6: *(dptr)++ = (byte)((value) >> 16);\
216   case 4: *(dptr)++ = (byte)((value) >> 8);\
217   case 2: *(dptr)++ = (byte)(value); break;\
218   sample_end_
219 #define sample_store_next64(value, dptr, dbit, dbpv, dbbyte)\
220   sample_store_next12_(value, dptr, dbit, dbpv, dbbyte)\
221   case 16: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 56));\
222   case 14: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 48));\
223   case 12: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 40));\
224   case 10: *(dptr)++ = (byte)((value) >> sample_bound_shift((value), 32));\
225   case 8: *(dptr)++ = (byte)((value) >> 24);\
226   case 6: *(dptr)++ = (byte)((value) >> 16);\
227   case 4: *(dptr)++ = (byte)((value) >> 8);\
228   case 2: *(dptr)++ = (byte)(value); break;\
229   sample_end_
230 #define sample_store_next_any(value, dptr, dbit, dbpv, dbbyte)\
231   if (sizeof(value) > 4)\
232     sample_store_next64(value, dptr, dbit, dbpv, dbbyte);\
233   else\
234     sample_store_next32(value, dptr, dbit, dbpv, dbbyte)
235 
236 /* Skip over storing one sample.  This may or may not store into the */
237 /* skipped region. */
238 #define sample_store_skip_next(dptr, dbit, dbpv, dbbyte)\
239   if ( (dbpv) < 8 ) {\
240     sample_store_flush(dptr, dbit, dbpv, dbbyte);\
241     sample_next(dptr, dbit, dbpv);\
242   } else dptr += ((dbpv) >> 3)
243 
244 /* Finish storing by flushing any partial byte. */
245 #define sample_store_flush(dptr, dbit, dbpv, dbbyte)\
246   if ( (dbit) != 0 )\
247     *(dptr) = dbbyte | (*(dptr) & (0xff >> (dbit)));
248 
249 /* Increment a pointer to the next sample. */
250 #define sample_next(ptr, bit, bpv)\
251   BEGIN bit += (bpv); ptr += bit >> 3; bit &= 7; END
252 
253 /* ---------------- Definitions ---------------- */
254 
255 /*
256  * Define the chunk size for monobit filling operations.
257  * This is always uint, regardless of byte order.
258  */
259 #define mono_fill_chunk uint
260 #define mono_fill_chunk_bytes arch_sizeof_int
261 
262 /* ---------------- Procedures ---------------- */
263 
264 /* Fill a rectangle of bits with an 8x1 pattern. */
265 /* The pattern argument must consist of the pattern in every byte, */
266 /* e.g., if the desired pattern is 0xaa, the pattern argument must */
267 /* have the value 0xaaaa (if ints are short) or 0xaaaaaaaa. */
268 #if mono_fill_chunk_bytes == 2
269 #  define mono_fill_make_pattern(byt) (uint)((uint)(byt) * 0x0101)
270 #else
271 #  define mono_fill_make_pattern(byt) (uint)((uint)(byt) * 0x01010101)
272 #endif
273 void bits_fill_rectangle(byte * dest, int dest_bit, uint raster,
274 		      mono_fill_chunk pattern, int width_bits, int height);
275 void bits_fill_rectangle_masked(byte * dest, int dest_bit, uint raster,
276 		      mono_fill_chunk pattern, mono_fill_chunk src_mask,
277 		      int width_bits, int height);
278 
279 /* Replicate a bitmap horizontally in place. */
280 void bits_replicate_horizontally(byte * data, uint width, uint height,
281 	       uint raster, uint replicated_width, uint replicated_raster);
282 
283 /* Replicate a bitmap vertically in place. */
284 void bits_replicate_vertically(byte * data, uint height, uint raster,
285     uint replicated_height);
286 
287 /* Find the bounding box of a bitmap. */
288 void bits_bounding_box(const byte * data, uint height, uint raster,
289     gs_int_rect * pbox);
290 
291 /* Compress an oversampled image, possibly in place. */
292 /* The width and height must be multiples of the respective scale factors. */
293 /* The source must be an aligned bitmap, as usual. */
294 void bits_compress_scaled(const byte * src, int srcx, uint width,
295     uint height, uint sraster, byte * dest, uint draster,
296     const gs_log2_scale_point * plog2_scale, int log2_out_bits);
297 
298 /* Extract a plane from a pixmap. */
299 typedef struct bits_plane_s {
300     union bpd_ {	/* Bit planes must be aligned. */
301 	byte *write;
302 	const byte *read;
303     } data;
304     int raster;
305     int depth;
306     int x;			/* starting x */
307 } bits_plane_t;
308 int bits_extract_plane(const bits_plane_t *dest /*write*/,
309     const bits_plane_t *source /*read*/, int shift, int width, int height);
310 
311 /* Expand a plane into a pixmap. */
312 int bits_expand_plane(const bits_plane_t *dest /*write*/,
313     const bits_plane_t *source /*read*/, int shift, int width, int height);
314 
315 /* Fill a rectangle of bytes. */
316 void bytes_fill_rectangle(byte * dest, uint raster,
317     byte value, int width_bytes, int height);
318 
319 /* Copy a rectangle of bytes. */
320 void bytes_copy_rectangle(byte * dest, uint dest_raster,
321     const byte * src, uint src_raster, int width_bytes, int height);
322 
323 #endif /* gsbitops_INCLUDED */
324