xref: /plan9/sys/src/cmd/gs/src/gdevm56.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1*593dc095SDavid du Colombier /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises, 2001 Artifex Software.  All rights reserved.
2*593dc095SDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
5*593dc095SDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
9*593dc095SDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15*593dc095SDavid du Colombier */
16*593dc095SDavid du Colombier 
17*593dc095SDavid du Colombier /*$Id: gdevm56.c,v 1.3 2004/08/30 21:45:48 dan Exp $ */
18*593dc095SDavid du Colombier /* 56-bit-per-pixel "memory" (stored bitmap) device */
19*593dc095SDavid du Colombier #include "memory_.h"
20*593dc095SDavid du Colombier #include "gx.h"
21*593dc095SDavid du Colombier #include "gxdevice.h"
22*593dc095SDavid du Colombier #include "gxdevmem.h"		/* semi-public definitions */
23*593dc095SDavid du Colombier #include "gdevmem.h"		/* private definitions */
24*593dc095SDavid du Colombier 
25*593dc095SDavid du Colombier /* Define debugging statistics. */
26*593dc095SDavid du Colombier #ifdef DEBUG
27*593dc095SDavid du Colombier struct stats_mem56_s {
28*593dc095SDavid du Colombier     long
29*593dc095SDavid du Colombier 	fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5],
30*593dc095SDavid du Colombier 	fprevc[257];
31*593dc095SDavid du Colombier     double ftotal;
32*593dc095SDavid du Colombier } stats_mem56;
33*593dc095SDavid du Colombier static int prev_count;
34*593dc095SDavid du Colombier static gx_color_index prev_colors[256];
35*593dc095SDavid du Colombier # define INCR(v) (++(stats_mem56.v))
36*593dc095SDavid du Colombier #else
37*593dc095SDavid du Colombier # define INCR(v) DO_NOTHING
38*593dc095SDavid du Colombier #endif
39*593dc095SDavid du Colombier 
40*593dc095SDavid du Colombier 
41*593dc095SDavid du Colombier /* ================ Standard (byte-oriented) device ================ */
42*593dc095SDavid du Colombier 
43*593dc095SDavid du Colombier #undef chunk
44*593dc095SDavid du Colombier #define chunk byte
45*593dc095SDavid du Colombier #define PIXEL_SIZE 7
46*593dc095SDavid du Colombier 
47*593dc095SDavid du Colombier /* Procedures */
48*593dc095SDavid du Colombier declare_mem_procs(mem_true56_copy_mono, mem_true56_copy_color, mem_true56_fill_rectangle);
49*593dc095SDavid du Colombier 
50*593dc095SDavid du Colombier /* The device descriptor. */
51*593dc095SDavid du Colombier const gx_device_memory mem_true56_device =
52*593dc095SDavid du Colombier mem_full_alpha_device("image56", 56, 0, mem_open,
53*593dc095SDavid du Colombier 		 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
54*593dc095SDavid du Colombier      mem_true56_copy_mono, mem_true56_copy_color, mem_true56_fill_rectangle,
55*593dc095SDavid du Colombier 		      gx_default_map_cmyk_color, gx_default_copy_alpha,
56*593dc095SDavid du Colombier 		 gx_default_strip_tile_rectangle, mem_default_strip_copy_rop,
57*593dc095SDavid du Colombier 		      mem_get_bits_rectangle);
58*593dc095SDavid du Colombier 
59*593dc095SDavid du Colombier /* Convert x coordinate to byte offset in scan line. */
60*593dc095SDavid du Colombier #undef x_to_byte
61*593dc095SDavid du Colombier #define x_to_byte(x) ((x) * PIXEL_SIZE)
62*593dc095SDavid du Colombier 
63*593dc095SDavid du Colombier /* Unpack a color into its bytes. */
64*593dc095SDavid du Colombier #define declare_unpack_color(a, b, c, d, e, f, g, color)\
65*593dc095SDavid du Colombier 	byte a = (byte)(color >> 48);\
66*593dc095SDavid du Colombier 	byte b = (byte)(color >> 40);\
67*593dc095SDavid du Colombier 	byte c = (byte)(color >> 32);\
68*593dc095SDavid du Colombier 	byte d = (byte)((uint)color >> 24);\
69*593dc095SDavid du Colombier 	byte e = (byte)((uint)color >> 16);\
70*593dc095SDavid du Colombier 	byte f = (byte)((uint)color >> 8);\
71*593dc095SDavid du Colombier 	byte g = (byte)color
72*593dc095SDavid du Colombier /* Put a 56-bit color into the bitmap. */
73*593dc095SDavid du Colombier #define put7(ptr, a, b, c, d, e, f, g)\
74*593dc095SDavid du Colombier 	(ptr)[0] = a, (ptr)[1] = b, (ptr)[2] = c, (ptr)[3] = d, (ptr)[4] = e, \
75*593dc095SDavid du Colombier 	(ptr)[5] = f, (ptr)[6] = g
76*593dc095SDavid du Colombier /* Put 4 bytes of color into the bitmap. */
77*593dc095SDavid du Colombier #define putw(ptr, wxyz)\
78*593dc095SDavid du Colombier 	*(bits32 *)(ptr) = (wxyz)
79*593dc095SDavid du Colombier /* Load the 7-word 56-bit-color cache. */
80*593dc095SDavid du Colombier /* Free variables: [m]dev, abcd, bcde, cdea, deab, earc. */
81*593dc095SDavid du Colombier #if arch_is_big_endian
82*593dc095SDavid du Colombier #  define set_color56_cache(color, a, b, c, d, e, f, g)\
83*593dc095SDavid du Colombier 	mdev->color56.abcd = abcd = (color) >> 24, \
84*593dc095SDavid du Colombier 	mdev->color56.bcde = bcde = (abcd << 8) | (e),\
85*593dc095SDavid du Colombier 	mdev->color56.cdef = cdef = (bcde << 8) | (f),\
86*593dc095SDavid du Colombier 	mdev->color56.defg = defg = (cdef << 8) | (g),\
87*593dc095SDavid du Colombier 	mdev->color56.efga = efga = (defg << 8) | (a),\
88*593dc095SDavid du Colombier 	mdev->color56.fgab = fgab = (efga << 8) | (b),\
89*593dc095SDavid du Colombier 	mdev->color56.gabc = gabc = (fgab << 8) | (c),\
90*593dc095SDavid du Colombier 	mdev->color56.abcdefg = (color)
91*593dc095SDavid du Colombier #else
92*593dc095SDavid du Colombier #  define set_color56_cache(color, a, b, c, d, e, f, g)\
93*593dc095SDavid du Colombier 	mdev->color56.abcd = abcd =\
94*593dc095SDavid du Colombier 		((bits32)(d) << 24) | ((bits32)(c) << 16) |\
95*593dc095SDavid du Colombier 		((bits16)(b) << 8) | (a),\
96*593dc095SDavid du Colombier 	mdev->color56.gabc = gabc = (abcd << 8) | (g),\
97*593dc095SDavid du Colombier 	mdev->color56.fgab = fgab = (gabc << 8) | (f),\
98*593dc095SDavid du Colombier 	mdev->color56.efga = efga = (fgab << 8) | (e),\
99*593dc095SDavid du Colombier 	mdev->color56.defg = defg = (efga << 8) | (d),\
100*593dc095SDavid du Colombier 	mdev->color56.cdef = cdef = (defg << 8) | (c),\
101*593dc095SDavid du Colombier 	mdev->color56.bcde = bcde = (cdef << 8) | (b),\
102*593dc095SDavid du Colombier 	mdev->color56.abcdefg = (color)
103*593dc095SDavid du Colombier #endif
104*593dc095SDavid du Colombier 
105*593dc095SDavid du Colombier /* Fill a rectangle with a color. */
106*593dc095SDavid du Colombier private int
mem_true56_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)107*593dc095SDavid du Colombier mem_true56_fill_rectangle(gx_device * dev,
108*593dc095SDavid du Colombier 			  int x, int y, int w, int h, gx_color_index color)
109*593dc095SDavid du Colombier {
110*593dc095SDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
111*593dc095SDavid du Colombier     declare_unpack_color(a, b, c, d, e, f, g, color);
112*593dc095SDavid du Colombier     declare_scan_ptr(dest);
113*593dc095SDavid du Colombier 
114*593dc095SDavid du Colombier     /*
115*593dc095SDavid du Colombier      * In order to avoid testing w > 0 and h > 0 twice, we defer
116*593dc095SDavid du Colombier      * executing setup_rect, and use fit_fill_xywh instead of
117*593dc095SDavid du Colombier      * fit_fill.
118*593dc095SDavid du Colombier      */
119*593dc095SDavid du Colombier     fit_fill_xywh(dev, x, y, w, h);
120*593dc095SDavid du Colombier     INCR(fill);
121*593dc095SDavid du Colombier #ifdef DEBUG
122*593dc095SDavid du Colombier     stats_mem56.ftotal += w;
123*593dc095SDavid du Colombier #endif
124*593dc095SDavid du Colombier     if (w >= 5) {
125*593dc095SDavid du Colombier 	if (h <= 0)
126*593dc095SDavid du Colombier 	    return 0;
127*593dc095SDavid du Colombier 	INCR(fwide);
128*593dc095SDavid du Colombier 	setup_rect(dest);
129*593dc095SDavid du Colombier 	if (a == b && b == c && c == d && d == e && e == f && f == g) {
130*593dc095SDavid du Colombier 	    int bcnt = w * PIXEL_SIZE;
131*593dc095SDavid du Colombier 
132*593dc095SDavid du Colombier 	    INCR(fgray[min(w, 100)]);
133*593dc095SDavid du Colombier 	    while (h-- > 0) {
134*593dc095SDavid du Colombier 		memset(dest, a, bcnt);
135*593dc095SDavid du Colombier 		inc_ptr(dest, draster);
136*593dc095SDavid du Colombier 	    }
137*593dc095SDavid du Colombier 	} else {
138*593dc095SDavid du Colombier 	    int x3 = -x & 3, ww = w - x3;	/* we know ww >= 2 */
139*593dc095SDavid du Colombier 	    bits32 abcd, bcde, cdef, defg, efga, fgab, gabc;
140*593dc095SDavid du Colombier 
141*593dc095SDavid du Colombier 	    if (mdev->color56.abcdefg == color) {
142*593dc095SDavid du Colombier 		abcd = mdev->color56.abcd;
143*593dc095SDavid du Colombier 		bcde = mdev->color56.bcde;
144*593dc095SDavid du Colombier 		cdef = mdev->color56.cdef;
145*593dc095SDavid du Colombier 		defg = mdev->color56.defg;
146*593dc095SDavid du Colombier 		efga = mdev->color56.efga;
147*593dc095SDavid du Colombier 		fgab = mdev->color56.fgab;
148*593dc095SDavid du Colombier 		gabc = mdev->color56.gabc;
149*593dc095SDavid du Colombier 	    } else {
150*593dc095SDavid du Colombier 		INCR(fsetc);
151*593dc095SDavid du Colombier 		set_color56_cache(color, a, b, c, d, e, f, g);
152*593dc095SDavid du Colombier 	    }
153*593dc095SDavid du Colombier #ifdef DEBUG
154*593dc095SDavid du Colombier 	    {
155*593dc095SDavid du Colombier 		int ci;
156*593dc095SDavid du Colombier 		for (ci = 0; ci < prev_count; ++ci)
157*593dc095SDavid du Colombier 		    if (prev_colors[ci] == color)
158*593dc095SDavid du Colombier 			break;
159*593dc095SDavid du Colombier 		INCR(fprevc[ci]);
160*593dc095SDavid du Colombier 		if (ci == prev_count) {
161*593dc095SDavid du Colombier 		    if (ci < countof(prev_colors))
162*593dc095SDavid du Colombier 			++prev_count;
163*593dc095SDavid du Colombier 		    else
164*593dc095SDavid du Colombier 			--ci;
165*593dc095SDavid du Colombier 		}
166*593dc095SDavid du Colombier 		if (ci) {
167*593dc095SDavid du Colombier 		    memmove(&prev_colors[1], &prev_colors[0],
168*593dc095SDavid du Colombier 			    ci * sizeof(prev_colors[0]));
169*593dc095SDavid du Colombier 		    prev_colors[0] = color;
170*593dc095SDavid du Colombier 		}
171*593dc095SDavid du Colombier 	    }
172*593dc095SDavid du Colombier #endif
173*593dc095SDavid du Colombier 	    INCR(fcolor[min(w, 100)]);
174*593dc095SDavid du Colombier 	    while (h-- > 0) {
175*593dc095SDavid du Colombier 		register byte *pptr = dest;
176*593dc095SDavid du Colombier 		int w1 = ww;
177*593dc095SDavid du Colombier 
178*593dc095SDavid du Colombier 		switch (x3) {
179*593dc095SDavid du Colombier 		    case 1:
180*593dc095SDavid du Colombier 			pptr[0] = a;
181*593dc095SDavid du Colombier 			pptr[1] = b;
182*593dc095SDavid du Colombier 			pptr[2] = c;
183*593dc095SDavid du Colombier 			putw(pptr + 3, defg);
184*593dc095SDavid du Colombier 			pptr += PIXEL_SIZE;
185*593dc095SDavid du Colombier 			break;
186*593dc095SDavid du Colombier 		    case 2:
187*593dc095SDavid du Colombier 			pptr[0] = a;
188*593dc095SDavid du Colombier 			pptr[1] = b;
189*593dc095SDavid du Colombier 			putw(pptr + 2, cdef);
190*593dc095SDavid du Colombier 			putw(pptr + 6, gabc);
191*593dc095SDavid du Colombier 			putw(pptr + 10, defg);
192*593dc095SDavid du Colombier 			pptr += 2 * PIXEL_SIZE;
193*593dc095SDavid du Colombier 			break;
194*593dc095SDavid du Colombier 		    case 3:
195*593dc095SDavid du Colombier 			pptr[0] = a;
196*593dc095SDavid du Colombier 			putw(pptr + 1, bcde);
197*593dc095SDavid du Colombier 			putw(pptr + 5, fgab);
198*593dc095SDavid du Colombier 			putw(pptr + 9, cdef);
199*593dc095SDavid du Colombier 			putw(pptr + 13, gabc);
200*593dc095SDavid du Colombier 			putw(pptr + 17, defg);
201*593dc095SDavid du Colombier 			pptr += 3 * PIXEL_SIZE;
202*593dc095SDavid du Colombier 			break;
203*593dc095SDavid du Colombier 		    case 0:
204*593dc095SDavid du Colombier 			;
205*593dc095SDavid du Colombier 		}
206*593dc095SDavid du Colombier 		while (w1 >= 4) {
207*593dc095SDavid du Colombier 		    putw(pptr, abcd);
208*593dc095SDavid du Colombier 		    putw(pptr + 4, efga);
209*593dc095SDavid du Colombier 		    putw(pptr + 8, bcde);
210*593dc095SDavid du Colombier 		    putw(pptr + 12, fgab);
211*593dc095SDavid du Colombier 		    putw(pptr + 16, cdef);
212*593dc095SDavid du Colombier 		    putw(pptr + 20, gabc);
213*593dc095SDavid du Colombier 		    putw(pptr + 24, defg);
214*593dc095SDavid du Colombier 		    pptr += 4 * PIXEL_SIZE;
215*593dc095SDavid du Colombier 		    w1 -= 4;
216*593dc095SDavid du Colombier 		}
217*593dc095SDavid du Colombier 		switch (w1) {
218*593dc095SDavid du Colombier 		    case 1:
219*593dc095SDavid du Colombier 			putw(pptr, abcd);
220*593dc095SDavid du Colombier 			pptr[4] = e;
221*593dc095SDavid du Colombier 			pptr[5] = f;
222*593dc095SDavid du Colombier 			pptr[6] = g;
223*593dc095SDavid du Colombier 			break;
224*593dc095SDavid du Colombier 		    case 2:
225*593dc095SDavid du Colombier 			putw(pptr, abcd);
226*593dc095SDavid du Colombier 			putw(pptr + 4, efga);
227*593dc095SDavid du Colombier 			putw(pptr + 8, bcde);
228*593dc095SDavid du Colombier 			pptr[12] = f;
229*593dc095SDavid du Colombier 			pptr[13] = g;
230*593dc095SDavid du Colombier 			break;
231*593dc095SDavid du Colombier 		    case 3:
232*593dc095SDavid du Colombier 			putw(pptr, abcd);
233*593dc095SDavid du Colombier 			putw(pptr + 4, efga);
234*593dc095SDavid du Colombier 			putw(pptr + 8, bcde);
235*593dc095SDavid du Colombier 			putw(pptr + 12, fgab);
236*593dc095SDavid du Colombier 			putw(pptr + 16, cdef);
237*593dc095SDavid du Colombier 			pptr[20] = g;
238*593dc095SDavid du Colombier 			break;
239*593dc095SDavid du Colombier 		    case 0:
240*593dc095SDavid du Colombier 			;
241*593dc095SDavid du Colombier 		}
242*593dc095SDavid du Colombier 		inc_ptr(dest, draster);
243*593dc095SDavid du Colombier 	    }
244*593dc095SDavid du Colombier 	}
245*593dc095SDavid du Colombier     } else if (h > 0) {		/* w < 5 */
246*593dc095SDavid du Colombier 	INCR(fnarrow[max(w, 0)]);
247*593dc095SDavid du Colombier 	setup_rect(dest);
248*593dc095SDavid du Colombier 	switch (w) {
249*593dc095SDavid du Colombier 	    case 4:
250*593dc095SDavid du Colombier 		do {
251*593dc095SDavid du Colombier 		    dest[21] = dest[14] = dest[7] = dest[0] = a;
252*593dc095SDavid du Colombier 		    dest[22] = dest[15] = dest[8] = dest[1] = b;
253*593dc095SDavid du Colombier 		    dest[23] = dest[16] = dest[9] = dest[2] = c;
254*593dc095SDavid du Colombier 		    dest[24] = dest[17] = dest[10] = dest[3] = d;
255*593dc095SDavid du Colombier 		    dest[25] = dest[18] = dest[11] = dest[4] = e;
256*593dc095SDavid du Colombier 		    dest[26] = dest[19] = dest[12] = dest[5] = f;
257*593dc095SDavid du Colombier 		    dest[27] = dest[20] = dest[13] = dest[6] = g;
258*593dc095SDavid du Colombier 		    inc_ptr(dest, draster);
259*593dc095SDavid du Colombier 		}
260*593dc095SDavid du Colombier 		while (--h);
261*593dc095SDavid du Colombier 		break;
262*593dc095SDavid du Colombier 	    case 3:
263*593dc095SDavid du Colombier 		do {
264*593dc095SDavid du Colombier 		    dest[14] = dest[7] = dest[0] = a;
265*593dc095SDavid du Colombier 		    dest[15] = dest[8] = dest[1] = b;
266*593dc095SDavid du Colombier 		    dest[16] = dest[9] = dest[2] = c;
267*593dc095SDavid du Colombier 		    dest[17] = dest[10] = dest[3] = d;
268*593dc095SDavid du Colombier 		    dest[18] = dest[11] = dest[4] = e;
269*593dc095SDavid du Colombier 		    dest[19] = dest[12] = dest[5] = f;
270*593dc095SDavid du Colombier 		    dest[20] = dest[13] = dest[6] = g;
271*593dc095SDavid du Colombier 		    inc_ptr(dest, draster);
272*593dc095SDavid du Colombier 		}
273*593dc095SDavid du Colombier 		while (--h);
274*593dc095SDavid du Colombier 		break;
275*593dc095SDavid du Colombier 	    case 2:
276*593dc095SDavid du Colombier 		do {
277*593dc095SDavid du Colombier 		    dest[7] = dest[0] = a;
278*593dc095SDavid du Colombier 		    dest[8] = dest[1] = b;
279*593dc095SDavid du Colombier 		    dest[9] = dest[2] = c;
280*593dc095SDavid du Colombier 		    dest[10] = dest[3] = d;
281*593dc095SDavid du Colombier 		    dest[11] = dest[4] = e;
282*593dc095SDavid du Colombier 		    dest[12] = dest[5] = f;
283*593dc095SDavid du Colombier 		    dest[13] = dest[6] = g;
284*593dc095SDavid du Colombier 		    inc_ptr(dest, draster);
285*593dc095SDavid du Colombier 		}
286*593dc095SDavid du Colombier 		while (--h);
287*593dc095SDavid du Colombier 		break;
288*593dc095SDavid du Colombier 	    case 1:
289*593dc095SDavid du Colombier 		do {
290*593dc095SDavid du Colombier 		    dest[0] = a; dest[1] = b; dest[2] = c; dest[3] = d;
291*593dc095SDavid du Colombier 		    dest[4] = e; dest[5] = f; dest[6] = g;
292*593dc095SDavid du Colombier 		    inc_ptr(dest, draster);
293*593dc095SDavid du Colombier 		}
294*593dc095SDavid du Colombier 		while (--h);
295*593dc095SDavid du Colombier 		break;
296*593dc095SDavid du Colombier 	    case 0:
297*593dc095SDavid du Colombier 	    default:
298*593dc095SDavid du Colombier 		;
299*593dc095SDavid du Colombier 	}
300*593dc095SDavid du Colombier     }
301*593dc095SDavid du Colombier     return 0;
302*593dc095SDavid du Colombier }
303*593dc095SDavid du Colombier 
304*593dc095SDavid du Colombier /* Copy a monochrome bitmap. */
305*593dc095SDavid du Colombier private int
mem_true56_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)306*593dc095SDavid du Colombier mem_true56_copy_mono(gx_device * dev,
307*593dc095SDavid du Colombier 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
308*593dc095SDavid du Colombier 	int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
309*593dc095SDavid du Colombier {
310*593dc095SDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
311*593dc095SDavid du Colombier     const byte *line;
312*593dc095SDavid du Colombier     int sbit;
313*593dc095SDavid du Colombier     int first_bit;
314*593dc095SDavid du Colombier 
315*593dc095SDavid du Colombier     declare_scan_ptr(dest);
316*593dc095SDavid du Colombier 
317*593dc095SDavid du Colombier     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
318*593dc095SDavid du Colombier     setup_rect(dest);
319*593dc095SDavid du Colombier     line = base + (sourcex >> 3);
320*593dc095SDavid du Colombier     sbit = sourcex & 7;
321*593dc095SDavid du Colombier     first_bit = 0x80 >> sbit;
322*593dc095SDavid du Colombier     if (zero != gx_no_color_index) {	/* Loop for halftones or inverted masks */
323*593dc095SDavid du Colombier 	/* (never used). */
324*593dc095SDavid du Colombier 	declare_unpack_color(a0, b0, c0, d0, e0, f0, g0, zero);
325*593dc095SDavid du Colombier 	declare_unpack_color(a1, b1, c1, d1, e1, f1, g1, one);
326*593dc095SDavid du Colombier 	while (h-- > 0) {
327*593dc095SDavid du Colombier 	    register byte *pptr = dest;
328*593dc095SDavid du Colombier 	    const byte *sptr = line;
329*593dc095SDavid du Colombier 	    register int sbyte = *sptr++;
330*593dc095SDavid du Colombier 	    register int bit = first_bit;
331*593dc095SDavid du Colombier 	    int count = w;
332*593dc095SDavid du Colombier 
333*593dc095SDavid du Colombier 	    do {
334*593dc095SDavid du Colombier 		if (sbyte & bit) {
335*593dc095SDavid du Colombier 		    if (one != gx_no_color_index)
336*593dc095SDavid du Colombier 			put7(pptr, a1, b1, c1, d1, e1, f1, g1);
337*593dc095SDavid du Colombier 		} else
338*593dc095SDavid du Colombier 		    put7(pptr, a0, b0, c0, d0, e0, f0, g0);
339*593dc095SDavid du Colombier 		pptr += PIXEL_SIZE;
340*593dc095SDavid du Colombier 		if ((bit >>= 1) == 0)
341*593dc095SDavid du Colombier 		    bit = 0x80, sbyte = *sptr++;
342*593dc095SDavid du Colombier 	    }
343*593dc095SDavid du Colombier 	    while (--count > 0);
344*593dc095SDavid du Colombier 	    line += sraster;
345*593dc095SDavid du Colombier 	    inc_ptr(dest, draster);
346*593dc095SDavid du Colombier 	}
347*593dc095SDavid du Colombier     } else if (one != gx_no_color_index) {	/* Loop for character and pattern masks. */
348*593dc095SDavid du Colombier 	/* This is used heavily. */
349*593dc095SDavid du Colombier 	declare_unpack_color(a1, b1, c1, d1, e1, f1, g1, one);
350*593dc095SDavid du Colombier 	int first_mask = first_bit << 1;
351*593dc095SDavid du Colombier 	int first_count, first_skip;
352*593dc095SDavid du Colombier 
353*593dc095SDavid du Colombier 	if (sbit + w > 8)
354*593dc095SDavid du Colombier 	    first_mask -= 1,
355*593dc095SDavid du Colombier 		first_count = 8 - sbit;
356*593dc095SDavid du Colombier 	else
357*593dc095SDavid du Colombier 	    first_mask -= first_mask >> w,
358*593dc095SDavid du Colombier 		first_count = w;
359*593dc095SDavid du Colombier 	first_skip = first_count * PIXEL_SIZE;
360*593dc095SDavid du Colombier 	while (h-- > 0) {
361*593dc095SDavid du Colombier 	    register byte *pptr = dest;
362*593dc095SDavid du Colombier 	    const byte *sptr = line;
363*593dc095SDavid du Colombier 	    register int sbyte = *sptr++ & first_mask;
364*593dc095SDavid du Colombier 	    int count = w - first_count;
365*593dc095SDavid du Colombier 
366*593dc095SDavid du Colombier 	    if (sbyte) {
367*593dc095SDavid du Colombier 		register int bit = first_bit;
368*593dc095SDavid du Colombier 
369*593dc095SDavid du Colombier 		do {
370*593dc095SDavid du Colombier 		    if (sbyte & bit)
371*593dc095SDavid du Colombier 			put7(pptr, a1, b1, c1, d1, e1, f1, g1);
372*593dc095SDavid du Colombier 		    pptr += PIXEL_SIZE;
373*593dc095SDavid du Colombier 		}
374*593dc095SDavid du Colombier 		while ((bit >>= 1) & first_mask);
375*593dc095SDavid du Colombier 	    } else
376*593dc095SDavid du Colombier 		pptr += first_skip;
377*593dc095SDavid du Colombier 	    while (count >= 8) {
378*593dc095SDavid du Colombier 		sbyte = *sptr++;
379*593dc095SDavid du Colombier 		if (sbyte & 0xf0) {
380*593dc095SDavid du Colombier 		    if (sbyte & 0x80)
381*593dc095SDavid du Colombier 			put7(pptr, a1, b1, c1, d1, e1, f1, g1);
382*593dc095SDavid du Colombier 		    if (sbyte & 0x40)
383*593dc095SDavid du Colombier 			put7(pptr + 7, a1, b1, c1, d1, e1, f1, g1);
384*593dc095SDavid du Colombier 		    if (sbyte & 0x20)
385*593dc095SDavid du Colombier 			put7(pptr + 14, a1, b1, c1, d1, e1, f1, g1);
386*593dc095SDavid du Colombier 		    if (sbyte & 0x10)
387*593dc095SDavid du Colombier 			put7(pptr + 21, a1, b1, c1, d1, e1, f1, g1);
388*593dc095SDavid du Colombier 		}
389*593dc095SDavid du Colombier 		if (sbyte & 0xf) {
390*593dc095SDavid du Colombier 		    if (sbyte & 8)
391*593dc095SDavid du Colombier 			put7(pptr + 28, a1, b1, c1, d1, e1, f1, g1);
392*593dc095SDavid du Colombier 		    if (sbyte & 4)
393*593dc095SDavid du Colombier 			put7(pptr + 35, a1, b1, c1, d1, e1, f1, g1);
394*593dc095SDavid du Colombier 		    if (sbyte & 2)
395*593dc095SDavid du Colombier 			put7(pptr + 42, a1, b1, c1, d1, e1, f1, g1);
396*593dc095SDavid du Colombier 		    if (sbyte & 1)
397*593dc095SDavid du Colombier 			put7(pptr + 49, a1, b1, c1, d1, e1, f1, g1);
398*593dc095SDavid du Colombier 		}
399*593dc095SDavid du Colombier 		pptr += 8 * PIXEL_SIZE;
400*593dc095SDavid du Colombier 		count -= 8;
401*593dc095SDavid du Colombier 	    }
402*593dc095SDavid du Colombier 	    if (count > 0) {
403*593dc095SDavid du Colombier 		register int bit = 0x80;
404*593dc095SDavid du Colombier 
405*593dc095SDavid du Colombier 		sbyte = *sptr++;
406*593dc095SDavid du Colombier 		do {
407*593dc095SDavid du Colombier 		    if (sbyte & bit)
408*593dc095SDavid du Colombier 			put7(pptr, a1, b1, c1, d1, e1, f1, g1);
409*593dc095SDavid du Colombier 		    pptr += PIXEL_SIZE;
410*593dc095SDavid du Colombier 		    bit >>= 1;
411*593dc095SDavid du Colombier 		}
412*593dc095SDavid du Colombier 		while (--count > 0);
413*593dc095SDavid du Colombier 	    }
414*593dc095SDavid du Colombier 	    line += sraster;
415*593dc095SDavid du Colombier 	    inc_ptr(dest, draster);
416*593dc095SDavid du Colombier 	}
417*593dc095SDavid du Colombier     }
418*593dc095SDavid du Colombier     return 0;
419*593dc095SDavid du Colombier }
420*593dc095SDavid du Colombier 
421*593dc095SDavid du Colombier /* Copy a color bitmap. */
422*593dc095SDavid du Colombier private int
mem_true56_copy_color(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h)423*593dc095SDavid du Colombier mem_true56_copy_color(gx_device * dev,
424*593dc095SDavid du Colombier 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
425*593dc095SDavid du Colombier 		      int x, int y, int w, int h)
426*593dc095SDavid du Colombier {
427*593dc095SDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
428*593dc095SDavid du Colombier 
429*593dc095SDavid du Colombier     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
430*593dc095SDavid du Colombier     mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
431*593dc095SDavid du Colombier     return 0;
432*593dc095SDavid du Colombier }
433*593dc095SDavid du Colombier 
434*593dc095SDavid du Colombier /* ================ "Word"-oriented device ================ */
435*593dc095SDavid du Colombier 
436*593dc095SDavid du Colombier /* Note that on a big-endian machine, this is the same as the */
437*593dc095SDavid du Colombier /* standard byte-oriented-device. */
438*593dc095SDavid du Colombier 
439*593dc095SDavid du Colombier #if !arch_is_big_endian
440*593dc095SDavid du Colombier 
441*593dc095SDavid du Colombier /* Procedures */
442*593dc095SDavid du Colombier declare_mem_procs(mem56_word_copy_mono, mem56_word_copy_color, mem56_word_fill_rectangle);
443*593dc095SDavid du Colombier 
444*593dc095SDavid du Colombier /* Here is the device descriptor. */
445*593dc095SDavid du Colombier const gx_device_memory mem_true56_word_device =
446*593dc095SDavid du Colombier mem_full_device("image56w", 56, 0, mem_open,
447*593dc095SDavid du Colombier 		gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
448*593dc095SDavid du Colombier      mem56_word_copy_mono, mem56_word_copy_color, mem56_word_fill_rectangle,
449*593dc095SDavid du Colombier 		gx_default_map_cmyk_color, gx_default_strip_tile_rectangle,
450*593dc095SDavid du Colombier 		gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
451*593dc095SDavid du Colombier 
452*593dc095SDavid du Colombier /* Fill a rectangle with a color. */
453*593dc095SDavid du Colombier private int
mem56_word_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)454*593dc095SDavid du Colombier mem56_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
455*593dc095SDavid du Colombier 			  gx_color_index color)
456*593dc095SDavid du Colombier {
457*593dc095SDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
458*593dc095SDavid du Colombier     byte *base;
459*593dc095SDavid du Colombier     uint raster;
460*593dc095SDavid du Colombier 
461*593dc095SDavid du Colombier     fit_fill(dev, x, y, w, h);
462*593dc095SDavid du Colombier     base = scan_line_base(mdev, y);
463*593dc095SDavid du Colombier     raster = mdev->raster;
464*593dc095SDavid du Colombier     mem_swap_byte_rect(base, raster, x * 56, w * 56, h, true);
465*593dc095SDavid du Colombier     mem_true56_fill_rectangle(dev, x, y, w, h, color);
466*593dc095SDavid du Colombier     mem_swap_byte_rect(base, raster, x * 56, w * 56, h, false);
467*593dc095SDavid du Colombier     return 0;
468*593dc095SDavid du Colombier }
469*593dc095SDavid du Colombier 
470*593dc095SDavid du Colombier /* Copy a bitmap. */
471*593dc095SDavid du Colombier private int
mem56_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)472*593dc095SDavid du Colombier mem56_word_copy_mono(gx_device * dev,
473*593dc095SDavid du Colombier 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
474*593dc095SDavid du Colombier 	int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
475*593dc095SDavid du Colombier {
476*593dc095SDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
477*593dc095SDavid du Colombier     byte *row;
478*593dc095SDavid du Colombier     uint raster;
479*593dc095SDavid du Colombier     bool store;
480*593dc095SDavid du Colombier 
481*593dc095SDavid du Colombier     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
482*593dc095SDavid du Colombier     row = scan_line_base(mdev, y);
483*593dc095SDavid du Colombier     raster = mdev->raster;
484*593dc095SDavid du Colombier     store = (zero != gx_no_color_index && one != gx_no_color_index);
485*593dc095SDavid du Colombier     mem_swap_byte_rect(row, raster, x * 56, w * 56, h, store);
486*593dc095SDavid du Colombier     mem_true56_copy_mono(dev, base, sourcex, sraster, id,
487*593dc095SDavid du Colombier 			 x, y, w, h, zero, one);
488*593dc095SDavid du Colombier     mem_swap_byte_rect(row, raster, x * 56, w * 56, h, false);
489*593dc095SDavid du Colombier     return 0;
490*593dc095SDavid du Colombier }
491*593dc095SDavid du Colombier 
492*593dc095SDavid du Colombier /* Copy a color bitmap. */
493*593dc095SDavid du Colombier private int
mem56_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)494*593dc095SDavid du Colombier mem56_word_copy_color(gx_device * dev,
495*593dc095SDavid du Colombier 	       const byte * base, int sourcex, int sraster, gx_bitmap_id id,
496*593dc095SDavid du Colombier 		      int x, int y, int w, int h)
497*593dc095SDavid du Colombier {
498*593dc095SDavid du Colombier     gx_device_memory * const mdev = (gx_device_memory *)dev;
499*593dc095SDavid du Colombier     byte *row;
500*593dc095SDavid du Colombier     uint raster;
501*593dc095SDavid du Colombier 
502*593dc095SDavid du Colombier     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
503*593dc095SDavid du Colombier     row = scan_line_base(mdev, y);
504*593dc095SDavid du Colombier     raster = mdev->raster;
505*593dc095SDavid du Colombier     mem_swap_byte_rect(row, raster, x * 56, w * 56, h, true);
506*593dc095SDavid du Colombier     bytes_copy_rectangle(row + x * PIXEL_SIZE, raster, base + sourcex * PIXEL_SIZE,
507*593dc095SDavid du Colombier     				sraster, w * PIXEL_SIZE, h);
508*593dc095SDavid du Colombier     mem_swap_byte_rect(row, raster, x * 56, w * 56, h, false);
509*593dc095SDavid du Colombier     return 0;
510*593dc095SDavid du Colombier }
511*593dc095SDavid du Colombier 
512*593dc095SDavid du Colombier #endif /* !arch_is_big_endian */
513