xref: /csrg-svn/sys/sparc/rcons/raster_op.c (revision 55131)
1*55131Storek /*-
2*55131Storek  * Copyright (c) 1991 The Regents of the University of California.
3*55131Storek  * All rights reserved.
4*55131Storek  *
5*55131Storek  * This code is derived from software contributed to the Computer Systems
6*55131Storek  * Engineering Group at Lawrence Berkeley Laboratory and to the University
7*55131Storek  * of California at Berkeley by Jef Poskanzer.
8*55131Storek  *
9*55131Storek  * %sccs.include.redist.c%
10*55131Storek  *
11*55131Storek  *	@(#)raster_op.c	7.1 (Berkeley) 07/13/92
12*55131Storek  *
13*55131Storek  * from: $Header: raster_op.c,v 1.22 92/06/17 08:14:44 torek Exp $
14*55131Storek  */
15*55131Storek 
16*55131Storek /*
17*55131Storek  * Bitblit routine for raster library.
18*55131Storek  *
19*55131Storek  * This raster-op is machined to exacting tolerances by skilled native
20*55131Storek  * craftsmen with pride in their work.
21*55131Storek  *
22*55131Storek  * The various cases are broken down like this:
23*55131Storek  *
24*55131Storek  *   src required
25*55131Storek  *       1-bit to 1-bit
26*55131Storek  *       1-bit to 8-bits
27*55131Storek  *       8-bits to 8-bits
28*55131Storek  *   no src required
29*55131Storek  *       1-bit no-src
30*55131Storek  *       8-bits no-src
31*55131Storek  */
32*55131Storek 
33*55131Storek #ifdef KERNEL
34*55131Storek #include "sys/types.h"
35*55131Storek #else
36*55131Storek #include <sys/types.h>
37*55131Storek #endif
38*55131Storek #include "raster.h"
39*55131Storek 
40*55131Storek /* CONFIGURE: To save on executable size, you can configure out the seldom-used
41*55131Storek ** logical operations.  With this variable set, the only operations implemented
42*55131Storek ** are: RAS_SRC, RAS_CLEAR, RAS_SET, RAS_INVERT, RAS_XOR, RAS_INVERTSRC.
43*55131Storek */
44*55131Storek #ifdef KERNEL
45*55131Storek #define PARTIAL_LOGICAL_OPS
46*55131Storek #endif
47*55131Storek 
48*55131Storek /* CONFIGURE: bcopy() is supposed to be the ultimately fastest way to move
49*55131Storek ** bytes, overlapping or not, ignoring the startup cost.  Unfortunately
50*55131Storek ** this is not true on some systems.  For example, on a Sun 3 running
51*55131Storek ** SunOS 3.5, bcopy() is about five times slower than a simple for loop
52*55131Storek ** on overlapping copies.  And on a 4.1.1 SPARC, bcopy() is about 2/3rds
53*55131Storek ** as fast on backwards overlaps.  So, only define this if your bcopy is ok.
54*55131Storek */
55*55131Storek #undef BCOPY_FASTER
56*55131Storek 
57*55131Storek /* End of configurable definitions. */
58*55131Storek 
59*55131Storek 
60*55131Storek /* Definitions. */
61*55131Storek 
62*55131Storek /* Raster-op macros.  These encapsulate the switch statements and so make
63*55131Storek ** the source code 16 times smaller.  The pre and pst args are code
64*55131Storek ** fragments to put before and after the assignment in each case.  They
65*55131Storek ** can be the beginning and end of a loop.  If the pst fragment includes a
66*55131Storek ** masked assignment, for example to handle the left or right edge cases,
67*55131Storek ** a good optimizing compiler will simplify the boolean expressions very
68*55131Storek ** nicely - both cc and gcc on the SPARC will do this.
69*55131Storek */
70*55131Storek 
71*55131Storek #ifndef PARTIAL_LOGICAL_OPS
72*55131Storek 
73*55131Storek #define ROP_DST(op,pre,d,pst) \
74*55131Storek     switch ( op ) \
75*55131Storek 	{ \
76*55131Storek 	case RAS_CLEAR: \
77*55131Storek 	pre \
78*55131Storek 	(d) = 0; \
79*55131Storek 	pst \
80*55131Storek 	break; \
81*55131Storek 	case RAS_INVERT: \
82*55131Storek 	pre \
83*55131Storek 	(d) = ~(d); \
84*55131Storek 	pst \
85*55131Storek 	break; \
86*55131Storek 	case RAS_DST: \
87*55131Storek 	/* noop */ \
88*55131Storek 	break; \
89*55131Storek 	case RAS_SET: \
90*55131Storek 	pre \
91*55131Storek 	(d) = ~0; \
92*55131Storek 	pst \
93*55131Storek 	break; \
94*55131Storek 	default: \
95*55131Storek 	return -1; \
96*55131Storek 	}
97*55131Storek 
98*55131Storek #define ROP_DSTCOLOR(op,pre,d,c,pst) \
99*55131Storek     switch ( op ) \
100*55131Storek 	{ \
101*55131Storek 	case RAS_CLEAR: \
102*55131Storek 	pre \
103*55131Storek 	(d) = 0; \
104*55131Storek 	pst \
105*55131Storek 	break; \
106*55131Storek 	case RAS_INVERT: \
107*55131Storek 	pre \
108*55131Storek 	(d) = ~(d); \
109*55131Storek 	pst \
110*55131Storek 	break; \
111*55131Storek 	case RAS_DST: \
112*55131Storek 	/* noop */ \
113*55131Storek 	break; \
114*55131Storek 	case RAS_SET: \
115*55131Storek 	pre \
116*55131Storek 	(d) = (c); \
117*55131Storek 	pst \
118*55131Storek 	break; \
119*55131Storek 	default: \
120*55131Storek 	return -1; \
121*55131Storek 	}
122*55131Storek 
123*55131Storek #define ROP_SRCDST(op,pre,s,d,pst) \
124*55131Storek     switch ( op ) \
125*55131Storek 	{ \
126*55131Storek 	case RAS_NOTOR: \
127*55131Storek 	pre \
128*55131Storek 	(d) = ~( (s) | (d) ); \
129*55131Storek 	pst \
130*55131Storek 	break; \
131*55131Storek 	case RAS_NOTSRC_AND_DST: \
132*55131Storek 	pre \
133*55131Storek 	(d) = ~(s) & (d); \
134*55131Storek 	pst \
135*55131Storek 	break; \
136*55131Storek 	case RAS_INVERTSRC: \
137*55131Storek 	pre \
138*55131Storek 	(d) = ~(s); \
139*55131Storek 	pst \
140*55131Storek 	break; \
141*55131Storek 	case RAS_SRC_AND_NOTDST: \
142*55131Storek 	pre \
143*55131Storek 	(d) = (s) & ~(d); \
144*55131Storek 	pst \
145*55131Storek 	break; \
146*55131Storek 	case RAS_XOR: \
147*55131Storek 	pre \
148*55131Storek 	(d) = (s) ^ (d); \
149*55131Storek 	pst \
150*55131Storek 	break; \
151*55131Storek 	case RAS_NOTAND: \
152*55131Storek 	pre \
153*55131Storek 	(d) = ~( (s) & (d) ); \
154*55131Storek 	pst \
155*55131Storek 	break; \
156*55131Storek 	case RAS_AND: \
157*55131Storek 	pre \
158*55131Storek 	(d) = (s) & (d); \
159*55131Storek 	pst \
160*55131Storek 	break; \
161*55131Storek 	case RAS_NOTXOR: \
162*55131Storek 	pre \
163*55131Storek 	(d) = ~( (s) ^ (d) ); \
164*55131Storek 	pst \
165*55131Storek 	break; \
166*55131Storek 	case RAS_NOTSRC_OR_DST: \
167*55131Storek 	pre \
168*55131Storek 	(d) = ~(s) | (d); \
169*55131Storek 	pst \
170*55131Storek 	break; \
171*55131Storek 	case RAS_SRC: \
172*55131Storek 	pre \
173*55131Storek 	(d) = (s); \
174*55131Storek 	pst \
175*55131Storek 	break; \
176*55131Storek 	case RAS_SRC_OR_NOTDST: \
177*55131Storek 	pre \
178*55131Storek 	(d) = (s) | ~(d); \
179*55131Storek 	pst \
180*55131Storek 	break; \
181*55131Storek 	case RAS_OR: \
182*55131Storek 	pre \
183*55131Storek 	(d) = (s) | (d); \
184*55131Storek 	pst \
185*55131Storek 	break; \
186*55131Storek 	default: \
187*55131Storek 	return -1; \
188*55131Storek 	}
189*55131Storek 
190*55131Storek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
191*55131Storek     switch ( op ) \
192*55131Storek 	{ \
193*55131Storek 	case RAS_NOTOR: \
194*55131Storek 	pre \
195*55131Storek 	if ( s ) \
196*55131Storek 	    (d) = ~( (c) | (d) ); \
197*55131Storek 	else \
198*55131Storek 	    (d) = ~(d); \
199*55131Storek 	pst \
200*55131Storek 	break; \
201*55131Storek 	case RAS_NOTSRC_AND_DST: \
202*55131Storek 	pre \
203*55131Storek 	if ( s ) \
204*55131Storek 	    (d) = ~(c) & (d); \
205*55131Storek 	pst \
206*55131Storek 	break; \
207*55131Storek 	case RAS_INVERTSRC: \
208*55131Storek 	pre \
209*55131Storek 	if ( s ) \
210*55131Storek 	    (d) = ~(c); \
211*55131Storek 	else \
212*55131Storek 	    (d) = ~0; \
213*55131Storek 	pst \
214*55131Storek 	break; \
215*55131Storek 	case RAS_SRC_AND_NOTDST: \
216*55131Storek 	pre \
217*55131Storek 	if ( s ) \
218*55131Storek 	    (d) = (c) & ~(d); \
219*55131Storek 	else \
220*55131Storek 	    (d) = 0; \
221*55131Storek 	pst \
222*55131Storek 	break; \
223*55131Storek 	case RAS_XOR: \
224*55131Storek 	pre \
225*55131Storek 	if ( s ) \
226*55131Storek 	    (d) = (c) ^ (d); \
227*55131Storek 	pst \
228*55131Storek 	break; \
229*55131Storek 	case RAS_NOTAND: \
230*55131Storek 	pre \
231*55131Storek 	if ( s ) \
232*55131Storek 	    (d) = ~( (c) & (d) ); \
233*55131Storek 	else \
234*55131Storek 	    (d) = ~0; \
235*55131Storek 	pst \
236*55131Storek 	break; \
237*55131Storek 	case RAS_AND: \
238*55131Storek 	pre \
239*55131Storek 	if ( s ) \
240*55131Storek 	    (d) = (c) & (d); \
241*55131Storek 	else \
242*55131Storek 	    (d) = 0; \
243*55131Storek 	pst \
244*55131Storek 	break; \
245*55131Storek 	case RAS_NOTXOR: \
246*55131Storek 	pre \
247*55131Storek 	if ( s ) \
248*55131Storek 	    (d) = ~( (c) ^ (d) ); \
249*55131Storek 	else \
250*55131Storek 	    (d) = ~(d); \
251*55131Storek 	pst \
252*55131Storek 	break; \
253*55131Storek 	case RAS_NOTSRC_OR_DST: \
254*55131Storek 	pre \
255*55131Storek 	if ( s ) \
256*55131Storek 	    (d) = ~(c) | (d); \
257*55131Storek 	else \
258*55131Storek 	    (d) = ~0; \
259*55131Storek 	pst \
260*55131Storek 	break; \
261*55131Storek 	case RAS_SRC: \
262*55131Storek 	pre \
263*55131Storek 	if ( s ) \
264*55131Storek 	    (d) = (c); \
265*55131Storek 	else \
266*55131Storek 	    (d) = 0; \
267*55131Storek 	pst \
268*55131Storek 	break; \
269*55131Storek 	case RAS_SRC_OR_NOTDST: \
270*55131Storek 	pre \
271*55131Storek 	if ( s ) \
272*55131Storek 	    (d) = (c) | ~(d); \
273*55131Storek 	else \
274*55131Storek 	    (d) = ~(d); \
275*55131Storek 	pst \
276*55131Storek 	break; \
277*55131Storek 	case RAS_OR: \
278*55131Storek 	pre \
279*55131Storek 	if ( s ) \
280*55131Storek 	    (d) = (c) | (d); \
281*55131Storek 	pst \
282*55131Storek 	break; \
283*55131Storek 	default: \
284*55131Storek 	return -1; \
285*55131Storek 	}
286*55131Storek 
287*55131Storek #else /*PARTIAL_LOGICAL_OPS*/
288*55131Storek 
289*55131Storek #define ROP_DST(op,pre,d,pst) \
290*55131Storek     switch ( op ) \
291*55131Storek 	{ \
292*55131Storek 	case RAS_CLEAR: \
293*55131Storek 	pre \
294*55131Storek 	(d) = 0; \
295*55131Storek 	pst \
296*55131Storek 	break; \
297*55131Storek 	case RAS_INVERT: \
298*55131Storek 	pre \
299*55131Storek 	(d) = ~(d); \
300*55131Storek 	pst \
301*55131Storek 	break; \
302*55131Storek 	case RAS_SET: \
303*55131Storek 	pre \
304*55131Storek 	(d) = ~0; \
305*55131Storek 	pst \
306*55131Storek 	break; \
307*55131Storek 	default: \
308*55131Storek 	return -1; \
309*55131Storek 	}
310*55131Storek 
311*55131Storek #define ROP_DSTCOLOR(op,pre,d,c,pst) \
312*55131Storek     switch ( op ) \
313*55131Storek 	{ \
314*55131Storek 	case RAS_CLEAR: \
315*55131Storek 	pre \
316*55131Storek 	(d) = 0; \
317*55131Storek 	pst \
318*55131Storek 	break; \
319*55131Storek 	case RAS_INVERT: \
320*55131Storek 	pre \
321*55131Storek 	(d) = ~(d); \
322*55131Storek 	pst \
323*55131Storek 	break; \
324*55131Storek 	case RAS_SET: \
325*55131Storek 	pre \
326*55131Storek 	(d) = (c); \
327*55131Storek 	pst \
328*55131Storek 	break; \
329*55131Storek 	default: \
330*55131Storek 	return -1; \
331*55131Storek 	}
332*55131Storek 
333*55131Storek #define ROP_SRCDST(op,pre,s,d,pst) \
334*55131Storek     switch ( op ) \
335*55131Storek 	{ \
336*55131Storek 	case RAS_INVERTSRC: \
337*55131Storek 	pre \
338*55131Storek 	(d) = ~(s); \
339*55131Storek 	pst \
340*55131Storek 	break; \
341*55131Storek 	case RAS_XOR: \
342*55131Storek 	pre \
343*55131Storek 	(d) = (s) ^ (d); \
344*55131Storek 	pst \
345*55131Storek 	break; \
346*55131Storek 	case RAS_SRC: \
347*55131Storek 	pre \
348*55131Storek 	(d) = (s); \
349*55131Storek 	pst \
350*55131Storek 	break; \
351*55131Storek 	default: \
352*55131Storek 	return -1; \
353*55131Storek 	}
354*55131Storek 
355*55131Storek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
356*55131Storek     switch ( op ) \
357*55131Storek 	{ \
358*55131Storek 	case RAS_INVERTSRC: \
359*55131Storek 	pre \
360*55131Storek 	if ( s ) \
361*55131Storek 	    (d) = ~(c); \
362*55131Storek 	else \
363*55131Storek 	    (d) = ~0; \
364*55131Storek 	pst \
365*55131Storek 	break; \
366*55131Storek 	case RAS_XOR: \
367*55131Storek 	pre \
368*55131Storek 	if ( s ) \
369*55131Storek 	    (d) = (c) ^ (d); \
370*55131Storek 	pst \
371*55131Storek 	break; \
372*55131Storek 	case RAS_SRC: \
373*55131Storek 	pre \
374*55131Storek 	if ( s ) \
375*55131Storek 	    (d) = (c); \
376*55131Storek 	else \
377*55131Storek 	    (d) = 0; \
378*55131Storek 	pst \
379*55131Storek 	break; \
380*55131Storek 	default: \
381*55131Storek 	return -1; \
382*55131Storek 	}
383*55131Storek 
384*55131Storek #endif /*PARTIAL_LOGICAL_OPS*/
385*55131Storek 
386*55131Storek 
387*55131Storek /* Variables. */
388*55131Storek 
389*55131Storek static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 };
390*55131Storek /*                       CLEAR          INVERT          DST            SET */
391*55131Storek 
392*55131Storek #ifdef MSBIT_FIRST
393*55131Storek 
394*55131Storek u_long raster_bitmask[32] = {
395*55131Storek     0x80000000, 0x40000000, 0x20000000, 0x10000000,
396*55131Storek     0x08000000, 0x04000000, 0x02000000, 0x01000000,
397*55131Storek     0x00800000, 0x00400000, 0x00200000, 0x00100000,
398*55131Storek     0x00080000, 0x00040000, 0x00020000, 0x00010000,
399*55131Storek     0x00008000, 0x00004000, 0x00002000, 0x00001000,
400*55131Storek     0x00000800, 0x00000400, 0x00000200, 0x00000100,
401*55131Storek     0x00000080, 0x00000040, 0x00000020, 0x00000010,
402*55131Storek     0x00000008, 0x00000004, 0x00000002, 0x00000001 };
403*55131Storek 
404*55131Storek #ifdef MSBYTE_FIRST
405*55131Storek static u_long leftmask[32] = {
406*55131Storek     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
407*55131Storek     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
408*55131Storek     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
409*55131Storek     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
410*55131Storek     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
411*55131Storek     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
412*55131Storek     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
413*55131Storek     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
414*55131Storek static u_long rightmask[32] = {
415*55131Storek     0x00000000, 0x00000001, 0x00000003, 0x00000007,
416*55131Storek     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
417*55131Storek     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
418*55131Storek     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
419*55131Storek     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
420*55131Storek     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
421*55131Storek     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
422*55131Storek     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
423*55131Storek #endif /*MSBYTE_FIRST*/
424*55131Storek 
425*55131Storek #else /*MSBIT_FIRST*/
426*55131Storek 
427*55131Storek u_long raster_bitmask[32] = {
428*55131Storek     0x00000001, 0x00000002, 0x00000004, 0x00000008,
429*55131Storek     0x00000010, 0x00000020, 0x00000040, 0x00000080,
430*55131Storek     0x00000100, 0x00000200, 0x00000400, 0x00000800,
431*55131Storek     0x00001000, 0x00002000, 0x00004000, 0x00008000,
432*55131Storek     0x00010000, 0x00020000, 0x00040000, 0x00080000,
433*55131Storek     0x00100000, 0x00200000, 0x00400000, 0x00800000,
434*55131Storek     0x01000000, 0x02000000, 0x04000000, 0x08000000,
435*55131Storek     0x10000000, 0x20000000, 0x40000000, 0x80000000 };
436*55131Storek 
437*55131Storek #ifndef MSBYTE_FIRST
438*55131Storek static u_long leftmask[32] = {
439*55131Storek     0x00000000, 0x00000001, 0x00000003, 0x00000007,
440*55131Storek     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
441*55131Storek     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
442*55131Storek     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
443*55131Storek     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
444*55131Storek     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
445*55131Storek     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
446*55131Storek     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
447*55131Storek static u_long rightmask[32] = {
448*55131Storek     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
449*55131Storek     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
450*55131Storek     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
451*55131Storek     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
452*55131Storek     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
453*55131Storek     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
454*55131Storek     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
455*55131Storek     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
456*55131Storek #endif /*not MSBYTE_FIRST*/
457*55131Storek 
458*55131Storek #endif /*MSBIT_FIRST*/
459*55131Storek 
460*55131Storek /* (The odd combinations MSBIT+~MSBYTE and ~MSBIT+MSBYTE could be added.) */
461*55131Storek 
462*55131Storek #ifdef MSBYTE_FIRST
463*55131Storek static u_long bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
464*55131Storek #else /*MSBYTE_FIRST*/
465*55131Storek static u_long bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
466*55131Storek #endif /*MSBYTE_FIRST*/
467*55131Storek 
468*55131Storek 
469*55131Storek /* Forward routines. */
470*55131Storek 
471*55131Storek static int raster_blit();
472*55131Storek 
473*55131Storek 
474*55131Storek /* Raster operations.  */
475*55131Storek 
476*55131Storek /* Performs a bitblit.  Returns 0 on success, -1 on failure. */
477*55131Storek int
478*55131Storek raster_op( dst, dx, dy, w, h, rop, src, sx, sy )
479*55131Storek     struct raster* dst;
480*55131Storek     int dx, dy, w, h, rop;
481*55131Storek     struct raster* src;
482*55131Storek     int sx, sy;
483*55131Storek     {
484*55131Storek     if ( dst == (struct raster*) 0 )
485*55131Storek 	return -1;			/* no destination */
486*55131Storek 
487*55131Storek     if ( needsrc[RAS_GETOP( rop )] )
488*55131Storek 	{
489*55131Storek 	/* Two-operand blit. */
490*55131Storek 	if ( src == (struct raster*) 0 )
491*55131Storek 	    return -1;			/* no source */
492*55131Storek 
493*55131Storek 	/* Clip against source. */
494*55131Storek 	if ( sx < 0 )
495*55131Storek 	    {
496*55131Storek 	    w += sx;
497*55131Storek 	    sx = 0;
498*55131Storek 	    }
499*55131Storek 	if ( sy < 0 )
500*55131Storek 	    {
501*55131Storek 	    h += sy;
502*55131Storek 	    sy = 0;
503*55131Storek 	    }
504*55131Storek 	if ( sx + w > src->width )
505*55131Storek 	    w = src->width - sx;
506*55131Storek 	if ( sy + h > src->height )
507*55131Storek 	    h = src->height - sy;
508*55131Storek 
509*55131Storek 	/* Clip against dest. */
510*55131Storek 	if ( dx < 0 )
511*55131Storek 	    {
512*55131Storek 	    w += dx;
513*55131Storek 	    sx -= dx;
514*55131Storek 	    dx = 0;
515*55131Storek 	    }
516*55131Storek 	if ( dy < 0 )
517*55131Storek 	    {
518*55131Storek 	    h += dy;
519*55131Storek 	    sy -= dy;
520*55131Storek 	    dy = 0;
521*55131Storek 	    }
522*55131Storek 	if ( dx + w > dst->width )
523*55131Storek 	    w = dst->width - dx;
524*55131Storek 	if ( dy + h > dst->height )
525*55131Storek 	    h = dst->height - dy;
526*55131Storek 
527*55131Storek 	if ( w <= 0 || h <= 0 )
528*55131Storek 	    return 0;			/* nothing to do */
529*55131Storek 
530*55131Storek 	return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy );
531*55131Storek 	}
532*55131Storek 
533*55131Storek     /* No source necessary - one-operand blit. */
534*55131Storek     if ( src != (struct raster*) 0 )
535*55131Storek 	return -1;			/* unwanted source */
536*55131Storek 
537*55131Storek     /* Clip against dest. */
538*55131Storek     if ( dx < 0 )
539*55131Storek 	{
540*55131Storek 	w += dx;
541*55131Storek 	dx = 0;
542*55131Storek 	}
543*55131Storek     if ( dy < 0 )
544*55131Storek 	{
545*55131Storek 	h += dy;
546*55131Storek 	dy = 0;
547*55131Storek 	}
548*55131Storek     if ( dx + w > dst->width )
549*55131Storek 	w = dst->width - dx;
550*55131Storek     if ( dy + h > dst->height )
551*55131Storek 	h = dst->height - dy;
552*55131Storek 
553*55131Storek     if ( w <= 0 || h <= 0 )
554*55131Storek 	return 0;			/* nothing to do */
555*55131Storek 
556*55131Storek     return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop );
557*55131Storek     }
558*55131Storek 
559*55131Storek /* Semi-public routine to do a bitblit without clipping.  Returns 0 on
560*55131Storek ** success, -1 on failure.
561*55131Storek */
562*55131Storek int
563*55131Storek raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy )
564*55131Storek     struct raster* dst;
565*55131Storek     int dx, dy, w, h, rop;
566*55131Storek     struct raster* src;
567*55131Storek     int sx, sy;
568*55131Storek     {
569*55131Storek     int op;
570*55131Storek 
571*55131Storek     op = RAS_GETOP( rop );
572*55131Storek 
573*55131Storek     if ( src->depth == 1 )
574*55131Storek 	{
575*55131Storek 	/* One-bit to ? blit. */
576*55131Storek 	if ( dst->depth == 1 )
577*55131Storek 	    {
578*55131Storek 	    /* One to one blit. */
579*55131Storek 	    u_long* srclin1;
580*55131Storek 	    u_long* dstlin1;
581*55131Storek 	    int srcleftignore, srcrightignore, srclongs;
582*55131Storek 	    int dstleftignore, dstrightignore, dstlongs;
583*55131Storek 
584*55131Storek 	    srclin1 = RAS_ADDR( src, sx, sy );
585*55131Storek 	    dstlin1 = RAS_ADDR( dst, dx, dy );
586*55131Storek 
587*55131Storek #ifdef BCOPY_FASTER
588*55131Storek 	    /* Special-case full-width to full-width copies. */
589*55131Storek 	    if ( op == RAS_SRC && src->width == w && dst->width == w &&
590*55131Storek 		 src->linelongs == dst->linelongs && src->linelongs == w >> 5 )
591*55131Storek 		{
592*55131Storek 		bcopy(
593*55131Storek 		    (char*) srclin1, (char*) dstlin1,
594*55131Storek 		    h * src->linelongs * sizeof(u_long) );
595*55131Storek 		return 0;
596*55131Storek 		}
597*55131Storek #endif /*BCOPY_FASTER*/
598*55131Storek 
599*55131Storek 	    srcleftignore = ( sx & 31 );
600*55131Storek 	    srclongs = ( srcleftignore + w + 31 ) >> 5;
601*55131Storek 	    srcrightignore = ( srclongs * 32 - w - srcleftignore ) & 31;
602*55131Storek 	    dstleftignore = ( dx & 31 );
603*55131Storek 	    dstlongs = ( dstleftignore + w + 31 ) >> 5;
604*55131Storek 	    dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
605*55131Storek 
606*55131Storek 	    return raster_blit(
607*55131Storek 		src, srclin1, srcleftignore, srcrightignore, srclongs,
608*55131Storek 		dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
609*55131Storek 	    }
610*55131Storek 
611*55131Storek 	else
612*55131Storek 	    {
613*55131Storek 	    /* One to eight, using the color in the rop.  This could
614*55131Storek 	    ** probably be sped up by handling each four-bit source nybble
615*55131Storek 	    ** as a group, indexing into a 16-element runtime-constructed
616*55131Storek 	    ** table of longwords.
617*55131Storek 	    */
618*55131Storek 	    u_long* srclin1;
619*55131Storek 	    u_long* dstlin1;
620*55131Storek 	    u_long* srclin2;
621*55131Storek 	    u_long* srclin;
622*55131Storek 	    u_long* dstlin;
623*55131Storek 	    register u_long* srclong;
624*55131Storek 	    register u_long* dstlong;
625*55131Storek 	    register u_long color, dl;
626*55131Storek 	    register int srcbit, dstbyte, i;
627*55131Storek 
628*55131Storek 	    color = RAS_GETCOLOR( rop );
629*55131Storek 	    if ( color == 0 )
630*55131Storek 		color = 255;
631*55131Storek 
632*55131Storek 	    /* Make 32 bits of color so we can do the ROP without shifting. */
633*55131Storek 	    color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
634*55131Storek 
635*55131Storek 	    /* Don't have to worry about overlapping blits here. */
636*55131Storek 	    srclin1 = RAS_ADDR( src, sx, sy );
637*55131Storek 	    srclin2 = srclin1 + h * src->linelongs;
638*55131Storek 	    dstlin1 = RAS_ADDR( dst, dx, dy );
639*55131Storek 	    srclin = srclin1;
640*55131Storek 	    dstlin = dstlin1;
641*55131Storek 	    while ( srclin != srclin2 )
642*55131Storek 		{
643*55131Storek 		srclong = srclin;
644*55131Storek 		srcbit = sx & 31;
645*55131Storek 		dstlong = dstlin;
646*55131Storek 		dstbyte = dx & 3;
647*55131Storek 		i = w;
648*55131Storek 
649*55131Storek 		/* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
650*55131Storek 		ROP_SRCDSTCOLOR(
651*55131Storek 		/*op*/  op,
652*55131Storek 		/*pre*/ while ( i > 0 )
653*55131Storek 			    {
654*55131Storek 			    dl = *dstlong;,
655*55131Storek 		/*s*/       *srclong & raster_bitmask[srcbit],
656*55131Storek 		/*d*/       dl,
657*55131Storek 		/*c*/       color,
658*55131Storek 		/*pst*/     *dstlong = ( *dstlong & ~bytemask[dstbyte] ) |
659*55131Storek 				       ( dl & bytemask[dstbyte] );
660*55131Storek 			    if ( srcbit == 31 )
661*55131Storek 				{
662*55131Storek 				srcbit = 0;
663*55131Storek 				++srclong;
664*55131Storek 				}
665*55131Storek 			    else
666*55131Storek 				++srcbit;
667*55131Storek 			    if ( dstbyte == 3 )
668*55131Storek 				{
669*55131Storek 				dstbyte = 0;
670*55131Storek 				++dstlong;
671*55131Storek 				}
672*55131Storek 			    else
673*55131Storek 				++dstbyte;
674*55131Storek 			    --i;
675*55131Storek 			    } )
676*55131Storek 
677*55131Storek 		srclin += src->linelongs;
678*55131Storek 		dstlin += dst->linelongs;
679*55131Storek 		}
680*55131Storek 	    }
681*55131Storek 	}
682*55131Storek 
683*55131Storek     else
684*55131Storek 	{
685*55131Storek 	/* Eight to eight blit. */
686*55131Storek 	u_long* srclin1;
687*55131Storek 	u_long* dstlin1;
688*55131Storek 	int srcleftignore, srcrightignore, srclongs;
689*55131Storek 	int dstleftignore, dstrightignore, dstlongs;
690*55131Storek 
691*55131Storek 	if ( dst->depth != 8 )
692*55131Storek 	    return -1;		/* depth mismatch */
693*55131Storek 
694*55131Storek 	srclin1 = RAS_ADDR( src, sx, sy );
695*55131Storek 	dstlin1 = RAS_ADDR( dst, dx, dy );
696*55131Storek 
697*55131Storek #ifdef BCOPY_FASTER
698*55131Storek 	/* Special-case full-width to full-width copies. */
699*55131Storek 	if ( op == RAS_SRC && src->width == w && dst->width == w &&
700*55131Storek 	     src->linelongs == dst->linelongs && src->linelongs == w >> 2 )
701*55131Storek 	    {
702*55131Storek 	    bcopy( (char*) srclin1, (char*) dstlin1,
703*55131Storek 		   h * src->linelongs * sizeof(u_long) );
704*55131Storek 	    return 0;
705*55131Storek 	    }
706*55131Storek #endif /*BCOPY_FASTER*/
707*55131Storek 
708*55131Storek 	srcleftignore = ( sx & 3 ) * 8;
709*55131Storek 	srclongs = ( srcleftignore + w * 8 + 31 ) >> 5;
710*55131Storek 	srcrightignore = ( srclongs * 32 - w * 8 - srcleftignore ) & 31;
711*55131Storek 	dstleftignore = ( dx & 3 ) * 8;
712*55131Storek 	dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
713*55131Storek 	dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
714*55131Storek 
715*55131Storek 	return raster_blit(
716*55131Storek 	    src, srclin1, srcleftignore, srcrightignore, srclongs,
717*55131Storek 	    dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
718*55131Storek 	}
719*55131Storek 
720*55131Storek     return 0;
721*55131Storek     }
722*55131Storek 
723*55131Storek /* Semi-public routine to do a no-src bitblit without clipping.  Returns 0
724*55131Storek ** on success, -1 on failure.
725*55131Storek */
726*55131Storek int
727*55131Storek raster_op_nosrc_noclip( dst, dx, dy, w, h, rop )
728*55131Storek     struct raster* dst;
729*55131Storek     int dx, dy, w, h, rop;
730*55131Storek     {
731*55131Storek     int op;
732*55131Storek 
733*55131Storek     op = RAS_GETOP( rop );
734*55131Storek 
735*55131Storek     if ( dst->depth == 1 )
736*55131Storek 	{
737*55131Storek 	/* One-bit no-src blit. */
738*55131Storek 	u_long* dstlin1;
739*55131Storek 	u_long* dstlin2;
740*55131Storek 	u_long* dstlin;
741*55131Storek 	int dstleftignore, dstrightignore, dstlongs;
742*55131Storek 	u_long dl, lm, nlm, rm, nrm;
743*55131Storek 	register u_long* dstlong2;
744*55131Storek 	register u_long* dstlong;
745*55131Storek 
746*55131Storek 	dstlin1 = RAS_ADDR( dst, dx, dy );
747*55131Storek 
748*55131Storek #ifdef BCOPY_FASTER
749*55131Storek 	/* Special-case full-width clears. */
750*55131Storek 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 )
751*55131Storek 	    {
752*55131Storek 	    bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) );
753*55131Storek 	    return 0;
754*55131Storek 	    }
755*55131Storek #endif /*BCOPY_FASTER*/
756*55131Storek 
757*55131Storek 	dstleftignore = ( dx & 31 );
758*55131Storek 	dstlongs = ( dstleftignore + w + 31 ) >> 5;
759*55131Storek 	dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
760*55131Storek 
761*55131Storek 	dstlin2 = dstlin1 + h * dst->linelongs;
762*55131Storek 	dstlin = dstlin1;
763*55131Storek 
764*55131Storek 	if ( dstlongs == 1 )
765*55131Storek 	    {
766*55131Storek 	    /* It fits into a single longword. */
767*55131Storek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
768*55131Storek 	    nlm = ~lm;
769*55131Storek 	    while ( dstlin != dstlin2 )
770*55131Storek 		{
771*55131Storek 		ROP_DST(
772*55131Storek 		/*op*/  op,
773*55131Storek 		/*pre*/ dl = *dstlin;,
774*55131Storek 		/*d*/   dl,
775*55131Storek 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
776*55131Storek 
777*55131Storek 		dstlin += dst->linelongs;
778*55131Storek 		}
779*55131Storek 	    }
780*55131Storek 	else
781*55131Storek 	    {
782*55131Storek 	    lm = leftmask[dstleftignore];
783*55131Storek 	    rm = rightmask[dstrightignore];
784*55131Storek 	    nrm = ~rm;
785*55131Storek 	    nlm = ~lm;
786*55131Storek 
787*55131Storek 	    while ( dstlin != dstlin2 )
788*55131Storek 		{
789*55131Storek 		dstlong = dstlin;
790*55131Storek 		dstlong2 = dstlong + dstlongs;
791*55131Storek 		if ( dstrightignore != 0 )
792*55131Storek 		    --dstlong2;
793*55131Storek 
794*55131Storek 		/* Leading edge. */
795*55131Storek 		if ( dstleftignore != 0 )
796*55131Storek 		    {
797*55131Storek 		    ROP_DST(
798*55131Storek 		    /*op*/  op,
799*55131Storek 		    /*pre*/ dl = *dstlong;,
800*55131Storek 		    /*d*/   dl,
801*55131Storek 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
802*55131Storek 		    ++dstlong;
803*55131Storek 		    }
804*55131Storek 
805*55131Storek 		/* Main rop. */
806*55131Storek 		ROP_DST(
807*55131Storek 		/*op*/  op,
808*55131Storek 		/*pre*/ while ( dstlong != dstlong2 )
809*55131Storek 			    {,
810*55131Storek 		/*d*/       *dstlong,
811*55131Storek 		/*pst*/     ++dstlong;
812*55131Storek 			    } )
813*55131Storek 
814*55131Storek 		/* Trailing edge. */
815*55131Storek 		if ( dstrightignore != 0 )
816*55131Storek 		    {
817*55131Storek 		    ROP_DST(
818*55131Storek 		    /*op*/  op,
819*55131Storek 		    /*pre*/ dl = *dstlong;,
820*55131Storek 		    /*d*/   dl,
821*55131Storek 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
822*55131Storek 		    }
823*55131Storek 
824*55131Storek 		dstlin += dst->linelongs;
825*55131Storek 		}
826*55131Storek 	    }
827*55131Storek 	}
828*55131Storek 
829*55131Storek     else
830*55131Storek 	{
831*55131Storek 	/* Eight-bit no-src blit. */
832*55131Storek 	register u_long color;
833*55131Storek 	u_long* dstlin1;
834*55131Storek 	u_long* dstlin2;
835*55131Storek 	u_long* dstlin;
836*55131Storek 	int dstleftignore, dstrightignore, dstlongs;
837*55131Storek 	u_long dl, lm, nlm, rm, nrm;
838*55131Storek 	register u_long* dstlong2;
839*55131Storek 	register u_long* dstlong;
840*55131Storek 
841*55131Storek 	dstlin1 = RAS_ADDR( dst, dx, dy );
842*55131Storek 
843*55131Storek #ifdef BCOPY_FASTER
844*55131Storek 	/* Special-case full-width clears. */
845*55131Storek 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 2 )
846*55131Storek 	    {
847*55131Storek 	    bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) );
848*55131Storek 	    return 0;
849*55131Storek 	    }
850*55131Storek #endif /*BCOPY_FASTER*/
851*55131Storek 
852*55131Storek 	color = RAS_GETCOLOR( rop );
853*55131Storek 	if ( color == 0 )
854*55131Storek 	    color = 255;
855*55131Storek 
856*55131Storek 	/* Make 32 bits of color so we can do the ROP without shifting. */
857*55131Storek 	color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
858*55131Storek 
859*55131Storek 	dstleftignore = ( dx & 3 ) * 8;
860*55131Storek 	dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
861*55131Storek 	dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
862*55131Storek 
863*55131Storek 	dstlin2 = dstlin1 + h * dst->linelongs;
864*55131Storek 	dstlin = dstlin1;
865*55131Storek 
866*55131Storek 	if ( dstlongs == 1 )
867*55131Storek 	    {
868*55131Storek 	    /* It fits into a single longword. */
869*55131Storek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
870*55131Storek 	    nlm = ~lm;
871*55131Storek 	    while ( dstlin != dstlin2 )
872*55131Storek 		{
873*55131Storek 		ROP_DSTCOLOR(
874*55131Storek 		/*op*/  op,
875*55131Storek 		/*pre*/ dl = *dstlin;,
876*55131Storek 		/*d*/   dl,
877*55131Storek 		/*c*/	color,
878*55131Storek 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
879*55131Storek 
880*55131Storek 		dstlin += dst->linelongs;
881*55131Storek 		}
882*55131Storek 	    }
883*55131Storek 	else
884*55131Storek 	    {
885*55131Storek 	    lm = leftmask[dstleftignore];
886*55131Storek 	    rm = rightmask[dstrightignore];
887*55131Storek 	    nrm = ~rm;
888*55131Storek 	    nlm = ~lm;
889*55131Storek 	    while ( dstlin != dstlin2 )
890*55131Storek 		{
891*55131Storek 		dstlong = dstlin;
892*55131Storek 		dstlong2 = dstlong + dstlongs;
893*55131Storek 		if ( dstrightignore != 0 )
894*55131Storek 		    --dstlong2;
895*55131Storek 
896*55131Storek 		/* Leading edge. */
897*55131Storek 		if ( dstleftignore != 0 )
898*55131Storek 		    {
899*55131Storek 		    ROP_DSTCOLOR(
900*55131Storek 		    /*op*/  op,
901*55131Storek 		    /*pre*/ dl = *dstlong;,
902*55131Storek 		    /*d*/   dl,
903*55131Storek 		    /*c*/   color,
904*55131Storek 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
905*55131Storek 		    ++dstlong;
906*55131Storek 		    }
907*55131Storek 
908*55131Storek 		/* Main rop. */
909*55131Storek 		ROP_DSTCOLOR(
910*55131Storek 		/*op*/  op,
911*55131Storek 		/*pre*/ while ( dstlong != dstlong2 )
912*55131Storek 			    {,
913*55131Storek 		/*d*/       *dstlong,
914*55131Storek 		/*c*/       color,
915*55131Storek 		/*pst*/     ++dstlong;
916*55131Storek 			    } )
917*55131Storek 
918*55131Storek 		/* Trailing edge. */
919*55131Storek 		if ( dstrightignore != 0 )
920*55131Storek 		    {
921*55131Storek 		    ROP_DSTCOLOR(
922*55131Storek 		    /*op*/  op,
923*55131Storek 		    /*pre*/ dl = *dstlong;,
924*55131Storek 		    /*d*/   dl,
925*55131Storek 		    /*c*/   color,
926*55131Storek 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
927*55131Storek 		    }
928*55131Storek 
929*55131Storek 		dstlin += dst->linelongs;
930*55131Storek 		}
931*55131Storek 	    }
932*55131Storek 	}
933*55131Storek 
934*55131Storek     return 0;
935*55131Storek     }
936*55131Storek 
937*55131Storek /* This is a general bitblit routine, handling overlapping source and
938*55131Storek ** destination.  It's used for both the 1-to-1 and 8-to-8 cases.
939*55131Storek */
940*55131Storek static int
941*55131Storek raster_blit( src, srclin1, srcleftignore, srcrightignore, srclongs, dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op )
942*55131Storek     struct raster* src;
943*55131Storek     u_long* srclin1;
944*55131Storek     int srcleftignore, srcrightignore, srclongs;
945*55131Storek     struct raster* dst;
946*55131Storek     u_long* dstlin1;
947*55131Storek     int dstleftignore, dstrightignore, dstlongs;
948*55131Storek     int h, op;
949*55131Storek     {
950*55131Storek     u_long* srclin2;
951*55131Storek     u_long* dstlin2;
952*55131Storek     int srclininc, dstlininc;
953*55131Storek     u_long* srclin;
954*55131Storek     u_long* dstlin;
955*55131Storek     register int prevleftshift, currrightshift;
956*55131Storek     int longinc;
957*55131Storek     register u_long* srclong;
958*55131Storek     register u_long* dstlong;
959*55131Storek     register u_long* dstlong2;
960*55131Storek     register u_long dl, lm, nlm, rm, nrm;
961*55131Storek 
962*55131Storek     prevleftshift = ( srcleftignore - dstleftignore ) & 31;
963*55131Storek 
964*55131Storek     srclin2 = srclin1 + h * src->linelongs;
965*55131Storek     dstlin2 = dstlin1 + h * dst->linelongs;
966*55131Storek     srclininc = src->linelongs;
967*55131Storek     dstlininc = dst->linelongs;
968*55131Storek     longinc = 1;
969*55131Storek 
970*55131Storek     /* Check for overlaps. */
971*55131Storek     if ( ( dstlin1 >= srclin1 && dstlin1 < srclin1 + srclongs ) ||
972*55131Storek 	 ( srclin1 >= dstlin1 && srclin1 < dstlin1 + dstlongs ) )
973*55131Storek 	{
974*55131Storek 	/* Horizontal overlap.  Should we reverse? */
975*55131Storek 	if ( srclin1 < dstlin1 )
976*55131Storek 	    {
977*55131Storek 	    longinc = -1;
978*55131Storek 	    srclin1 += srclongs - 1;
979*55131Storek 	    srclin2 += srclongs - 1;
980*55131Storek 	    dstlin1 += dstlongs - 1;
981*55131Storek 	    }
982*55131Storek 	}
983*55131Storek     else if ( ( dstlin1 >= srclin1 && dstlin1 < srclin2 ) ||
984*55131Storek 	      ( srclin1 >= dstlin1 && srclin1 < dstlin2 ) )
985*55131Storek 	{
986*55131Storek 	/* Vertical overlap.  Should we reverse? */
987*55131Storek 	if ( srclin1 < dstlin1 )
988*55131Storek 	    {
989*55131Storek 	    srclin2 = srclin1 - srclininc;
990*55131Storek 	    srclin1 += ( h - 1 ) * srclininc;
991*55131Storek 	    dstlin1 += ( h - 1 ) * dstlininc;
992*55131Storek 	    srclininc = -srclininc;
993*55131Storek 	    dstlininc = -dstlininc;
994*55131Storek 	    }
995*55131Storek 	}
996*55131Storek     srclin = srclin1;
997*55131Storek     dstlin = dstlin1;
998*55131Storek 
999*55131Storek     if ( prevleftshift == 0 )
1000*55131Storek 	{
1001*55131Storek 	/* The bits line up, no shifting necessary. */
1002*55131Storek 	if ( dstlongs == 1 )
1003*55131Storek 	    {
1004*55131Storek 	    /* It all fits into a single longword. */
1005*55131Storek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
1006*55131Storek 	    nlm = ~lm;
1007*55131Storek 	    while ( srclin != srclin2 )
1008*55131Storek 		{
1009*55131Storek 		ROP_SRCDST(
1010*55131Storek 		/*op*/  op,
1011*55131Storek 		/*pre*/ dl = *dstlin;,
1012*55131Storek 		/*s*/   *srclin,
1013*55131Storek 		/*d*/   dl,
1014*55131Storek 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1015*55131Storek 
1016*55131Storek 		srclin += srclininc;
1017*55131Storek 		dstlin += dstlininc;
1018*55131Storek 		}
1019*55131Storek 	    }
1020*55131Storek 	else
1021*55131Storek 	    {
1022*55131Storek 	    /* Multiple longwords. */
1023*55131Storek 	    lm = leftmask[dstleftignore];
1024*55131Storek 	    rm = rightmask[dstrightignore];
1025*55131Storek 	    nrm = ~rm;
1026*55131Storek 	    nlm = ~lm;
1027*55131Storek 	    if ( longinc == 1 )
1028*55131Storek 		{
1029*55131Storek 		/* Left to right. */
1030*55131Storek 		while ( srclin != srclin2 )
1031*55131Storek 		    {
1032*55131Storek 		    srclong = srclin;
1033*55131Storek 		    dstlong = dstlin;
1034*55131Storek 		    dstlong2 = dstlong + dstlongs;
1035*55131Storek 		    if ( dstrightignore != 0 )
1036*55131Storek 			--dstlong2;
1037*55131Storek 
1038*55131Storek 		    /* Leading edge. */
1039*55131Storek 		    if ( dstleftignore != 0 )
1040*55131Storek 			{
1041*55131Storek 			ROP_SRCDST(
1042*55131Storek 			/*op*/  op,
1043*55131Storek 			/*pre*/ dl = *dstlong;,
1044*55131Storek 			/*s*/   *srclong,
1045*55131Storek 			/*d*/   dl,
1046*55131Storek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1047*55131Storek 			++srclong;
1048*55131Storek 			++dstlong;
1049*55131Storek 			}
1050*55131Storek 
1051*55131Storek 		    /* Main rop. */
1052*55131Storek 		    ROP_SRCDST(
1053*55131Storek 		    /*op*/  op,
1054*55131Storek 		    /*pre*/ while ( dstlong != dstlong2 )
1055*55131Storek 				{,
1056*55131Storek 		    /*s*/       *srclong,
1057*55131Storek 		    /*d*/       *dstlong,
1058*55131Storek 		    /*pst*/     ++srclong;
1059*55131Storek 				++dstlong;
1060*55131Storek 				} )
1061*55131Storek 
1062*55131Storek 		    /* Trailing edge. */
1063*55131Storek 		    if ( dstrightignore != 0 )
1064*55131Storek 			{
1065*55131Storek 			ROP_SRCDST(
1066*55131Storek 			/*op*/  op,
1067*55131Storek 			/*pre*/ dl = *dstlong;,
1068*55131Storek 			/*s*/   *srclong,
1069*55131Storek 			/*d*/   dl,
1070*55131Storek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1071*55131Storek 			}
1072*55131Storek 
1073*55131Storek 		    srclin += srclininc;
1074*55131Storek 		    dstlin += dstlininc;
1075*55131Storek 		    }
1076*55131Storek 		}
1077*55131Storek 	    else
1078*55131Storek 		{
1079*55131Storek 		/* Right to left. */
1080*55131Storek 		while ( srclin != srclin2 )
1081*55131Storek 		    {
1082*55131Storek 		    srclong = srclin;
1083*55131Storek 		    dstlong = dstlin;
1084*55131Storek 		    dstlong2 = dstlong - dstlongs;
1085*55131Storek 		    if ( dstleftignore != 0 )
1086*55131Storek 			++dstlong2;
1087*55131Storek 
1088*55131Storek 		    /* Leading edge. */
1089*55131Storek 		    if ( dstrightignore != 0 )
1090*55131Storek 			{
1091*55131Storek 			ROP_SRCDST(
1092*55131Storek 			/*op*/  op,
1093*55131Storek 			/*pre*/ dl = *dstlong;,
1094*55131Storek 			/*s*/   *srclong,
1095*55131Storek 			/*d*/   dl,
1096*55131Storek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1097*55131Storek 			--srclong;
1098*55131Storek 			--dstlong;
1099*55131Storek 			}
1100*55131Storek 
1101*55131Storek 		    /* Main rop. */
1102*55131Storek 		    ROP_SRCDST(
1103*55131Storek 		    /*op*/  op,
1104*55131Storek 		    /*pre*/ while ( dstlong != dstlong2 )
1105*55131Storek 				{,
1106*55131Storek 		    /*s*/       *srclong,
1107*55131Storek 		    /*d*/       *dstlong,
1108*55131Storek 		    /*pst*/     --srclong;
1109*55131Storek 				--dstlong;
1110*55131Storek 				} )
1111*55131Storek 
1112*55131Storek 		    /* Trailing edge. */
1113*55131Storek 		    if ( dstleftignore != 0 )
1114*55131Storek 			{
1115*55131Storek 			ROP_SRCDST(
1116*55131Storek 			/*op*/  op,
1117*55131Storek 			/*pre*/ dl = *dstlong;,
1118*55131Storek 			/*s*/   *srclong,
1119*55131Storek 			/*d*/   dl,
1120*55131Storek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1121*55131Storek 			}
1122*55131Storek 
1123*55131Storek 		    srclin += srclininc;
1124*55131Storek 		    dstlin += dstlininc;
1125*55131Storek 		    }
1126*55131Storek 		}
1127*55131Storek 	    }
1128*55131Storek 	}
1129*55131Storek 
1130*55131Storek     else
1131*55131Storek 	{
1132*55131Storek 	/* General case, with shifting and everything. */
1133*55131Storek 	register u_long sl, prevsl;
1134*55131Storek 
1135*55131Storek 	currrightshift = 32 - prevleftshift;
1136*55131Storek 	if ( srclongs == 1 && dstlongs == 1 )
1137*55131Storek 	    {
1138*55131Storek 	    /* It fits into a single longword, with a shift. */
1139*55131Storek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
1140*55131Storek 	    nlm = ~lm;
1141*55131Storek 	    if ( srcleftignore > dstleftignore )
1142*55131Storek 		{
1143*55131Storek 		while ( srclin != srclin2 )
1144*55131Storek 		    {
1145*55131Storek 		    ROP_SRCDST(
1146*55131Storek 		    /*op*/  op,
1147*55131Storek 		    /*pre*/ dl = *dstlin;,
1148*55131Storek 		    /*s*/   *srclin << prevleftshift,
1149*55131Storek 		    /*d*/   dl,
1150*55131Storek 		    /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1151*55131Storek 
1152*55131Storek 		    srclin += srclininc;
1153*55131Storek 		    dstlin += dstlininc;
1154*55131Storek 		    }
1155*55131Storek 		}
1156*55131Storek 	    else
1157*55131Storek 		{
1158*55131Storek 		while ( srclin != srclin2 )
1159*55131Storek 		    {
1160*55131Storek 		    ROP_SRCDST(
1161*55131Storek 		    /*op*/  op,
1162*55131Storek 		    /*pre*/ dl = *dstlin;,
1163*55131Storek 		    /*s*/   *srclin >> currrightshift,
1164*55131Storek 		    /*d*/   dl,
1165*55131Storek 		    /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1166*55131Storek 
1167*55131Storek 		    srclin += srclininc;
1168*55131Storek 		    dstlin += dstlininc;
1169*55131Storek 		    }
1170*55131Storek 		}
1171*55131Storek 	    }
1172*55131Storek 	else
1173*55131Storek 	    {
1174*55131Storek 	    /* Multiple longwords. */
1175*55131Storek 	    lm = leftmask[dstleftignore];
1176*55131Storek 	    rm = rightmask[dstrightignore];
1177*55131Storek 	    nrm = ~rm;
1178*55131Storek 	    nlm = ~lm;
1179*55131Storek 	    if ( longinc == 1 )
1180*55131Storek 		{
1181*55131Storek 		/* Left to right. */
1182*55131Storek 		while ( srclin != srclin2 )
1183*55131Storek 		    {
1184*55131Storek 		    srclong = srclin;
1185*55131Storek 		    dstlong = dstlin;
1186*55131Storek 		    dstlong2 = dstlong + dstlongs;
1187*55131Storek 		    if ( srcleftignore > dstleftignore )
1188*55131Storek 			prevsl = *srclong++ << prevleftshift;
1189*55131Storek 		    else
1190*55131Storek 			prevsl = 0;
1191*55131Storek 		    if ( dstrightignore != 0 )
1192*55131Storek 			--dstlong2;
1193*55131Storek 
1194*55131Storek 		    /* Leading edge. */
1195*55131Storek 		    if ( dstleftignore != 0 )
1196*55131Storek 			{
1197*55131Storek 			ROP_SRCDST(
1198*55131Storek 			/*op*/  op,
1199*55131Storek 			/*pre*/ sl = *srclong;
1200*55131Storek 				dl = *dstlong;,
1201*55131Storek 			/*s*/   prevsl | ( sl >> currrightshift ),
1202*55131Storek 			/*d*/   dl,
1203*55131Storek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1204*55131Storek 			prevsl = sl << prevleftshift;
1205*55131Storek 			++srclong;
1206*55131Storek 			++dstlong;
1207*55131Storek 			}
1208*55131Storek 
1209*55131Storek 		    /* Main rop. */
1210*55131Storek 		    ROP_SRCDST(
1211*55131Storek 		    /*op*/  op,
1212*55131Storek 		    /*pre*/ while ( dstlong != dstlong2 )
1213*55131Storek 				{
1214*55131Storek 				sl = *srclong;,
1215*55131Storek 		    /*s*/       prevsl | ( sl >> currrightshift ),
1216*55131Storek 		    /*d*/       *dstlong,
1217*55131Storek 		    /*pst*/     prevsl = sl << prevleftshift;
1218*55131Storek 				++srclong;
1219*55131Storek 				++dstlong;
1220*55131Storek 				} )
1221*55131Storek 
1222*55131Storek 		    /* Trailing edge. */
1223*55131Storek 		    if ( dstrightignore != 0 )
1224*55131Storek 			{
1225*55131Storek 			ROP_SRCDST(
1226*55131Storek 			/*op*/  op,
1227*55131Storek 			/*pre*/ dl = *dstlong;,
1228*55131Storek 			/*s*/   prevsl | ( *srclong >> currrightshift ),
1229*55131Storek 			/*d*/   dl,
1230*55131Storek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1231*55131Storek 			}
1232*55131Storek 
1233*55131Storek 		    srclin += srclininc;
1234*55131Storek 		    dstlin += dstlininc;
1235*55131Storek 		    }
1236*55131Storek 		}
1237*55131Storek 	    else
1238*55131Storek 		{
1239*55131Storek 		/* Right to left. */
1240*55131Storek 		while ( srclin != srclin2 )
1241*55131Storek 		    {
1242*55131Storek 		    srclong = srclin;
1243*55131Storek 		    dstlong = dstlin;
1244*55131Storek 		    dstlong2 = dstlong - dstlongs;
1245*55131Storek 		    if ( srcrightignore > dstrightignore )
1246*55131Storek 			prevsl = *srclong-- >> currrightshift;
1247*55131Storek 		    else
1248*55131Storek 			prevsl = 0;
1249*55131Storek 		    if ( dstleftignore != 0 )
1250*55131Storek 			++dstlong2;
1251*55131Storek 
1252*55131Storek 		    /* Leading edge. */
1253*55131Storek 		    if ( dstrightignore != 0 )
1254*55131Storek 			{
1255*55131Storek 			ROP_SRCDST(
1256*55131Storek 			/*op*/  op,
1257*55131Storek 			/*pre*/ sl = *srclong;
1258*55131Storek 				dl = *dstlong;,
1259*55131Storek 			/*s*/   prevsl | ( sl << prevleftshift ),
1260*55131Storek 			/*d*/   dl,
1261*55131Storek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1262*55131Storek 			prevsl = sl >> currrightshift;
1263*55131Storek 			--srclong;
1264*55131Storek 			--dstlong;
1265*55131Storek 			}
1266*55131Storek 
1267*55131Storek 		    /* Main rop. */
1268*55131Storek 		    ROP_SRCDST(
1269*55131Storek 		    /*op*/  op,
1270*55131Storek 		    /*pre*/ while ( dstlong != dstlong2 )
1271*55131Storek 				{
1272*55131Storek 				sl = *srclong;,
1273*55131Storek 		    /*s*/       prevsl | ( sl << prevleftshift ),
1274*55131Storek 		    /*d*/       *dstlong,
1275*55131Storek 		    /*pst*/     prevsl = sl >> currrightshift;
1276*55131Storek 				--srclong;
1277*55131Storek 				--dstlong;
1278*55131Storek 				} )
1279*55131Storek 
1280*55131Storek 		    /* Trailing edge. */
1281*55131Storek 		    if ( dstleftignore != 0 )
1282*55131Storek 			{
1283*55131Storek 			ROP_SRCDST(
1284*55131Storek 			/*op*/  op,
1285*55131Storek 			/*pre*/ dl = *dstlong;,
1286*55131Storek 			/*s*/   prevsl | ( *srclong << prevleftshift ),
1287*55131Storek 			/*d*/   dl,
1288*55131Storek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1289*55131Storek 			}
1290*55131Storek 
1291*55131Storek 		    srclin += srclininc;
1292*55131Storek 		    dstlin += dstlininc;
1293*55131Storek 		    }
1294*55131Storek 		}
1295*55131Storek 	    }
1296*55131Storek 	}
1297*55131Storek 
1298*55131Storek     return 0;
1299*55131Storek     }
1300