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: gdevm40.c,v 1.3 2005/06/20 08:59:23 igor Exp $ */
18*593dc095SDavid du Colombier /* 40-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_mem40_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_mem40;
33*593dc095SDavid du Colombier static int prev_count = 0;
34*593dc095SDavid du Colombier static gx_color_index prev_colors[256];
35*593dc095SDavid du Colombier # define INCR(v) (++(stats_mem40.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 5
46*593dc095SDavid du Colombier
47*593dc095SDavid du Colombier /* Procedures */
48*593dc095SDavid du Colombier declare_mem_procs(mem_true40_copy_mono, mem_true40_copy_color, mem_true40_fill_rectangle);
49*593dc095SDavid du Colombier
50*593dc095SDavid du Colombier /* The device descriptor. */
51*593dc095SDavid du Colombier const gx_device_memory mem_true40_device =
52*593dc095SDavid du Colombier mem_full_alpha_device("image40", 40, 0, mem_open,
53*593dc095SDavid du Colombier gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
54*593dc095SDavid du Colombier mem_true40_copy_mono, mem_true40_copy_color, mem_true40_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, color)\
65*593dc095SDavid du Colombier byte a = (byte)(color >> 32);\
66*593dc095SDavid du Colombier byte b = (byte)((uint)color >> 24);\
67*593dc095SDavid du Colombier byte c = (byte)((uint)color >> 16);\
68*593dc095SDavid du Colombier byte d = (byte)((uint)color >> 8);\
69*593dc095SDavid du Colombier byte e = (byte)color
70*593dc095SDavid du Colombier /* Put a 40-bit color into the bitmap. */
71*593dc095SDavid du Colombier #define put5(ptr, a, b, c, d, e)\
72*593dc095SDavid du Colombier (ptr)[0] = a, (ptr)[1] = b, (ptr)[2] = c, (ptr)[3] = d, (ptr)[4] = e
73*593dc095SDavid du Colombier /* Put 4 bytes of color into the bitmap. */
74*593dc095SDavid du Colombier #define putw(ptr, wxyz)\
75*593dc095SDavid du Colombier *(bits32 *)(ptr) = (wxyz)
76*593dc095SDavid du Colombier /* Load the 5-word 40-bit-color cache. */
77*593dc095SDavid du Colombier /* Free variables: [m]dev, abcd, bcde, cdea, deab, earc. */
78*593dc095SDavid du Colombier #if arch_is_big_endian
79*593dc095SDavid du Colombier # define set_color40_cache(color, a, b, c, d, e)\
80*593dc095SDavid du Colombier mdev->color40.abcd = abcd = (color) >> 8, \
81*593dc095SDavid du Colombier mdev->color40.bcde = bcde = (abcd << 8) | (e),\
82*593dc095SDavid du Colombier mdev->color40.cdea = cdea = (bcde << 8) | (a),\
83*593dc095SDavid du Colombier mdev->color40.deab = deab = (cdea << 8) | (b),\
84*593dc095SDavid du Colombier mdev->color40.eabc = eabc = (deab << 8) | (c),\
85*593dc095SDavid du Colombier mdev->color40.abcde = (color)
86*593dc095SDavid du Colombier #else
87*593dc095SDavid du Colombier # define set_color40_cache(color, a, b, c, d, e)\
88*593dc095SDavid du Colombier mdev->color40.abcd = abcd =\
89*593dc095SDavid du Colombier ((bits32)(d) << 24) | ((bits32)(c) << 16) |\
90*593dc095SDavid du Colombier ((bits16)(b) << 8) | (a),\
91*593dc095SDavid du Colombier mdev->color40.eabc = eabc = (abcd << 8) | (e),\
92*593dc095SDavid du Colombier mdev->color40.deab = deab = (eabc << 8) | (d),\
93*593dc095SDavid du Colombier mdev->color40.cdea = cdea = (deab << 8) | (c),\
94*593dc095SDavid du Colombier mdev->color40.bcde = bcde = (cdea << 8) | (b),\
95*593dc095SDavid du Colombier mdev->color40.abcde = (color)
96*593dc095SDavid du Colombier #endif
97*593dc095SDavid du Colombier
98*593dc095SDavid du Colombier /* Fill a rectangle with a color. */
99*593dc095SDavid du Colombier private int
mem_true40_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)100*593dc095SDavid du Colombier mem_true40_fill_rectangle(gx_device * dev,
101*593dc095SDavid du Colombier int x, int y, int w, int h, gx_color_index color)
102*593dc095SDavid du Colombier {
103*593dc095SDavid du Colombier gx_device_memory * const mdev = (gx_device_memory *)dev;
104*593dc095SDavid du Colombier declare_unpack_color(a, b, c, d, e, color);
105*593dc095SDavid du Colombier declare_scan_ptr(dest);
106*593dc095SDavid du Colombier
107*593dc095SDavid du Colombier /*
108*593dc095SDavid du Colombier * In order to avoid testing w > 0 and h > 0 twice, we defer
109*593dc095SDavid du Colombier * executing setup_rect, and use fit_fill_xywh instead of
110*593dc095SDavid du Colombier * fit_fill.
111*593dc095SDavid du Colombier */
112*593dc095SDavid du Colombier fit_fill_xywh(dev, x, y, w, h);
113*593dc095SDavid du Colombier INCR(fill);
114*593dc095SDavid du Colombier #ifdef DEBUG
115*593dc095SDavid du Colombier stats_mem40.ftotal += w;
116*593dc095SDavid du Colombier #endif
117*593dc095SDavid du Colombier if (w >= 5) {
118*593dc095SDavid du Colombier if (h <= 0)
119*593dc095SDavid du Colombier return 0;
120*593dc095SDavid du Colombier INCR(fwide);
121*593dc095SDavid du Colombier setup_rect(dest);
122*593dc095SDavid du Colombier if (a == b && b == c && c == d && d == e) {
123*593dc095SDavid du Colombier int bcnt = w * PIXEL_SIZE;
124*593dc095SDavid du Colombier
125*593dc095SDavid du Colombier INCR(fgray[min(w, 100)]);
126*593dc095SDavid du Colombier while (h-- > 0) {
127*593dc095SDavid du Colombier memset(dest, a, bcnt);
128*593dc095SDavid du Colombier inc_ptr(dest, draster);
129*593dc095SDavid du Colombier }
130*593dc095SDavid du Colombier } else {
131*593dc095SDavid du Colombier int x3 = -x & 3, ww = w - x3; /* we know ww >= 2 */
132*593dc095SDavid du Colombier bits32 abcd, bcde, cdea, deab, eabc;
133*593dc095SDavid du Colombier
134*593dc095SDavid du Colombier if (mdev->color40.abcde == color) {
135*593dc095SDavid du Colombier abcd = mdev->color40.abcd;
136*593dc095SDavid du Colombier bcde = mdev->color40.bcde;
137*593dc095SDavid du Colombier cdea = mdev->color40.cdea;
138*593dc095SDavid du Colombier deab = mdev->color40.deab;
139*593dc095SDavid du Colombier eabc = mdev->color40.eabc;
140*593dc095SDavid du Colombier } else {
141*593dc095SDavid du Colombier INCR(fsetc);
142*593dc095SDavid du Colombier set_color40_cache(color, a, b, c, d, e);
143*593dc095SDavid du Colombier }
144*593dc095SDavid du Colombier #ifdef DEBUG
145*593dc095SDavid du Colombier {
146*593dc095SDavid du Colombier int ci;
147*593dc095SDavid du Colombier for (ci = 0; ci < prev_count; ++ci)
148*593dc095SDavid du Colombier if (prev_colors[ci] == color)
149*593dc095SDavid du Colombier break;
150*593dc095SDavid du Colombier INCR(fprevc[ci]);
151*593dc095SDavid du Colombier if (ci == prev_count) {
152*593dc095SDavid du Colombier if (ci < countof(prev_colors))
153*593dc095SDavid du Colombier ++prev_count;
154*593dc095SDavid du Colombier else
155*593dc095SDavid du Colombier --ci;
156*593dc095SDavid du Colombier }
157*593dc095SDavid du Colombier if (ci) {
158*593dc095SDavid du Colombier memmove(&prev_colors[1], &prev_colors[0],
159*593dc095SDavid du Colombier ci * sizeof(prev_colors[0]));
160*593dc095SDavid du Colombier prev_colors[0] = color;
161*593dc095SDavid du Colombier }
162*593dc095SDavid du Colombier }
163*593dc095SDavid du Colombier #endif
164*593dc095SDavid du Colombier INCR(fcolor[min(w, 100)]);
165*593dc095SDavid du Colombier while (h-- > 0) {
166*593dc095SDavid du Colombier register byte *pptr = dest;
167*593dc095SDavid du Colombier int w1 = ww;
168*593dc095SDavid du Colombier
169*593dc095SDavid du Colombier switch (x3) {
170*593dc095SDavid du Colombier case 1:
171*593dc095SDavid du Colombier pptr[0] = a;
172*593dc095SDavid du Colombier putw(pptr + 1, bcde);
173*593dc095SDavid du Colombier pptr += PIXEL_SIZE;
174*593dc095SDavid du Colombier break;
175*593dc095SDavid du Colombier case 2:
176*593dc095SDavid du Colombier pptr[0] = a;
177*593dc095SDavid du Colombier pptr[1] = b;
178*593dc095SDavid du Colombier putw(pptr + 2, cdea);
179*593dc095SDavid du Colombier putw(pptr + 6, bcde);
180*593dc095SDavid du Colombier pptr += 2 * PIXEL_SIZE;
181*593dc095SDavid du Colombier break;
182*593dc095SDavid du Colombier case 3:
183*593dc095SDavid du Colombier pptr[0] = a;
184*593dc095SDavid du Colombier pptr[1] = b;
185*593dc095SDavid du Colombier pptr[2] = c;
186*593dc095SDavid du Colombier putw(pptr + 3, deab);
187*593dc095SDavid du Colombier putw(pptr + 7, cdea);
188*593dc095SDavid du Colombier putw(pptr + 11, bcde);
189*593dc095SDavid du Colombier pptr += 3 * PIXEL_SIZE;
190*593dc095SDavid du Colombier break;
191*593dc095SDavid du Colombier case 0:
192*593dc095SDavid du Colombier ;
193*593dc095SDavid du Colombier }
194*593dc095SDavid du Colombier while (w1 >= 4) {
195*593dc095SDavid du Colombier putw(pptr, abcd);
196*593dc095SDavid du Colombier putw(pptr + 4, eabc);
197*593dc095SDavid du Colombier putw(pptr + 8, deab);
198*593dc095SDavid du Colombier putw(pptr + 12, cdea);
199*593dc095SDavid du Colombier putw(pptr + 16, bcde);
200*593dc095SDavid du Colombier pptr += 4 * PIXEL_SIZE;
201*593dc095SDavid du Colombier w1 -= 4;
202*593dc095SDavid du Colombier }
203*593dc095SDavid du Colombier switch (w1) {
204*593dc095SDavid du Colombier case 1:
205*593dc095SDavid du Colombier putw(pptr, abcd);
206*593dc095SDavid du Colombier pptr[4] = e;
207*593dc095SDavid du Colombier break;
208*593dc095SDavid du Colombier case 2:
209*593dc095SDavid du Colombier putw(pptr, abcd);
210*593dc095SDavid du Colombier putw(pptr + 4, eabc);
211*593dc095SDavid du Colombier pptr[8] = d;
212*593dc095SDavid du Colombier pptr[9] = e;
213*593dc095SDavid du Colombier break;
214*593dc095SDavid du Colombier case 3:
215*593dc095SDavid du Colombier putw(pptr, abcd);
216*593dc095SDavid du Colombier putw(pptr + 4, eabc);
217*593dc095SDavid du Colombier putw(pptr + 8, deab);
218*593dc095SDavid du Colombier pptr[12] = c;
219*593dc095SDavid du Colombier pptr[13] = d;
220*593dc095SDavid du Colombier pptr[14] = e;
221*593dc095SDavid du Colombier break;
222*593dc095SDavid du Colombier case 0:
223*593dc095SDavid du Colombier ;
224*593dc095SDavid du Colombier }
225*593dc095SDavid du Colombier inc_ptr(dest, draster);
226*593dc095SDavid du Colombier }
227*593dc095SDavid du Colombier }
228*593dc095SDavid du Colombier } else if (h > 0) { /* w < 5 */
229*593dc095SDavid du Colombier INCR(fnarrow[max(w, 0)]);
230*593dc095SDavid du Colombier setup_rect(dest);
231*593dc095SDavid du Colombier switch (w) {
232*593dc095SDavid du Colombier case 4:
233*593dc095SDavid du Colombier do {
234*593dc095SDavid du Colombier dest[15] = dest[10] = dest[5] = dest[0] = a;
235*593dc095SDavid du Colombier dest[16] = dest[11] = dest[6] = dest[1] = b;
236*593dc095SDavid du Colombier dest[17] = dest[12] = dest[7] = dest[2] = c;
237*593dc095SDavid du Colombier dest[18] = dest[13] = dest[8] = dest[3] = d;
238*593dc095SDavid du Colombier dest[19] = dest[14] = dest[9] = dest[4] = e;
239*593dc095SDavid du Colombier inc_ptr(dest, draster);
240*593dc095SDavid du Colombier }
241*593dc095SDavid du Colombier while (--h);
242*593dc095SDavid du Colombier break;
243*593dc095SDavid du Colombier case 3:
244*593dc095SDavid du Colombier do {
245*593dc095SDavid du Colombier dest[10] = dest[5] = dest[0] = a;
246*593dc095SDavid du Colombier dest[11] = dest[6] = dest[1] = b;
247*593dc095SDavid du Colombier dest[12] = dest[7] = dest[2] = c;
248*593dc095SDavid du Colombier dest[13] = dest[8] = dest[3] = d;
249*593dc095SDavid du Colombier dest[14] = dest[9] = dest[4] = e;
250*593dc095SDavid du Colombier inc_ptr(dest, draster);
251*593dc095SDavid du Colombier }
252*593dc095SDavid du Colombier while (--h);
253*593dc095SDavid du Colombier break;
254*593dc095SDavid du Colombier case 2:
255*593dc095SDavid du Colombier do {
256*593dc095SDavid du Colombier dest[5] = dest[0] = a;
257*593dc095SDavid du Colombier dest[6] = dest[1] = b;
258*593dc095SDavid du Colombier dest[7] = dest[2] = c;
259*593dc095SDavid du Colombier dest[8] = dest[3] = d;
260*593dc095SDavid du Colombier dest[9] = dest[4] = e;
261*593dc095SDavid du Colombier inc_ptr(dest, draster);
262*593dc095SDavid du Colombier }
263*593dc095SDavid du Colombier while (--h);
264*593dc095SDavid du Colombier break;
265*593dc095SDavid du Colombier case 1:
266*593dc095SDavid du Colombier do {
267*593dc095SDavid du Colombier dest[0] = a; dest[1] = b; dest[2] = c; dest[3] = d; dest[4] = e;
268*593dc095SDavid du Colombier inc_ptr(dest, draster);
269*593dc095SDavid du Colombier }
270*593dc095SDavid du Colombier while (--h);
271*593dc095SDavid du Colombier break;
272*593dc095SDavid du Colombier case 0:
273*593dc095SDavid du Colombier default:
274*593dc095SDavid du Colombier ;
275*593dc095SDavid du Colombier }
276*593dc095SDavid du Colombier }
277*593dc095SDavid du Colombier return 0;
278*593dc095SDavid du Colombier }
279*593dc095SDavid du Colombier
280*593dc095SDavid du Colombier /* Copy a monochrome bitmap. */
281*593dc095SDavid du Colombier private int
mem_true40_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)282*593dc095SDavid du Colombier mem_true40_copy_mono(gx_device * dev,
283*593dc095SDavid du Colombier const byte * base, int sourcex, int sraster, gx_bitmap_id id,
284*593dc095SDavid du Colombier int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
285*593dc095SDavid du Colombier {
286*593dc095SDavid du Colombier gx_device_memory * const mdev = (gx_device_memory *)dev;
287*593dc095SDavid du Colombier const byte *line;
288*593dc095SDavid du Colombier int sbit;
289*593dc095SDavid du Colombier int first_bit;
290*593dc095SDavid du Colombier
291*593dc095SDavid du Colombier declare_scan_ptr(dest);
292*593dc095SDavid du Colombier
293*593dc095SDavid du Colombier fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
294*593dc095SDavid du Colombier setup_rect(dest);
295*593dc095SDavid du Colombier line = base + (sourcex >> 3);
296*593dc095SDavid du Colombier sbit = sourcex & 7;
297*593dc095SDavid du Colombier first_bit = 0x80 >> sbit;
298*593dc095SDavid du Colombier if (zero != gx_no_color_index) { /* Loop for halftones or inverted masks */
299*593dc095SDavid du Colombier /* (never used). */
300*593dc095SDavid du Colombier declare_unpack_color(a0, b0, c0, d0, e0, zero);
301*593dc095SDavid du Colombier declare_unpack_color(a1, b1, c1, d1, e1, one);
302*593dc095SDavid du Colombier while (h-- > 0) {
303*593dc095SDavid du Colombier register byte *pptr = dest;
304*593dc095SDavid du Colombier const byte *sptr = line;
305*593dc095SDavid du Colombier register int sbyte = *sptr++;
306*593dc095SDavid du Colombier register int bit = first_bit;
307*593dc095SDavid du Colombier int count = w;
308*593dc095SDavid du Colombier
309*593dc095SDavid du Colombier do {
310*593dc095SDavid du Colombier if (sbyte & bit) {
311*593dc095SDavid du Colombier if (one != gx_no_color_index)
312*593dc095SDavid du Colombier put5(pptr, a1, b1, c1, d1, e1);
313*593dc095SDavid du Colombier } else
314*593dc095SDavid du Colombier put5(pptr, a0, b0, c0, d0, e0);
315*593dc095SDavid du Colombier pptr += PIXEL_SIZE;
316*593dc095SDavid du Colombier if ((bit >>= 1) == 0)
317*593dc095SDavid du Colombier bit = 0x80, sbyte = *sptr++;
318*593dc095SDavid du Colombier }
319*593dc095SDavid du Colombier while (--count > 0);
320*593dc095SDavid du Colombier line += sraster;
321*593dc095SDavid du Colombier inc_ptr(dest, draster);
322*593dc095SDavid du Colombier }
323*593dc095SDavid du Colombier } else if (one != gx_no_color_index) { /* Loop for character and pattern masks. */
324*593dc095SDavid du Colombier /* This is used heavily. */
325*593dc095SDavid du Colombier declare_unpack_color(a1, b1, c1, d1, e1, one);
326*593dc095SDavid du Colombier int first_mask = first_bit << 1;
327*593dc095SDavid du Colombier int first_count, first_skip;
328*593dc095SDavid du Colombier
329*593dc095SDavid du Colombier if (sbit + w > 8)
330*593dc095SDavid du Colombier first_mask -= 1,
331*593dc095SDavid du Colombier first_count = 8 - sbit;
332*593dc095SDavid du Colombier else
333*593dc095SDavid du Colombier first_mask -= first_mask >> w,
334*593dc095SDavid du Colombier first_count = w;
335*593dc095SDavid du Colombier first_skip = first_count * PIXEL_SIZE;
336*593dc095SDavid du Colombier while (h-- > 0) {
337*593dc095SDavid du Colombier register byte *pptr = dest;
338*593dc095SDavid du Colombier const byte *sptr = line;
339*593dc095SDavid du Colombier register int sbyte = *sptr++ & first_mask;
340*593dc095SDavid du Colombier int count = w - first_count;
341*593dc095SDavid du Colombier
342*593dc095SDavid du Colombier if (sbyte) {
343*593dc095SDavid du Colombier register int bit = first_bit;
344*593dc095SDavid du Colombier
345*593dc095SDavid du Colombier do {
346*593dc095SDavid du Colombier if (sbyte & bit)
347*593dc095SDavid du Colombier put5(pptr, a1, b1, c1, d1, e1);
348*593dc095SDavid du Colombier pptr += PIXEL_SIZE;
349*593dc095SDavid du Colombier }
350*593dc095SDavid du Colombier while ((bit >>= 1) & first_mask);
351*593dc095SDavid du Colombier } else
352*593dc095SDavid du Colombier pptr += first_skip;
353*593dc095SDavid du Colombier while (count >= 8) {
354*593dc095SDavid du Colombier sbyte = *sptr++;
355*593dc095SDavid du Colombier if (sbyte & 0xf0) {
356*593dc095SDavid du Colombier if (sbyte & 0x80)
357*593dc095SDavid du Colombier put5(pptr, a1, b1, c1, d1, e1);
358*593dc095SDavid du Colombier if (sbyte & 0x40)
359*593dc095SDavid du Colombier put5(pptr + 5, a1, b1, c1, d1, e1);
360*593dc095SDavid du Colombier if (sbyte & 0x20)
361*593dc095SDavid du Colombier put5(pptr + 10, a1, b1, c1, d1, e1);
362*593dc095SDavid du Colombier if (sbyte & 0x10)
363*593dc095SDavid du Colombier put5(pptr + 15, a1, b1, c1, d1, e1);
364*593dc095SDavid du Colombier }
365*593dc095SDavid du Colombier if (sbyte & 0xf) {
366*593dc095SDavid du Colombier if (sbyte & 8)
367*593dc095SDavid du Colombier put5(pptr + 20, a1, b1, c1, d1, e1);
368*593dc095SDavid du Colombier if (sbyte & 4)
369*593dc095SDavid du Colombier put5(pptr + 25, a1, b1, c1, d1, e1);
370*593dc095SDavid du Colombier if (sbyte & 2)
371*593dc095SDavid du Colombier put5(pptr + 30, a1, b1, c1, d1, e1);
372*593dc095SDavid du Colombier if (sbyte & 1)
373*593dc095SDavid du Colombier put5(pptr + 35, a1, b1, c1, d1, e1);
374*593dc095SDavid du Colombier }
375*593dc095SDavid du Colombier pptr += 8 * PIXEL_SIZE;
376*593dc095SDavid du Colombier count -= 8;
377*593dc095SDavid du Colombier }
378*593dc095SDavid du Colombier if (count > 0) {
379*593dc095SDavid du Colombier register int bit = 0x80;
380*593dc095SDavid du Colombier
381*593dc095SDavid du Colombier sbyte = *sptr++;
382*593dc095SDavid du Colombier do {
383*593dc095SDavid du Colombier if (sbyte & bit)
384*593dc095SDavid du Colombier put5(pptr, a1, b1, c1, d1, e1);
385*593dc095SDavid du Colombier pptr += PIXEL_SIZE;
386*593dc095SDavid du Colombier bit >>= 1;
387*593dc095SDavid du Colombier }
388*593dc095SDavid du Colombier while (--count > 0);
389*593dc095SDavid du Colombier }
390*593dc095SDavid du Colombier line += sraster;
391*593dc095SDavid du Colombier inc_ptr(dest, draster);
392*593dc095SDavid du Colombier }
393*593dc095SDavid du Colombier }
394*593dc095SDavid du Colombier return 0;
395*593dc095SDavid du Colombier }
396*593dc095SDavid du Colombier
397*593dc095SDavid du Colombier /* Copy a color bitmap. */
398*593dc095SDavid du Colombier private int
mem_true40_copy_color(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h)399*593dc095SDavid du Colombier mem_true40_copy_color(gx_device * dev,
400*593dc095SDavid du Colombier const byte * base, int sourcex, int sraster, gx_bitmap_id id,
401*593dc095SDavid du Colombier int x, int y, int w, int h)
402*593dc095SDavid du Colombier {
403*593dc095SDavid du Colombier gx_device_memory * const mdev = (gx_device_memory *)dev;
404*593dc095SDavid du Colombier
405*593dc095SDavid du Colombier fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
406*593dc095SDavid du Colombier mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
407*593dc095SDavid du Colombier return 0;
408*593dc095SDavid du Colombier }
409*593dc095SDavid du Colombier
410*593dc095SDavid du Colombier /* ================ "Word"-oriented device ================ */
411*593dc095SDavid du Colombier
412*593dc095SDavid du Colombier /* Note that on a big-endian machine, this is the same as the */
413*593dc095SDavid du Colombier /* standard byte-oriented-device. */
414*593dc095SDavid du Colombier
415*593dc095SDavid du Colombier #if !arch_is_big_endian
416*593dc095SDavid du Colombier
417*593dc095SDavid du Colombier /* Procedures */
418*593dc095SDavid du Colombier declare_mem_procs(mem40_word_copy_mono, mem40_word_copy_color, mem40_word_fill_rectangle);
419*593dc095SDavid du Colombier
420*593dc095SDavid du Colombier /* Here is the device descriptor. */
421*593dc095SDavid du Colombier const gx_device_memory mem_true40_word_device =
422*593dc095SDavid du Colombier mem_full_device("image40w", 40, 0, mem_open,
423*593dc095SDavid du Colombier gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
424*593dc095SDavid du Colombier mem40_word_copy_mono, mem40_word_copy_color, mem40_word_fill_rectangle,
425*593dc095SDavid du Colombier gx_default_map_cmyk_color, gx_default_strip_tile_rectangle,
426*593dc095SDavid du Colombier gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
427*593dc095SDavid du Colombier
428*593dc095SDavid du Colombier /* Fill a rectangle with a color. */
429*593dc095SDavid du Colombier private int
mem40_word_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)430*593dc095SDavid du Colombier mem40_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
431*593dc095SDavid du Colombier gx_color_index color)
432*593dc095SDavid du Colombier {
433*593dc095SDavid du Colombier gx_device_memory * const mdev = (gx_device_memory *)dev;
434*593dc095SDavid du Colombier byte *base;
435*593dc095SDavid du Colombier uint raster;
436*593dc095SDavid du Colombier
437*593dc095SDavid du Colombier fit_fill(dev, x, y, w, h);
438*593dc095SDavid du Colombier base = scan_line_base(mdev, y);
439*593dc095SDavid du Colombier raster = mdev->raster;
440*593dc095SDavid du Colombier mem_swap_byte_rect(base, raster, x * 40, w * 40, h, true);
441*593dc095SDavid du Colombier mem_true40_fill_rectangle(dev, x, y, w, h, color);
442*593dc095SDavid du Colombier mem_swap_byte_rect(base, raster, x * 40, w * 40, h, false);
443*593dc095SDavid du Colombier return 0;
444*593dc095SDavid du Colombier }
445*593dc095SDavid du Colombier
446*593dc095SDavid du Colombier /* Copy a bitmap. */
447*593dc095SDavid du Colombier private int
mem40_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)448*593dc095SDavid du Colombier mem40_word_copy_mono(gx_device * dev,
449*593dc095SDavid du Colombier const byte * base, int sourcex, int sraster, gx_bitmap_id id,
450*593dc095SDavid du Colombier int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
451*593dc095SDavid du Colombier {
452*593dc095SDavid du Colombier gx_device_memory * const mdev = (gx_device_memory *)dev;
453*593dc095SDavid du Colombier byte *row;
454*593dc095SDavid du Colombier uint raster;
455*593dc095SDavid du Colombier bool store;
456*593dc095SDavid du Colombier
457*593dc095SDavid du Colombier fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
458*593dc095SDavid du Colombier row = scan_line_base(mdev, y);
459*593dc095SDavid du Colombier raster = mdev->raster;
460*593dc095SDavid du Colombier store = (zero != gx_no_color_index && one != gx_no_color_index);
461*593dc095SDavid du Colombier mem_swap_byte_rect(row, raster, x * 40, w * 40, h, store);
462*593dc095SDavid du Colombier mem_true40_copy_mono(dev, base, sourcex, sraster, id,
463*593dc095SDavid du Colombier x, y, w, h, zero, one);
464*593dc095SDavid du Colombier mem_swap_byte_rect(row, raster, x * 40, w * 40, h, false);
465*593dc095SDavid du Colombier return 0;
466*593dc095SDavid du Colombier }
467*593dc095SDavid du Colombier
468*593dc095SDavid du Colombier /* Copy a color bitmap. */
469*593dc095SDavid du Colombier private int
mem40_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)470*593dc095SDavid du Colombier mem40_word_copy_color(gx_device * dev,
471*593dc095SDavid du Colombier const byte * base, int sourcex, int sraster, gx_bitmap_id id,
472*593dc095SDavid du Colombier int x, int y, int w, int h)
473*593dc095SDavid du Colombier {
474*593dc095SDavid du Colombier gx_device_memory * const mdev = (gx_device_memory *)dev;
475*593dc095SDavid du Colombier byte *row;
476*593dc095SDavid du Colombier uint raster;
477*593dc095SDavid du Colombier
478*593dc095SDavid du Colombier fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
479*593dc095SDavid du Colombier row = scan_line_base(mdev, y);
480*593dc095SDavid du Colombier raster = mdev->raster;
481*593dc095SDavid du Colombier mem_swap_byte_rect(row, raster, x * 40, w * 40, h, true);
482*593dc095SDavid du Colombier bytes_copy_rectangle(row + x * PIXEL_SIZE, raster, base + sourcex * PIXEL_SIZE,
483*593dc095SDavid du Colombier sraster, w * PIXEL_SIZE, h);
484*593dc095SDavid du Colombier mem_swap_byte_rect(row, raster, x * 40, w * 40, h, false);
485*593dc095SDavid du Colombier return 0;
486*593dc095SDavid du Colombier }
487*593dc095SDavid du Colombier
488*593dc095SDavid du Colombier #endif /* !arch_is_big_endian */
489