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