xref: /original-bsd/sys/sparc/rcons/raster_op.c (revision c32d685f)
19aa5da4cStorek /*-
2*c32d685fSbostic  * Copyright (c) 1991, 1993
3*c32d685fSbostic  *	The Regents of the University of California.  All rights reserved.
49aa5da4cStorek  *
59aa5da4cStorek  * This code is derived from software contributed to the Computer Systems
69aa5da4cStorek  * Engineering Group at Lawrence Berkeley Laboratory and to the University
79aa5da4cStorek  * of California at Berkeley by Jef Poskanzer.
89aa5da4cStorek  *
99aa5da4cStorek  * %sccs.include.redist.c%
109aa5da4cStorek  *
11*c32d685fSbostic  *	@(#)raster_op.c	8.1 (Berkeley) 06/11/93
129aa5da4cStorek  *
139aa5da4cStorek  * from: $Header: raster_op.c,v 1.22 92/06/17 08:14:44 torek Exp $
149aa5da4cStorek  */
159aa5da4cStorek 
169aa5da4cStorek /*
179aa5da4cStorek  * Bitblit routine for raster library.
189aa5da4cStorek  *
199aa5da4cStorek  * This raster-op is machined to exacting tolerances by skilled native
209aa5da4cStorek  * craftsmen with pride in their work.
219aa5da4cStorek  *
229aa5da4cStorek  * The various cases are broken down like this:
239aa5da4cStorek  *
249aa5da4cStorek  *   src required
259aa5da4cStorek  *       1-bit to 1-bit
269aa5da4cStorek  *       1-bit to 8-bits
279aa5da4cStorek  *       8-bits to 8-bits
289aa5da4cStorek  *   no src required
299aa5da4cStorek  *       1-bit no-src
309aa5da4cStorek  *       8-bits no-src
319aa5da4cStorek  */
329aa5da4cStorek 
339aa5da4cStorek #include <sys/types.h>
34ef65d49cSbostic #include <sparc/rcons/raster.h>
359aa5da4cStorek 
369aa5da4cStorek /* CONFIGURE: To save on executable size, you can configure out the seldom-used
379aa5da4cStorek ** logical operations.  With this variable set, the only operations implemented
389aa5da4cStorek ** are: RAS_SRC, RAS_CLEAR, RAS_SET, RAS_INVERT, RAS_XOR, RAS_INVERTSRC.
399aa5da4cStorek */
409aa5da4cStorek #ifdef KERNEL
419aa5da4cStorek #define PARTIAL_LOGICAL_OPS
429aa5da4cStorek #endif
439aa5da4cStorek 
449aa5da4cStorek /* CONFIGURE: bcopy() is supposed to be the ultimately fastest way to move
459aa5da4cStorek ** bytes, overlapping or not, ignoring the startup cost.  Unfortunately
469aa5da4cStorek ** this is not true on some systems.  For example, on a Sun 3 running
479aa5da4cStorek ** SunOS 3.5, bcopy() is about five times slower than a simple for loop
489aa5da4cStorek ** on overlapping copies.  And on a 4.1.1 SPARC, bcopy() is about 2/3rds
499aa5da4cStorek ** as fast on backwards overlaps.  So, only define this if your bcopy is ok.
509aa5da4cStorek */
519aa5da4cStorek #undef BCOPY_FASTER
529aa5da4cStorek 
539aa5da4cStorek /* End of configurable definitions. */
549aa5da4cStorek 
559aa5da4cStorek 
569aa5da4cStorek /* Definitions. */
579aa5da4cStorek 
589aa5da4cStorek /* Raster-op macros.  These encapsulate the switch statements and so make
599aa5da4cStorek ** the source code 16 times smaller.  The pre and pst args are code
609aa5da4cStorek ** fragments to put before and after the assignment in each case.  They
619aa5da4cStorek ** can be the beginning and end of a loop.  If the pst fragment includes a
629aa5da4cStorek ** masked assignment, for example to handle the left or right edge cases,
639aa5da4cStorek ** a good optimizing compiler will simplify the boolean expressions very
649aa5da4cStorek ** nicely - both cc and gcc on the SPARC will do this.
659aa5da4cStorek */
669aa5da4cStorek 
679aa5da4cStorek #ifndef PARTIAL_LOGICAL_OPS
689aa5da4cStorek 
699aa5da4cStorek #define ROP_DST(op,pre,d,pst) \
709aa5da4cStorek     switch ( op ) \
719aa5da4cStorek 	{ \
729aa5da4cStorek 	case RAS_CLEAR: \
739aa5da4cStorek 	pre \
749aa5da4cStorek 	(d) = 0; \
759aa5da4cStorek 	pst \
769aa5da4cStorek 	break; \
779aa5da4cStorek 	case RAS_INVERT: \
789aa5da4cStorek 	pre \
799aa5da4cStorek 	(d) = ~(d); \
809aa5da4cStorek 	pst \
819aa5da4cStorek 	break; \
829aa5da4cStorek 	case RAS_DST: \
839aa5da4cStorek 	/* noop */ \
849aa5da4cStorek 	break; \
859aa5da4cStorek 	case RAS_SET: \
869aa5da4cStorek 	pre \
879aa5da4cStorek 	(d) = ~0; \
889aa5da4cStorek 	pst \
899aa5da4cStorek 	break; \
909aa5da4cStorek 	default: \
919aa5da4cStorek 	return -1; \
929aa5da4cStorek 	}
939aa5da4cStorek 
949aa5da4cStorek #define ROP_DSTCOLOR(op,pre,d,c,pst) \
959aa5da4cStorek     switch ( op ) \
969aa5da4cStorek 	{ \
979aa5da4cStorek 	case RAS_CLEAR: \
989aa5da4cStorek 	pre \
999aa5da4cStorek 	(d) = 0; \
1009aa5da4cStorek 	pst \
1019aa5da4cStorek 	break; \
1029aa5da4cStorek 	case RAS_INVERT: \
1039aa5da4cStorek 	pre \
1049aa5da4cStorek 	(d) = ~(d); \
1059aa5da4cStorek 	pst \
1069aa5da4cStorek 	break; \
1079aa5da4cStorek 	case RAS_DST: \
1089aa5da4cStorek 	/* noop */ \
1099aa5da4cStorek 	break; \
1109aa5da4cStorek 	case RAS_SET: \
1119aa5da4cStorek 	pre \
1129aa5da4cStorek 	(d) = (c); \
1139aa5da4cStorek 	pst \
1149aa5da4cStorek 	break; \
1159aa5da4cStorek 	default: \
1169aa5da4cStorek 	return -1; \
1179aa5da4cStorek 	}
1189aa5da4cStorek 
1199aa5da4cStorek #define ROP_SRCDST(op,pre,s,d,pst) \
1209aa5da4cStorek     switch ( op ) \
1219aa5da4cStorek 	{ \
1229aa5da4cStorek 	case RAS_NOTOR: \
1239aa5da4cStorek 	pre \
1249aa5da4cStorek 	(d) = ~( (s) | (d) ); \
1259aa5da4cStorek 	pst \
1269aa5da4cStorek 	break; \
1279aa5da4cStorek 	case RAS_NOTSRC_AND_DST: \
1289aa5da4cStorek 	pre \
1299aa5da4cStorek 	(d) = ~(s) & (d); \
1309aa5da4cStorek 	pst \
1319aa5da4cStorek 	break; \
1329aa5da4cStorek 	case RAS_INVERTSRC: \
1339aa5da4cStorek 	pre \
1349aa5da4cStorek 	(d) = ~(s); \
1359aa5da4cStorek 	pst \
1369aa5da4cStorek 	break; \
1379aa5da4cStorek 	case RAS_SRC_AND_NOTDST: \
1389aa5da4cStorek 	pre \
1399aa5da4cStorek 	(d) = (s) & ~(d); \
1409aa5da4cStorek 	pst \
1419aa5da4cStorek 	break; \
1429aa5da4cStorek 	case RAS_XOR: \
1439aa5da4cStorek 	pre \
1449aa5da4cStorek 	(d) = (s) ^ (d); \
1459aa5da4cStorek 	pst \
1469aa5da4cStorek 	break; \
1479aa5da4cStorek 	case RAS_NOTAND: \
1489aa5da4cStorek 	pre \
1499aa5da4cStorek 	(d) = ~( (s) & (d) ); \
1509aa5da4cStorek 	pst \
1519aa5da4cStorek 	break; \
1529aa5da4cStorek 	case RAS_AND: \
1539aa5da4cStorek 	pre \
1549aa5da4cStorek 	(d) = (s) & (d); \
1559aa5da4cStorek 	pst \
1569aa5da4cStorek 	break; \
1579aa5da4cStorek 	case RAS_NOTXOR: \
1589aa5da4cStorek 	pre \
1599aa5da4cStorek 	(d) = ~( (s) ^ (d) ); \
1609aa5da4cStorek 	pst \
1619aa5da4cStorek 	break; \
1629aa5da4cStorek 	case RAS_NOTSRC_OR_DST: \
1639aa5da4cStorek 	pre \
1649aa5da4cStorek 	(d) = ~(s) | (d); \
1659aa5da4cStorek 	pst \
1669aa5da4cStorek 	break; \
1679aa5da4cStorek 	case RAS_SRC: \
1689aa5da4cStorek 	pre \
1699aa5da4cStorek 	(d) = (s); \
1709aa5da4cStorek 	pst \
1719aa5da4cStorek 	break; \
1729aa5da4cStorek 	case RAS_SRC_OR_NOTDST: \
1739aa5da4cStorek 	pre \
1749aa5da4cStorek 	(d) = (s) | ~(d); \
1759aa5da4cStorek 	pst \
1769aa5da4cStorek 	break; \
1779aa5da4cStorek 	case RAS_OR: \
1789aa5da4cStorek 	pre \
1799aa5da4cStorek 	(d) = (s) | (d); \
1809aa5da4cStorek 	pst \
1819aa5da4cStorek 	break; \
1829aa5da4cStorek 	default: \
1839aa5da4cStorek 	return -1; \
1849aa5da4cStorek 	}
1859aa5da4cStorek 
1869aa5da4cStorek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
1879aa5da4cStorek     switch ( op ) \
1889aa5da4cStorek 	{ \
1899aa5da4cStorek 	case RAS_NOTOR: \
1909aa5da4cStorek 	pre \
1919aa5da4cStorek 	if ( s ) \
1929aa5da4cStorek 	    (d) = ~( (c) | (d) ); \
1939aa5da4cStorek 	else \
1949aa5da4cStorek 	    (d) = ~(d); \
1959aa5da4cStorek 	pst \
1969aa5da4cStorek 	break; \
1979aa5da4cStorek 	case RAS_NOTSRC_AND_DST: \
1989aa5da4cStorek 	pre \
1999aa5da4cStorek 	if ( s ) \
2009aa5da4cStorek 	    (d) = ~(c) & (d); \
2019aa5da4cStorek 	pst \
2029aa5da4cStorek 	break; \
2039aa5da4cStorek 	case RAS_INVERTSRC: \
2049aa5da4cStorek 	pre \
2059aa5da4cStorek 	if ( s ) \
2069aa5da4cStorek 	    (d) = ~(c); \
2079aa5da4cStorek 	else \
2089aa5da4cStorek 	    (d) = ~0; \
2099aa5da4cStorek 	pst \
2109aa5da4cStorek 	break; \
2119aa5da4cStorek 	case RAS_SRC_AND_NOTDST: \
2129aa5da4cStorek 	pre \
2139aa5da4cStorek 	if ( s ) \
2149aa5da4cStorek 	    (d) = (c) & ~(d); \
2159aa5da4cStorek 	else \
2169aa5da4cStorek 	    (d) = 0; \
2179aa5da4cStorek 	pst \
2189aa5da4cStorek 	break; \
2199aa5da4cStorek 	case RAS_XOR: \
2209aa5da4cStorek 	pre \
2219aa5da4cStorek 	if ( s ) \
2229aa5da4cStorek 	    (d) = (c) ^ (d); \
2239aa5da4cStorek 	pst \
2249aa5da4cStorek 	break; \
2259aa5da4cStorek 	case RAS_NOTAND: \
2269aa5da4cStorek 	pre \
2279aa5da4cStorek 	if ( s ) \
2289aa5da4cStorek 	    (d) = ~( (c) & (d) ); \
2299aa5da4cStorek 	else \
2309aa5da4cStorek 	    (d) = ~0; \
2319aa5da4cStorek 	pst \
2329aa5da4cStorek 	break; \
2339aa5da4cStorek 	case RAS_AND: \
2349aa5da4cStorek 	pre \
2359aa5da4cStorek 	if ( s ) \
2369aa5da4cStorek 	    (d) = (c) & (d); \
2379aa5da4cStorek 	else \
2389aa5da4cStorek 	    (d) = 0; \
2399aa5da4cStorek 	pst \
2409aa5da4cStorek 	break; \
2419aa5da4cStorek 	case RAS_NOTXOR: \
2429aa5da4cStorek 	pre \
2439aa5da4cStorek 	if ( s ) \
2449aa5da4cStorek 	    (d) = ~( (c) ^ (d) ); \
2459aa5da4cStorek 	else \
2469aa5da4cStorek 	    (d) = ~(d); \
2479aa5da4cStorek 	pst \
2489aa5da4cStorek 	break; \
2499aa5da4cStorek 	case RAS_NOTSRC_OR_DST: \
2509aa5da4cStorek 	pre \
2519aa5da4cStorek 	if ( s ) \
2529aa5da4cStorek 	    (d) = ~(c) | (d); \
2539aa5da4cStorek 	else \
2549aa5da4cStorek 	    (d) = ~0; \
2559aa5da4cStorek 	pst \
2569aa5da4cStorek 	break; \
2579aa5da4cStorek 	case RAS_SRC: \
2589aa5da4cStorek 	pre \
2599aa5da4cStorek 	if ( s ) \
2609aa5da4cStorek 	    (d) = (c); \
2619aa5da4cStorek 	else \
2629aa5da4cStorek 	    (d) = 0; \
2639aa5da4cStorek 	pst \
2649aa5da4cStorek 	break; \
2659aa5da4cStorek 	case RAS_SRC_OR_NOTDST: \
2669aa5da4cStorek 	pre \
2679aa5da4cStorek 	if ( s ) \
2689aa5da4cStorek 	    (d) = (c) | ~(d); \
2699aa5da4cStorek 	else \
2709aa5da4cStorek 	    (d) = ~(d); \
2719aa5da4cStorek 	pst \
2729aa5da4cStorek 	break; \
2739aa5da4cStorek 	case RAS_OR: \
2749aa5da4cStorek 	pre \
2759aa5da4cStorek 	if ( s ) \
2769aa5da4cStorek 	    (d) = (c) | (d); \
2779aa5da4cStorek 	pst \
2789aa5da4cStorek 	break; \
2799aa5da4cStorek 	default: \
2809aa5da4cStorek 	return -1; \
2819aa5da4cStorek 	}
2829aa5da4cStorek 
2839aa5da4cStorek #else /*PARTIAL_LOGICAL_OPS*/
2849aa5da4cStorek 
2859aa5da4cStorek #define ROP_DST(op,pre,d,pst) \
2869aa5da4cStorek     switch ( op ) \
2879aa5da4cStorek 	{ \
2889aa5da4cStorek 	case RAS_CLEAR: \
2899aa5da4cStorek 	pre \
2909aa5da4cStorek 	(d) = 0; \
2919aa5da4cStorek 	pst \
2929aa5da4cStorek 	break; \
2939aa5da4cStorek 	case RAS_INVERT: \
2949aa5da4cStorek 	pre \
2959aa5da4cStorek 	(d) = ~(d); \
2969aa5da4cStorek 	pst \
2979aa5da4cStorek 	break; \
2989aa5da4cStorek 	case RAS_SET: \
2999aa5da4cStorek 	pre \
3009aa5da4cStorek 	(d) = ~0; \
3019aa5da4cStorek 	pst \
3029aa5da4cStorek 	break; \
3039aa5da4cStorek 	default: \
3049aa5da4cStorek 	return -1; \
3059aa5da4cStorek 	}
3069aa5da4cStorek 
3079aa5da4cStorek #define ROP_DSTCOLOR(op,pre,d,c,pst) \
3089aa5da4cStorek     switch ( op ) \
3099aa5da4cStorek 	{ \
3109aa5da4cStorek 	case RAS_CLEAR: \
3119aa5da4cStorek 	pre \
3129aa5da4cStorek 	(d) = 0; \
3139aa5da4cStorek 	pst \
3149aa5da4cStorek 	break; \
3159aa5da4cStorek 	case RAS_INVERT: \
3169aa5da4cStorek 	pre \
3179aa5da4cStorek 	(d) = ~(d); \
3189aa5da4cStorek 	pst \
3199aa5da4cStorek 	break; \
3209aa5da4cStorek 	case RAS_SET: \
3219aa5da4cStorek 	pre \
3229aa5da4cStorek 	(d) = (c); \
3239aa5da4cStorek 	pst \
3249aa5da4cStorek 	break; \
3259aa5da4cStorek 	default: \
3269aa5da4cStorek 	return -1; \
3279aa5da4cStorek 	}
3289aa5da4cStorek 
3299aa5da4cStorek #define ROP_SRCDST(op,pre,s,d,pst) \
3309aa5da4cStorek     switch ( op ) \
3319aa5da4cStorek 	{ \
3329aa5da4cStorek 	case RAS_INVERTSRC: \
3339aa5da4cStorek 	pre \
3349aa5da4cStorek 	(d) = ~(s); \
3359aa5da4cStorek 	pst \
3369aa5da4cStorek 	break; \
3379aa5da4cStorek 	case RAS_XOR: \
3389aa5da4cStorek 	pre \
3399aa5da4cStorek 	(d) = (s) ^ (d); \
3409aa5da4cStorek 	pst \
3419aa5da4cStorek 	break; \
3429aa5da4cStorek 	case RAS_SRC: \
3439aa5da4cStorek 	pre \
3449aa5da4cStorek 	(d) = (s); \
3459aa5da4cStorek 	pst \
3469aa5da4cStorek 	break; \
3479aa5da4cStorek 	default: \
3489aa5da4cStorek 	return -1; \
3499aa5da4cStorek 	}
3509aa5da4cStorek 
3519aa5da4cStorek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
3529aa5da4cStorek     switch ( op ) \
3539aa5da4cStorek 	{ \
3549aa5da4cStorek 	case RAS_INVERTSRC: \
3559aa5da4cStorek 	pre \
3569aa5da4cStorek 	if ( s ) \
3579aa5da4cStorek 	    (d) = ~(c); \
3589aa5da4cStorek 	else \
3599aa5da4cStorek 	    (d) = ~0; \
3609aa5da4cStorek 	pst \
3619aa5da4cStorek 	break; \
3629aa5da4cStorek 	case RAS_XOR: \
3639aa5da4cStorek 	pre \
3649aa5da4cStorek 	if ( s ) \
3659aa5da4cStorek 	    (d) = (c) ^ (d); \
3669aa5da4cStorek 	pst \
3679aa5da4cStorek 	break; \
3689aa5da4cStorek 	case RAS_SRC: \
3699aa5da4cStorek 	pre \
3709aa5da4cStorek 	if ( s ) \
3719aa5da4cStorek 	    (d) = (c); \
3729aa5da4cStorek 	else \
3739aa5da4cStorek 	    (d) = 0; \
3749aa5da4cStorek 	pst \
3759aa5da4cStorek 	break; \
3769aa5da4cStorek 	default: \
3779aa5da4cStorek 	return -1; \
3789aa5da4cStorek 	}
3799aa5da4cStorek 
3809aa5da4cStorek #endif /*PARTIAL_LOGICAL_OPS*/
3819aa5da4cStorek 
3829aa5da4cStorek 
3839aa5da4cStorek /* Variables. */
3849aa5da4cStorek 
3859aa5da4cStorek static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 };
3869aa5da4cStorek /*                       CLEAR          INVERT          DST            SET */
3879aa5da4cStorek 
3889aa5da4cStorek #ifdef MSBIT_FIRST
3899aa5da4cStorek 
3909aa5da4cStorek u_long raster_bitmask[32] = {
3919aa5da4cStorek     0x80000000, 0x40000000, 0x20000000, 0x10000000,
3929aa5da4cStorek     0x08000000, 0x04000000, 0x02000000, 0x01000000,
3939aa5da4cStorek     0x00800000, 0x00400000, 0x00200000, 0x00100000,
3949aa5da4cStorek     0x00080000, 0x00040000, 0x00020000, 0x00010000,
3959aa5da4cStorek     0x00008000, 0x00004000, 0x00002000, 0x00001000,
3969aa5da4cStorek     0x00000800, 0x00000400, 0x00000200, 0x00000100,
3979aa5da4cStorek     0x00000080, 0x00000040, 0x00000020, 0x00000010,
3989aa5da4cStorek     0x00000008, 0x00000004, 0x00000002, 0x00000001 };
3999aa5da4cStorek 
4009aa5da4cStorek #ifdef MSBYTE_FIRST
4019aa5da4cStorek static u_long leftmask[32] = {
4029aa5da4cStorek     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
4039aa5da4cStorek     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
4049aa5da4cStorek     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
4059aa5da4cStorek     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
4069aa5da4cStorek     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
4079aa5da4cStorek     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
4089aa5da4cStorek     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
4099aa5da4cStorek     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
4109aa5da4cStorek static u_long rightmask[32] = {
4119aa5da4cStorek     0x00000000, 0x00000001, 0x00000003, 0x00000007,
4129aa5da4cStorek     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
4139aa5da4cStorek     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
4149aa5da4cStorek     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
4159aa5da4cStorek     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
4169aa5da4cStorek     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
4179aa5da4cStorek     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
4189aa5da4cStorek     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
4199aa5da4cStorek #endif /*MSBYTE_FIRST*/
4209aa5da4cStorek 
4219aa5da4cStorek #else /*MSBIT_FIRST*/
4229aa5da4cStorek 
4239aa5da4cStorek u_long raster_bitmask[32] = {
4249aa5da4cStorek     0x00000001, 0x00000002, 0x00000004, 0x00000008,
4259aa5da4cStorek     0x00000010, 0x00000020, 0x00000040, 0x00000080,
4269aa5da4cStorek     0x00000100, 0x00000200, 0x00000400, 0x00000800,
4279aa5da4cStorek     0x00001000, 0x00002000, 0x00004000, 0x00008000,
4289aa5da4cStorek     0x00010000, 0x00020000, 0x00040000, 0x00080000,
4299aa5da4cStorek     0x00100000, 0x00200000, 0x00400000, 0x00800000,
4309aa5da4cStorek     0x01000000, 0x02000000, 0x04000000, 0x08000000,
4319aa5da4cStorek     0x10000000, 0x20000000, 0x40000000, 0x80000000 };
4329aa5da4cStorek 
4339aa5da4cStorek #ifndef MSBYTE_FIRST
4349aa5da4cStorek static u_long leftmask[32] = {
4359aa5da4cStorek     0x00000000, 0x00000001, 0x00000003, 0x00000007,
4369aa5da4cStorek     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
4379aa5da4cStorek     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
4389aa5da4cStorek     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
4399aa5da4cStorek     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
4409aa5da4cStorek     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
4419aa5da4cStorek     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
4429aa5da4cStorek     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
4439aa5da4cStorek static u_long rightmask[32] = {
4449aa5da4cStorek     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
4459aa5da4cStorek     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
4469aa5da4cStorek     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
4479aa5da4cStorek     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
4489aa5da4cStorek     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
4499aa5da4cStorek     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
4509aa5da4cStorek     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
4519aa5da4cStorek     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
4529aa5da4cStorek #endif /*not MSBYTE_FIRST*/
4539aa5da4cStorek 
4549aa5da4cStorek #endif /*MSBIT_FIRST*/
4559aa5da4cStorek 
4569aa5da4cStorek /* (The odd combinations MSBIT+~MSBYTE and ~MSBIT+MSBYTE could be added.) */
4579aa5da4cStorek 
4589aa5da4cStorek #ifdef MSBYTE_FIRST
4599aa5da4cStorek static u_long bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
4609aa5da4cStorek #else /*MSBYTE_FIRST*/
4619aa5da4cStorek static u_long bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
4629aa5da4cStorek #endif /*MSBYTE_FIRST*/
4639aa5da4cStorek 
4649aa5da4cStorek 
4659aa5da4cStorek /* Forward routines. */
4669aa5da4cStorek 
4679aa5da4cStorek static int raster_blit();
4689aa5da4cStorek 
4699aa5da4cStorek 
4709aa5da4cStorek /* Raster operations.  */
4719aa5da4cStorek 
4729aa5da4cStorek /* Performs a bitblit.  Returns 0 on success, -1 on failure. */
4739aa5da4cStorek int
raster_op(dst,dx,dy,w,h,rop,src,sx,sy)4749aa5da4cStorek raster_op( dst, dx, dy, w, h, rop, src, sx, sy )
4759aa5da4cStorek     struct raster* dst;
4769aa5da4cStorek     int dx, dy, w, h, rop;
4779aa5da4cStorek     struct raster* src;
4789aa5da4cStorek     int sx, sy;
4799aa5da4cStorek     {
4809aa5da4cStorek     if ( dst == (struct raster*) 0 )
4819aa5da4cStorek 	return -1;			/* no destination */
4829aa5da4cStorek 
4839aa5da4cStorek     if ( needsrc[RAS_GETOP( rop )] )
4849aa5da4cStorek 	{
4859aa5da4cStorek 	/* Two-operand blit. */
4869aa5da4cStorek 	if ( src == (struct raster*) 0 )
4879aa5da4cStorek 	    return -1;			/* no source */
4889aa5da4cStorek 
4899aa5da4cStorek 	/* Clip against source. */
4909aa5da4cStorek 	if ( sx < 0 )
4919aa5da4cStorek 	    {
4929aa5da4cStorek 	    w += sx;
4939aa5da4cStorek 	    sx = 0;
4949aa5da4cStorek 	    }
4959aa5da4cStorek 	if ( sy < 0 )
4969aa5da4cStorek 	    {
4979aa5da4cStorek 	    h += sy;
4989aa5da4cStorek 	    sy = 0;
4999aa5da4cStorek 	    }
5009aa5da4cStorek 	if ( sx + w > src->width )
5019aa5da4cStorek 	    w = src->width - sx;
5029aa5da4cStorek 	if ( sy + h > src->height )
5039aa5da4cStorek 	    h = src->height - sy;
5049aa5da4cStorek 
5059aa5da4cStorek 	/* Clip against dest. */
5069aa5da4cStorek 	if ( dx < 0 )
5079aa5da4cStorek 	    {
5089aa5da4cStorek 	    w += dx;
5099aa5da4cStorek 	    sx -= dx;
5109aa5da4cStorek 	    dx = 0;
5119aa5da4cStorek 	    }
5129aa5da4cStorek 	if ( dy < 0 )
5139aa5da4cStorek 	    {
5149aa5da4cStorek 	    h += dy;
5159aa5da4cStorek 	    sy -= dy;
5169aa5da4cStorek 	    dy = 0;
5179aa5da4cStorek 	    }
5189aa5da4cStorek 	if ( dx + w > dst->width )
5199aa5da4cStorek 	    w = dst->width - dx;
5209aa5da4cStorek 	if ( dy + h > dst->height )
5219aa5da4cStorek 	    h = dst->height - dy;
5229aa5da4cStorek 
5239aa5da4cStorek 	if ( w <= 0 || h <= 0 )
5249aa5da4cStorek 	    return 0;			/* nothing to do */
5259aa5da4cStorek 
5269aa5da4cStorek 	return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy );
5279aa5da4cStorek 	}
5289aa5da4cStorek 
5299aa5da4cStorek     /* No source necessary - one-operand blit. */
5309aa5da4cStorek     if ( src != (struct raster*) 0 )
5319aa5da4cStorek 	return -1;			/* unwanted source */
5329aa5da4cStorek 
5339aa5da4cStorek     /* Clip against dest. */
5349aa5da4cStorek     if ( dx < 0 )
5359aa5da4cStorek 	{
5369aa5da4cStorek 	w += dx;
5379aa5da4cStorek 	dx = 0;
5389aa5da4cStorek 	}
5399aa5da4cStorek     if ( dy < 0 )
5409aa5da4cStorek 	{
5419aa5da4cStorek 	h += dy;
5429aa5da4cStorek 	dy = 0;
5439aa5da4cStorek 	}
5449aa5da4cStorek     if ( dx + w > dst->width )
5459aa5da4cStorek 	w = dst->width - dx;
5469aa5da4cStorek     if ( dy + h > dst->height )
5479aa5da4cStorek 	h = dst->height - dy;
5489aa5da4cStorek 
5499aa5da4cStorek     if ( w <= 0 || h <= 0 )
5509aa5da4cStorek 	return 0;			/* nothing to do */
5519aa5da4cStorek 
5529aa5da4cStorek     return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop );
5539aa5da4cStorek     }
5549aa5da4cStorek 
5559aa5da4cStorek /* Semi-public routine to do a bitblit without clipping.  Returns 0 on
5569aa5da4cStorek ** success, -1 on failure.
5579aa5da4cStorek */
5589aa5da4cStorek int
raster_op_noclip(dst,dx,dy,w,h,rop,src,sx,sy)5599aa5da4cStorek raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy )
5609aa5da4cStorek     struct raster* dst;
5619aa5da4cStorek     int dx, dy, w, h, rop;
5629aa5da4cStorek     struct raster* src;
5639aa5da4cStorek     int sx, sy;
5649aa5da4cStorek     {
5659aa5da4cStorek     int op;
5669aa5da4cStorek 
5679aa5da4cStorek     op = RAS_GETOP( rop );
5689aa5da4cStorek 
5699aa5da4cStorek     if ( src->depth == 1 )
5709aa5da4cStorek 	{
5719aa5da4cStorek 	/* One-bit to ? blit. */
5729aa5da4cStorek 	if ( dst->depth == 1 )
5739aa5da4cStorek 	    {
5749aa5da4cStorek 	    /* One to one blit. */
5759aa5da4cStorek 	    u_long* srclin1;
5769aa5da4cStorek 	    u_long* dstlin1;
5779aa5da4cStorek 	    int srcleftignore, srcrightignore, srclongs;
5789aa5da4cStorek 	    int dstleftignore, dstrightignore, dstlongs;
5799aa5da4cStorek 
5809aa5da4cStorek 	    srclin1 = RAS_ADDR( src, sx, sy );
5819aa5da4cStorek 	    dstlin1 = RAS_ADDR( dst, dx, dy );
5829aa5da4cStorek 
5839aa5da4cStorek #ifdef BCOPY_FASTER
5849aa5da4cStorek 	    /* Special-case full-width to full-width copies. */
5859aa5da4cStorek 	    if ( op == RAS_SRC && src->width == w && dst->width == w &&
5869aa5da4cStorek 		 src->linelongs == dst->linelongs && src->linelongs == w >> 5 )
5879aa5da4cStorek 		{
5889aa5da4cStorek 		bcopy(
5899aa5da4cStorek 		    (char*) srclin1, (char*) dstlin1,
5909aa5da4cStorek 		    h * src->linelongs * sizeof(u_long) );
5919aa5da4cStorek 		return 0;
5929aa5da4cStorek 		}
5939aa5da4cStorek #endif /*BCOPY_FASTER*/
5949aa5da4cStorek 
5959aa5da4cStorek 	    srcleftignore = ( sx & 31 );
5969aa5da4cStorek 	    srclongs = ( srcleftignore + w + 31 ) >> 5;
5979aa5da4cStorek 	    srcrightignore = ( srclongs * 32 - w - srcleftignore ) & 31;
5989aa5da4cStorek 	    dstleftignore = ( dx & 31 );
5999aa5da4cStorek 	    dstlongs = ( dstleftignore + w + 31 ) >> 5;
6009aa5da4cStorek 	    dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
6019aa5da4cStorek 
6029aa5da4cStorek 	    return raster_blit(
6039aa5da4cStorek 		src, srclin1, srcleftignore, srcrightignore, srclongs,
6049aa5da4cStorek 		dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
6059aa5da4cStorek 	    }
6069aa5da4cStorek 
6079aa5da4cStorek 	else
6089aa5da4cStorek 	    {
6099aa5da4cStorek 	    /* One to eight, using the color in the rop.  This could
6109aa5da4cStorek 	    ** probably be sped up by handling each four-bit source nybble
6119aa5da4cStorek 	    ** as a group, indexing into a 16-element runtime-constructed
6129aa5da4cStorek 	    ** table of longwords.
6139aa5da4cStorek 	    */
6149aa5da4cStorek 	    u_long* srclin1;
6159aa5da4cStorek 	    u_long* dstlin1;
6169aa5da4cStorek 	    u_long* srclin2;
6179aa5da4cStorek 	    u_long* srclin;
6189aa5da4cStorek 	    u_long* dstlin;
6199aa5da4cStorek 	    register u_long* srclong;
6209aa5da4cStorek 	    register u_long* dstlong;
6219aa5da4cStorek 	    register u_long color, dl;
6229aa5da4cStorek 	    register int srcbit, dstbyte, i;
6239aa5da4cStorek 
6249aa5da4cStorek 	    color = RAS_GETCOLOR( rop );
6259aa5da4cStorek 	    if ( color == 0 )
6269aa5da4cStorek 		color = 255;
6279aa5da4cStorek 
6289aa5da4cStorek 	    /* Make 32 bits of color so we can do the ROP without shifting. */
6299aa5da4cStorek 	    color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
6309aa5da4cStorek 
6319aa5da4cStorek 	    /* Don't have to worry about overlapping blits here. */
6329aa5da4cStorek 	    srclin1 = RAS_ADDR( src, sx, sy );
6339aa5da4cStorek 	    srclin2 = srclin1 + h * src->linelongs;
6349aa5da4cStorek 	    dstlin1 = RAS_ADDR( dst, dx, dy );
6359aa5da4cStorek 	    srclin = srclin1;
6369aa5da4cStorek 	    dstlin = dstlin1;
6379aa5da4cStorek 	    while ( srclin != srclin2 )
6389aa5da4cStorek 		{
6399aa5da4cStorek 		srclong = srclin;
6409aa5da4cStorek 		srcbit = sx & 31;
6419aa5da4cStorek 		dstlong = dstlin;
6429aa5da4cStorek 		dstbyte = dx & 3;
6439aa5da4cStorek 		i = w;
6449aa5da4cStorek 
6459aa5da4cStorek 		/* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
6469aa5da4cStorek 		ROP_SRCDSTCOLOR(
6479aa5da4cStorek 		/*op*/  op,
6489aa5da4cStorek 		/*pre*/ while ( i > 0 )
6499aa5da4cStorek 			    {
6509aa5da4cStorek 			    dl = *dstlong;,
6519aa5da4cStorek 		/*s*/       *srclong & raster_bitmask[srcbit],
6529aa5da4cStorek 		/*d*/       dl,
6539aa5da4cStorek 		/*c*/       color,
6549aa5da4cStorek 		/*pst*/     *dstlong = ( *dstlong & ~bytemask[dstbyte] ) |
6559aa5da4cStorek 				       ( dl & bytemask[dstbyte] );
6569aa5da4cStorek 			    if ( srcbit == 31 )
6579aa5da4cStorek 				{
6589aa5da4cStorek 				srcbit = 0;
6599aa5da4cStorek 				++srclong;
6609aa5da4cStorek 				}
6619aa5da4cStorek 			    else
6629aa5da4cStorek 				++srcbit;
6639aa5da4cStorek 			    if ( dstbyte == 3 )
6649aa5da4cStorek 				{
6659aa5da4cStorek 				dstbyte = 0;
6669aa5da4cStorek 				++dstlong;
6679aa5da4cStorek 				}
6689aa5da4cStorek 			    else
6699aa5da4cStorek 				++dstbyte;
6709aa5da4cStorek 			    --i;
6719aa5da4cStorek 			    } )
6729aa5da4cStorek 
6739aa5da4cStorek 		srclin += src->linelongs;
6749aa5da4cStorek 		dstlin += dst->linelongs;
6759aa5da4cStorek 		}
6769aa5da4cStorek 	    }
6779aa5da4cStorek 	}
6789aa5da4cStorek 
6799aa5da4cStorek     else
6809aa5da4cStorek 	{
6819aa5da4cStorek 	/* Eight to eight blit. */
6829aa5da4cStorek 	u_long* srclin1;
6839aa5da4cStorek 	u_long* dstlin1;
6849aa5da4cStorek 	int srcleftignore, srcrightignore, srclongs;
6859aa5da4cStorek 	int dstleftignore, dstrightignore, dstlongs;
6869aa5da4cStorek 
6879aa5da4cStorek 	if ( dst->depth != 8 )
6889aa5da4cStorek 	    return -1;		/* depth mismatch */
6899aa5da4cStorek 
6909aa5da4cStorek 	srclin1 = RAS_ADDR( src, sx, sy );
6919aa5da4cStorek 	dstlin1 = RAS_ADDR( dst, dx, dy );
6929aa5da4cStorek 
6939aa5da4cStorek #ifdef BCOPY_FASTER
6949aa5da4cStorek 	/* Special-case full-width to full-width copies. */
6959aa5da4cStorek 	if ( op == RAS_SRC && src->width == w && dst->width == w &&
6969aa5da4cStorek 	     src->linelongs == dst->linelongs && src->linelongs == w >> 2 )
6979aa5da4cStorek 	    {
6989aa5da4cStorek 	    bcopy( (char*) srclin1, (char*) dstlin1,
6999aa5da4cStorek 		   h * src->linelongs * sizeof(u_long) );
7009aa5da4cStorek 	    return 0;
7019aa5da4cStorek 	    }
7029aa5da4cStorek #endif /*BCOPY_FASTER*/
7039aa5da4cStorek 
7049aa5da4cStorek 	srcleftignore = ( sx & 3 ) * 8;
7059aa5da4cStorek 	srclongs = ( srcleftignore + w * 8 + 31 ) >> 5;
7069aa5da4cStorek 	srcrightignore = ( srclongs * 32 - w * 8 - srcleftignore ) & 31;
7079aa5da4cStorek 	dstleftignore = ( dx & 3 ) * 8;
7089aa5da4cStorek 	dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
7099aa5da4cStorek 	dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
7109aa5da4cStorek 
7119aa5da4cStorek 	return raster_blit(
7129aa5da4cStorek 	    src, srclin1, srcleftignore, srcrightignore, srclongs,
7139aa5da4cStorek 	    dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
7149aa5da4cStorek 	}
7159aa5da4cStorek 
7169aa5da4cStorek     return 0;
7179aa5da4cStorek     }
7189aa5da4cStorek 
7199aa5da4cStorek /* Semi-public routine to do a no-src bitblit without clipping.  Returns 0
7209aa5da4cStorek ** on success, -1 on failure.
7219aa5da4cStorek */
7229aa5da4cStorek int
raster_op_nosrc_noclip(dst,dx,dy,w,h,rop)7239aa5da4cStorek raster_op_nosrc_noclip( dst, dx, dy, w, h, rop )
7249aa5da4cStorek     struct raster* dst;
7259aa5da4cStorek     int dx, dy, w, h, rop;
7269aa5da4cStorek     {
7279aa5da4cStorek     int op;
7289aa5da4cStorek 
7299aa5da4cStorek     op = RAS_GETOP( rop );
7309aa5da4cStorek 
7319aa5da4cStorek     if ( dst->depth == 1 )
7329aa5da4cStorek 	{
7339aa5da4cStorek 	/* One-bit no-src blit. */
7349aa5da4cStorek 	u_long* dstlin1;
7359aa5da4cStorek 	u_long* dstlin2;
7369aa5da4cStorek 	u_long* dstlin;
7379aa5da4cStorek 	int dstleftignore, dstrightignore, dstlongs;
7389aa5da4cStorek 	u_long dl, lm, nlm, rm, nrm;
7399aa5da4cStorek 	register u_long* dstlong2;
7409aa5da4cStorek 	register u_long* dstlong;
7419aa5da4cStorek 
7429aa5da4cStorek 	dstlin1 = RAS_ADDR( dst, dx, dy );
7439aa5da4cStorek 
7449aa5da4cStorek #ifdef BCOPY_FASTER
7459aa5da4cStorek 	/* Special-case full-width clears. */
7469aa5da4cStorek 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 )
7479aa5da4cStorek 	    {
7489aa5da4cStorek 	    bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) );
7499aa5da4cStorek 	    return 0;
7509aa5da4cStorek 	    }
7519aa5da4cStorek #endif /*BCOPY_FASTER*/
7529aa5da4cStorek 
7539aa5da4cStorek 	dstleftignore = ( dx & 31 );
7549aa5da4cStorek 	dstlongs = ( dstleftignore + w + 31 ) >> 5;
7559aa5da4cStorek 	dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
7569aa5da4cStorek 
7579aa5da4cStorek 	dstlin2 = dstlin1 + h * dst->linelongs;
7589aa5da4cStorek 	dstlin = dstlin1;
7599aa5da4cStorek 
7609aa5da4cStorek 	if ( dstlongs == 1 )
7619aa5da4cStorek 	    {
7629aa5da4cStorek 	    /* It fits into a single longword. */
7639aa5da4cStorek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
7649aa5da4cStorek 	    nlm = ~lm;
7659aa5da4cStorek 	    while ( dstlin != dstlin2 )
7669aa5da4cStorek 		{
7679aa5da4cStorek 		ROP_DST(
7689aa5da4cStorek 		/*op*/  op,
7699aa5da4cStorek 		/*pre*/ dl = *dstlin;,
7709aa5da4cStorek 		/*d*/   dl,
7719aa5da4cStorek 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
7729aa5da4cStorek 
7739aa5da4cStorek 		dstlin += dst->linelongs;
7749aa5da4cStorek 		}
7759aa5da4cStorek 	    }
7769aa5da4cStorek 	else
7779aa5da4cStorek 	    {
7789aa5da4cStorek 	    lm = leftmask[dstleftignore];
7799aa5da4cStorek 	    rm = rightmask[dstrightignore];
7809aa5da4cStorek 	    nrm = ~rm;
7819aa5da4cStorek 	    nlm = ~lm;
7829aa5da4cStorek 
7839aa5da4cStorek 	    while ( dstlin != dstlin2 )
7849aa5da4cStorek 		{
7859aa5da4cStorek 		dstlong = dstlin;
7869aa5da4cStorek 		dstlong2 = dstlong + dstlongs;
7879aa5da4cStorek 		if ( dstrightignore != 0 )
7889aa5da4cStorek 		    --dstlong2;
7899aa5da4cStorek 
7909aa5da4cStorek 		/* Leading edge. */
7919aa5da4cStorek 		if ( dstleftignore != 0 )
7929aa5da4cStorek 		    {
7939aa5da4cStorek 		    ROP_DST(
7949aa5da4cStorek 		    /*op*/  op,
7959aa5da4cStorek 		    /*pre*/ dl = *dstlong;,
7969aa5da4cStorek 		    /*d*/   dl,
7979aa5da4cStorek 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
7989aa5da4cStorek 		    ++dstlong;
7999aa5da4cStorek 		    }
8009aa5da4cStorek 
8019aa5da4cStorek 		/* Main rop. */
8029aa5da4cStorek 		ROP_DST(
8039aa5da4cStorek 		/*op*/  op,
8049aa5da4cStorek 		/*pre*/ while ( dstlong != dstlong2 )
8059aa5da4cStorek 			    {,
8069aa5da4cStorek 		/*d*/       *dstlong,
8079aa5da4cStorek 		/*pst*/     ++dstlong;
8089aa5da4cStorek 			    } )
8099aa5da4cStorek 
8109aa5da4cStorek 		/* Trailing edge. */
8119aa5da4cStorek 		if ( dstrightignore != 0 )
8129aa5da4cStorek 		    {
8139aa5da4cStorek 		    ROP_DST(
8149aa5da4cStorek 		    /*op*/  op,
8159aa5da4cStorek 		    /*pre*/ dl = *dstlong;,
8169aa5da4cStorek 		    /*d*/   dl,
8179aa5da4cStorek 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
8189aa5da4cStorek 		    }
8199aa5da4cStorek 
8209aa5da4cStorek 		dstlin += dst->linelongs;
8219aa5da4cStorek 		}
8229aa5da4cStorek 	    }
8239aa5da4cStorek 	}
8249aa5da4cStorek 
8259aa5da4cStorek     else
8269aa5da4cStorek 	{
8279aa5da4cStorek 	/* Eight-bit no-src blit. */
8289aa5da4cStorek 	register u_long color;
8299aa5da4cStorek 	u_long* dstlin1;
8309aa5da4cStorek 	u_long* dstlin2;
8319aa5da4cStorek 	u_long* dstlin;
8329aa5da4cStorek 	int dstleftignore, dstrightignore, dstlongs;
8339aa5da4cStorek 	u_long dl, lm, nlm, rm, nrm;
8349aa5da4cStorek 	register u_long* dstlong2;
8359aa5da4cStorek 	register u_long* dstlong;
8369aa5da4cStorek 
8379aa5da4cStorek 	dstlin1 = RAS_ADDR( dst, dx, dy );
8389aa5da4cStorek 
8399aa5da4cStorek #ifdef BCOPY_FASTER
8409aa5da4cStorek 	/* Special-case full-width clears. */
8419aa5da4cStorek 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 2 )
8429aa5da4cStorek 	    {
8439aa5da4cStorek 	    bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) );
8449aa5da4cStorek 	    return 0;
8459aa5da4cStorek 	    }
8469aa5da4cStorek #endif /*BCOPY_FASTER*/
8479aa5da4cStorek 
8489aa5da4cStorek 	color = RAS_GETCOLOR( rop );
8499aa5da4cStorek 	if ( color == 0 )
8509aa5da4cStorek 	    color = 255;
8519aa5da4cStorek 
8529aa5da4cStorek 	/* Make 32 bits of color so we can do the ROP without shifting. */
8539aa5da4cStorek 	color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
8549aa5da4cStorek 
8559aa5da4cStorek 	dstleftignore = ( dx & 3 ) * 8;
8569aa5da4cStorek 	dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
8579aa5da4cStorek 	dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
8589aa5da4cStorek 
8599aa5da4cStorek 	dstlin2 = dstlin1 + h * dst->linelongs;
8609aa5da4cStorek 	dstlin = dstlin1;
8619aa5da4cStorek 
8629aa5da4cStorek 	if ( dstlongs == 1 )
8639aa5da4cStorek 	    {
8649aa5da4cStorek 	    /* It fits into a single longword. */
8659aa5da4cStorek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
8669aa5da4cStorek 	    nlm = ~lm;
8679aa5da4cStorek 	    while ( dstlin != dstlin2 )
8689aa5da4cStorek 		{
8699aa5da4cStorek 		ROP_DSTCOLOR(
8709aa5da4cStorek 		/*op*/  op,
8719aa5da4cStorek 		/*pre*/ dl = *dstlin;,
8729aa5da4cStorek 		/*d*/   dl,
8739aa5da4cStorek 		/*c*/	color,
8749aa5da4cStorek 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
8759aa5da4cStorek 
8769aa5da4cStorek 		dstlin += dst->linelongs;
8779aa5da4cStorek 		}
8789aa5da4cStorek 	    }
8799aa5da4cStorek 	else
8809aa5da4cStorek 	    {
8819aa5da4cStorek 	    lm = leftmask[dstleftignore];
8829aa5da4cStorek 	    rm = rightmask[dstrightignore];
8839aa5da4cStorek 	    nrm = ~rm;
8849aa5da4cStorek 	    nlm = ~lm;
8859aa5da4cStorek 	    while ( dstlin != dstlin2 )
8869aa5da4cStorek 		{
8879aa5da4cStorek 		dstlong = dstlin;
8889aa5da4cStorek 		dstlong2 = dstlong + dstlongs;
8899aa5da4cStorek 		if ( dstrightignore != 0 )
8909aa5da4cStorek 		    --dstlong2;
8919aa5da4cStorek 
8929aa5da4cStorek 		/* Leading edge. */
8939aa5da4cStorek 		if ( dstleftignore != 0 )
8949aa5da4cStorek 		    {
8959aa5da4cStorek 		    ROP_DSTCOLOR(
8969aa5da4cStorek 		    /*op*/  op,
8979aa5da4cStorek 		    /*pre*/ dl = *dstlong;,
8989aa5da4cStorek 		    /*d*/   dl,
8999aa5da4cStorek 		    /*c*/   color,
9009aa5da4cStorek 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
9019aa5da4cStorek 		    ++dstlong;
9029aa5da4cStorek 		    }
9039aa5da4cStorek 
9049aa5da4cStorek 		/* Main rop. */
9059aa5da4cStorek 		ROP_DSTCOLOR(
9069aa5da4cStorek 		/*op*/  op,
9079aa5da4cStorek 		/*pre*/ while ( dstlong != dstlong2 )
9089aa5da4cStorek 			    {,
9099aa5da4cStorek 		/*d*/       *dstlong,
9109aa5da4cStorek 		/*c*/       color,
9119aa5da4cStorek 		/*pst*/     ++dstlong;
9129aa5da4cStorek 			    } )
9139aa5da4cStorek 
9149aa5da4cStorek 		/* Trailing edge. */
9159aa5da4cStorek 		if ( dstrightignore != 0 )
9169aa5da4cStorek 		    {
9179aa5da4cStorek 		    ROP_DSTCOLOR(
9189aa5da4cStorek 		    /*op*/  op,
9199aa5da4cStorek 		    /*pre*/ dl = *dstlong;,
9209aa5da4cStorek 		    /*d*/   dl,
9219aa5da4cStorek 		    /*c*/   color,
9229aa5da4cStorek 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
9239aa5da4cStorek 		    }
9249aa5da4cStorek 
9259aa5da4cStorek 		dstlin += dst->linelongs;
9269aa5da4cStorek 		}
9279aa5da4cStorek 	    }
9289aa5da4cStorek 	}
9299aa5da4cStorek 
9309aa5da4cStorek     return 0;
9319aa5da4cStorek     }
9329aa5da4cStorek 
9339aa5da4cStorek /* This is a general bitblit routine, handling overlapping source and
9349aa5da4cStorek ** destination.  It's used for both the 1-to-1 and 8-to-8 cases.
9359aa5da4cStorek */
9369aa5da4cStorek static int
raster_blit(src,srclin1,srcleftignore,srcrightignore,srclongs,dst,dstlin1,dstleftignore,dstrightignore,dstlongs,h,op)9379aa5da4cStorek raster_blit( src, srclin1, srcleftignore, srcrightignore, srclongs, dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op )
9389aa5da4cStorek     struct raster* src;
9399aa5da4cStorek     u_long* srclin1;
9409aa5da4cStorek     int srcleftignore, srcrightignore, srclongs;
9419aa5da4cStorek     struct raster* dst;
9429aa5da4cStorek     u_long* dstlin1;
9439aa5da4cStorek     int dstleftignore, dstrightignore, dstlongs;
9449aa5da4cStorek     int h, op;
9459aa5da4cStorek     {
9469aa5da4cStorek     u_long* srclin2;
9479aa5da4cStorek     u_long* dstlin2;
9489aa5da4cStorek     int srclininc, dstlininc;
9499aa5da4cStorek     u_long* srclin;
9509aa5da4cStorek     u_long* dstlin;
9519aa5da4cStorek     register int prevleftshift, currrightshift;
9529aa5da4cStorek     int longinc;
9539aa5da4cStorek     register u_long* srclong;
9549aa5da4cStorek     register u_long* dstlong;
9559aa5da4cStorek     register u_long* dstlong2;
9569aa5da4cStorek     register u_long dl, lm, nlm, rm, nrm;
9579aa5da4cStorek 
9589aa5da4cStorek     prevleftshift = ( srcleftignore - dstleftignore ) & 31;
9599aa5da4cStorek 
9609aa5da4cStorek     srclin2 = srclin1 + h * src->linelongs;
9619aa5da4cStorek     dstlin2 = dstlin1 + h * dst->linelongs;
9629aa5da4cStorek     srclininc = src->linelongs;
9639aa5da4cStorek     dstlininc = dst->linelongs;
9649aa5da4cStorek     longinc = 1;
9659aa5da4cStorek 
9669aa5da4cStorek     /* Check for overlaps. */
9679aa5da4cStorek     if ( ( dstlin1 >= srclin1 && dstlin1 < srclin1 + srclongs ) ||
9689aa5da4cStorek 	 ( srclin1 >= dstlin1 && srclin1 < dstlin1 + dstlongs ) )
9699aa5da4cStorek 	{
9709aa5da4cStorek 	/* Horizontal overlap.  Should we reverse? */
9719aa5da4cStorek 	if ( srclin1 < dstlin1 )
9729aa5da4cStorek 	    {
9739aa5da4cStorek 	    longinc = -1;
9749aa5da4cStorek 	    srclin1 += srclongs - 1;
9759aa5da4cStorek 	    srclin2 += srclongs - 1;
9769aa5da4cStorek 	    dstlin1 += dstlongs - 1;
9779aa5da4cStorek 	    }
9789aa5da4cStorek 	}
9799aa5da4cStorek     else if ( ( dstlin1 >= srclin1 && dstlin1 < srclin2 ) ||
9809aa5da4cStorek 	      ( srclin1 >= dstlin1 && srclin1 < dstlin2 ) )
9819aa5da4cStorek 	{
9829aa5da4cStorek 	/* Vertical overlap.  Should we reverse? */
9839aa5da4cStorek 	if ( srclin1 < dstlin1 )
9849aa5da4cStorek 	    {
9859aa5da4cStorek 	    srclin2 = srclin1 - srclininc;
9869aa5da4cStorek 	    srclin1 += ( h - 1 ) * srclininc;
9879aa5da4cStorek 	    dstlin1 += ( h - 1 ) * dstlininc;
9889aa5da4cStorek 	    srclininc = -srclininc;
9899aa5da4cStorek 	    dstlininc = -dstlininc;
9909aa5da4cStorek 	    }
9919aa5da4cStorek 	}
9929aa5da4cStorek     srclin = srclin1;
9939aa5da4cStorek     dstlin = dstlin1;
9949aa5da4cStorek 
9959aa5da4cStorek     if ( prevleftshift == 0 )
9969aa5da4cStorek 	{
9979aa5da4cStorek 	/* The bits line up, no shifting necessary. */
9989aa5da4cStorek 	if ( dstlongs == 1 )
9999aa5da4cStorek 	    {
10009aa5da4cStorek 	    /* It all fits into a single longword. */
10019aa5da4cStorek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
10029aa5da4cStorek 	    nlm = ~lm;
10039aa5da4cStorek 	    while ( srclin != srclin2 )
10049aa5da4cStorek 		{
10059aa5da4cStorek 		ROP_SRCDST(
10069aa5da4cStorek 		/*op*/  op,
10079aa5da4cStorek 		/*pre*/ dl = *dstlin;,
10089aa5da4cStorek 		/*s*/   *srclin,
10099aa5da4cStorek 		/*d*/   dl,
10109aa5da4cStorek 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
10119aa5da4cStorek 
10129aa5da4cStorek 		srclin += srclininc;
10139aa5da4cStorek 		dstlin += dstlininc;
10149aa5da4cStorek 		}
10159aa5da4cStorek 	    }
10169aa5da4cStorek 	else
10179aa5da4cStorek 	    {
10189aa5da4cStorek 	    /* Multiple longwords. */
10199aa5da4cStorek 	    lm = leftmask[dstleftignore];
10209aa5da4cStorek 	    rm = rightmask[dstrightignore];
10219aa5da4cStorek 	    nrm = ~rm;
10229aa5da4cStorek 	    nlm = ~lm;
10239aa5da4cStorek 	    if ( longinc == 1 )
10249aa5da4cStorek 		{
10259aa5da4cStorek 		/* Left to right. */
10269aa5da4cStorek 		while ( srclin != srclin2 )
10279aa5da4cStorek 		    {
10289aa5da4cStorek 		    srclong = srclin;
10299aa5da4cStorek 		    dstlong = dstlin;
10309aa5da4cStorek 		    dstlong2 = dstlong + dstlongs;
10319aa5da4cStorek 		    if ( dstrightignore != 0 )
10329aa5da4cStorek 			--dstlong2;
10339aa5da4cStorek 
10349aa5da4cStorek 		    /* Leading edge. */
10359aa5da4cStorek 		    if ( dstleftignore != 0 )
10369aa5da4cStorek 			{
10379aa5da4cStorek 			ROP_SRCDST(
10389aa5da4cStorek 			/*op*/  op,
10399aa5da4cStorek 			/*pre*/ dl = *dstlong;,
10409aa5da4cStorek 			/*s*/   *srclong,
10419aa5da4cStorek 			/*d*/   dl,
10429aa5da4cStorek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
10439aa5da4cStorek 			++srclong;
10449aa5da4cStorek 			++dstlong;
10459aa5da4cStorek 			}
10469aa5da4cStorek 
10479aa5da4cStorek 		    /* Main rop. */
10489aa5da4cStorek 		    ROP_SRCDST(
10499aa5da4cStorek 		    /*op*/  op,
10509aa5da4cStorek 		    /*pre*/ while ( dstlong != dstlong2 )
10519aa5da4cStorek 				{,
10529aa5da4cStorek 		    /*s*/       *srclong,
10539aa5da4cStorek 		    /*d*/       *dstlong,
10549aa5da4cStorek 		    /*pst*/     ++srclong;
10559aa5da4cStorek 				++dstlong;
10569aa5da4cStorek 				} )
10579aa5da4cStorek 
10589aa5da4cStorek 		    /* Trailing edge. */
10599aa5da4cStorek 		    if ( dstrightignore != 0 )
10609aa5da4cStorek 			{
10619aa5da4cStorek 			ROP_SRCDST(
10629aa5da4cStorek 			/*op*/  op,
10639aa5da4cStorek 			/*pre*/ dl = *dstlong;,
10649aa5da4cStorek 			/*s*/   *srclong,
10659aa5da4cStorek 			/*d*/   dl,
10669aa5da4cStorek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
10679aa5da4cStorek 			}
10689aa5da4cStorek 
10699aa5da4cStorek 		    srclin += srclininc;
10709aa5da4cStorek 		    dstlin += dstlininc;
10719aa5da4cStorek 		    }
10729aa5da4cStorek 		}
10739aa5da4cStorek 	    else
10749aa5da4cStorek 		{
10759aa5da4cStorek 		/* Right to left. */
10769aa5da4cStorek 		while ( srclin != srclin2 )
10779aa5da4cStorek 		    {
10789aa5da4cStorek 		    srclong = srclin;
10799aa5da4cStorek 		    dstlong = dstlin;
10809aa5da4cStorek 		    dstlong2 = dstlong - dstlongs;
10819aa5da4cStorek 		    if ( dstleftignore != 0 )
10829aa5da4cStorek 			++dstlong2;
10839aa5da4cStorek 
10849aa5da4cStorek 		    /* Leading edge. */
10859aa5da4cStorek 		    if ( dstrightignore != 0 )
10869aa5da4cStorek 			{
10879aa5da4cStorek 			ROP_SRCDST(
10889aa5da4cStorek 			/*op*/  op,
10899aa5da4cStorek 			/*pre*/ dl = *dstlong;,
10909aa5da4cStorek 			/*s*/   *srclong,
10919aa5da4cStorek 			/*d*/   dl,
10929aa5da4cStorek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
10939aa5da4cStorek 			--srclong;
10949aa5da4cStorek 			--dstlong;
10959aa5da4cStorek 			}
10969aa5da4cStorek 
10979aa5da4cStorek 		    /* Main rop. */
10989aa5da4cStorek 		    ROP_SRCDST(
10999aa5da4cStorek 		    /*op*/  op,
11009aa5da4cStorek 		    /*pre*/ while ( dstlong != dstlong2 )
11019aa5da4cStorek 				{,
11029aa5da4cStorek 		    /*s*/       *srclong,
11039aa5da4cStorek 		    /*d*/       *dstlong,
11049aa5da4cStorek 		    /*pst*/     --srclong;
11059aa5da4cStorek 				--dstlong;
11069aa5da4cStorek 				} )
11079aa5da4cStorek 
11089aa5da4cStorek 		    /* Trailing edge. */
11099aa5da4cStorek 		    if ( dstleftignore != 0 )
11109aa5da4cStorek 			{
11119aa5da4cStorek 			ROP_SRCDST(
11129aa5da4cStorek 			/*op*/  op,
11139aa5da4cStorek 			/*pre*/ dl = *dstlong;,
11149aa5da4cStorek 			/*s*/   *srclong,
11159aa5da4cStorek 			/*d*/   dl,
11169aa5da4cStorek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
11179aa5da4cStorek 			}
11189aa5da4cStorek 
11199aa5da4cStorek 		    srclin += srclininc;
11209aa5da4cStorek 		    dstlin += dstlininc;
11219aa5da4cStorek 		    }
11229aa5da4cStorek 		}
11239aa5da4cStorek 	    }
11249aa5da4cStorek 	}
11259aa5da4cStorek 
11269aa5da4cStorek     else
11279aa5da4cStorek 	{
11289aa5da4cStorek 	/* General case, with shifting and everything. */
11299aa5da4cStorek 	register u_long sl, prevsl;
11309aa5da4cStorek 
11319aa5da4cStorek 	currrightshift = 32 - prevleftshift;
11329aa5da4cStorek 	if ( srclongs == 1 && dstlongs == 1 )
11339aa5da4cStorek 	    {
11349aa5da4cStorek 	    /* It fits into a single longword, with a shift. */
11359aa5da4cStorek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
11369aa5da4cStorek 	    nlm = ~lm;
11379aa5da4cStorek 	    if ( srcleftignore > dstleftignore )
11389aa5da4cStorek 		{
11399aa5da4cStorek 		while ( srclin != srclin2 )
11409aa5da4cStorek 		    {
11419aa5da4cStorek 		    ROP_SRCDST(
11429aa5da4cStorek 		    /*op*/  op,
11439aa5da4cStorek 		    /*pre*/ dl = *dstlin;,
11449aa5da4cStorek 		    /*s*/   *srclin << prevleftshift,
11459aa5da4cStorek 		    /*d*/   dl,
11469aa5da4cStorek 		    /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
11479aa5da4cStorek 
11489aa5da4cStorek 		    srclin += srclininc;
11499aa5da4cStorek 		    dstlin += dstlininc;
11509aa5da4cStorek 		    }
11519aa5da4cStorek 		}
11529aa5da4cStorek 	    else
11539aa5da4cStorek 		{
11549aa5da4cStorek 		while ( srclin != srclin2 )
11559aa5da4cStorek 		    {
11569aa5da4cStorek 		    ROP_SRCDST(
11579aa5da4cStorek 		    /*op*/  op,
11589aa5da4cStorek 		    /*pre*/ dl = *dstlin;,
11599aa5da4cStorek 		    /*s*/   *srclin >> currrightshift,
11609aa5da4cStorek 		    /*d*/   dl,
11619aa5da4cStorek 		    /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
11629aa5da4cStorek 
11639aa5da4cStorek 		    srclin += srclininc;
11649aa5da4cStorek 		    dstlin += dstlininc;
11659aa5da4cStorek 		    }
11669aa5da4cStorek 		}
11679aa5da4cStorek 	    }
11689aa5da4cStorek 	else
11699aa5da4cStorek 	    {
11709aa5da4cStorek 	    /* Multiple longwords. */
11719aa5da4cStorek 	    lm = leftmask[dstleftignore];
11729aa5da4cStorek 	    rm = rightmask[dstrightignore];
11739aa5da4cStorek 	    nrm = ~rm;
11749aa5da4cStorek 	    nlm = ~lm;
11759aa5da4cStorek 	    if ( longinc == 1 )
11769aa5da4cStorek 		{
11779aa5da4cStorek 		/* Left to right. */
11789aa5da4cStorek 		while ( srclin != srclin2 )
11799aa5da4cStorek 		    {
11809aa5da4cStorek 		    srclong = srclin;
11819aa5da4cStorek 		    dstlong = dstlin;
11829aa5da4cStorek 		    dstlong2 = dstlong + dstlongs;
11839aa5da4cStorek 		    if ( srcleftignore > dstleftignore )
11849aa5da4cStorek 			prevsl = *srclong++ << prevleftshift;
11859aa5da4cStorek 		    else
11869aa5da4cStorek 			prevsl = 0;
11879aa5da4cStorek 		    if ( dstrightignore != 0 )
11889aa5da4cStorek 			--dstlong2;
11899aa5da4cStorek 
11909aa5da4cStorek 		    /* Leading edge. */
11919aa5da4cStorek 		    if ( dstleftignore != 0 )
11929aa5da4cStorek 			{
11939aa5da4cStorek 			ROP_SRCDST(
11949aa5da4cStorek 			/*op*/  op,
11959aa5da4cStorek 			/*pre*/ sl = *srclong;
11969aa5da4cStorek 				dl = *dstlong;,
11979aa5da4cStorek 			/*s*/   prevsl | ( sl >> currrightshift ),
11989aa5da4cStorek 			/*d*/   dl,
11999aa5da4cStorek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
12009aa5da4cStorek 			prevsl = sl << prevleftshift;
12019aa5da4cStorek 			++srclong;
12029aa5da4cStorek 			++dstlong;
12039aa5da4cStorek 			}
12049aa5da4cStorek 
12059aa5da4cStorek 		    /* Main rop. */
12069aa5da4cStorek 		    ROP_SRCDST(
12079aa5da4cStorek 		    /*op*/  op,
12089aa5da4cStorek 		    /*pre*/ while ( dstlong != dstlong2 )
12099aa5da4cStorek 				{
12109aa5da4cStorek 				sl = *srclong;,
12119aa5da4cStorek 		    /*s*/       prevsl | ( sl >> currrightshift ),
12129aa5da4cStorek 		    /*d*/       *dstlong,
12139aa5da4cStorek 		    /*pst*/     prevsl = sl << prevleftshift;
12149aa5da4cStorek 				++srclong;
12159aa5da4cStorek 				++dstlong;
12169aa5da4cStorek 				} )
12179aa5da4cStorek 
12189aa5da4cStorek 		    /* Trailing edge. */
12199aa5da4cStorek 		    if ( dstrightignore != 0 )
12209aa5da4cStorek 			{
12219aa5da4cStorek 			ROP_SRCDST(
12229aa5da4cStorek 			/*op*/  op,
12239aa5da4cStorek 			/*pre*/ dl = *dstlong;,
12249aa5da4cStorek 			/*s*/   prevsl | ( *srclong >> currrightshift ),
12259aa5da4cStorek 			/*d*/   dl,
12269aa5da4cStorek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
12279aa5da4cStorek 			}
12289aa5da4cStorek 
12299aa5da4cStorek 		    srclin += srclininc;
12309aa5da4cStorek 		    dstlin += dstlininc;
12319aa5da4cStorek 		    }
12329aa5da4cStorek 		}
12339aa5da4cStorek 	    else
12349aa5da4cStorek 		{
12359aa5da4cStorek 		/* Right to left. */
12369aa5da4cStorek 		while ( srclin != srclin2 )
12379aa5da4cStorek 		    {
12389aa5da4cStorek 		    srclong = srclin;
12399aa5da4cStorek 		    dstlong = dstlin;
12409aa5da4cStorek 		    dstlong2 = dstlong - dstlongs;
12419aa5da4cStorek 		    if ( srcrightignore > dstrightignore )
12429aa5da4cStorek 			prevsl = *srclong-- >> currrightshift;
12439aa5da4cStorek 		    else
12449aa5da4cStorek 			prevsl = 0;
12459aa5da4cStorek 		    if ( dstleftignore != 0 )
12469aa5da4cStorek 			++dstlong2;
12479aa5da4cStorek 
12489aa5da4cStorek 		    /* Leading edge. */
12499aa5da4cStorek 		    if ( dstrightignore != 0 )
12509aa5da4cStorek 			{
12519aa5da4cStorek 			ROP_SRCDST(
12529aa5da4cStorek 			/*op*/  op,
12539aa5da4cStorek 			/*pre*/ sl = *srclong;
12549aa5da4cStorek 				dl = *dstlong;,
12559aa5da4cStorek 			/*s*/   prevsl | ( sl << prevleftshift ),
12569aa5da4cStorek 			/*d*/   dl,
12579aa5da4cStorek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
12589aa5da4cStorek 			prevsl = sl >> currrightshift;
12599aa5da4cStorek 			--srclong;
12609aa5da4cStorek 			--dstlong;
12619aa5da4cStorek 			}
12629aa5da4cStorek 
12639aa5da4cStorek 		    /* Main rop. */
12649aa5da4cStorek 		    ROP_SRCDST(
12659aa5da4cStorek 		    /*op*/  op,
12669aa5da4cStorek 		    /*pre*/ while ( dstlong != dstlong2 )
12679aa5da4cStorek 				{
12689aa5da4cStorek 				sl = *srclong;,
12699aa5da4cStorek 		    /*s*/       prevsl | ( sl << prevleftshift ),
12709aa5da4cStorek 		    /*d*/       *dstlong,
12719aa5da4cStorek 		    /*pst*/     prevsl = sl >> currrightshift;
12729aa5da4cStorek 				--srclong;
12739aa5da4cStorek 				--dstlong;
12749aa5da4cStorek 				} )
12759aa5da4cStorek 
12769aa5da4cStorek 		    /* Trailing edge. */
12779aa5da4cStorek 		    if ( dstleftignore != 0 )
12789aa5da4cStorek 			{
12799aa5da4cStorek 			ROP_SRCDST(
12809aa5da4cStorek 			/*op*/  op,
12819aa5da4cStorek 			/*pre*/ dl = *dstlong;,
12829aa5da4cStorek 			/*s*/   prevsl | ( *srclong << prevleftshift ),
12839aa5da4cStorek 			/*d*/   dl,
12849aa5da4cStorek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
12859aa5da4cStorek 			}
12869aa5da4cStorek 
12879aa5da4cStorek 		    srclin += srclininc;
12889aa5da4cStorek 		    dstlin += dstlininc;
12899aa5da4cStorek 		    }
12909aa5da4cStorek 		}
12919aa5da4cStorek 	    }
12929aa5da4cStorek 	}
12939aa5da4cStorek 
12949aa5da4cStorek     return 0;
12959aa5da4cStorek     }
1296