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