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