Home | History | Annotate | Line # | Download | only in fb
      1 /*
      2  * Copyright  1998 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that
      7  * copyright notice and this permission notice appear in supporting
      8  * documentation, and that the name of Keith Packard not be used in
      9  * advertising or publicity pertaining to distribution of the software without
     10  * specific, written prior permission.  Keith Packard makes no
     11  * representations about the suitability of this software for any purpose.  It
     12  * is provided "as is" without express or implied warranty.
     13  *
     14  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     20  * PERFORMANCE OF THIS SOFTWARE.
     21  */
     22 
     23 /*
     24  * This file defines functions for drawing some primitives using
     25  * underlying datatypes instead of masks
     26  */
     27 
     28 #define isClipped(c,ul,lr)  (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000)
     29 
     30 #ifdef HAVE_DIX_CONFIG_H
     31 #include <dix-config.h>
     32 #endif
     33 
     34 #ifdef BITSMUL
     35 #define MUL BITSMUL
     36 #else
     37 #define MUL 1
     38 #endif
     39 
     40 #ifdef BITSSTORE
     41 #define STORE(b,x)  BITSSTORE(b,x)
     42 #else
     43 #define STORE(b,x)  WRITE((b), (x))
     44 #endif
     45 
     46 #ifdef BITSRROP
     47 #define RROP(b,a,x)	BITSRROP(b,a,x)
     48 #else
     49 #define RROP(b,a,x)	WRITE((b), FbDoRRop (READ(b), (a), (x)))
     50 #endif
     51 
     52 #ifdef BITSUNIT
     53 #define UNIT BITSUNIT
     54 #define USE_SOLID
     55 #else
     56 #define UNIT BITS
     57 #endif
     58 
     59 /*
     60  * Define the following before including this file:
     61  *
     62  *  BRESSOLID	name of function for drawing a solid segment
     63  *  BRESDASH	name of function for drawing a dashed segment
     64  *  DOTS	name of function for drawing dots
     65  *  ARC		name of function for drawing a solid arc
     66  *  BITS	type of underlying unit
     67  */
     68 
     69 #ifdef BRESSOLID
     70 void
     71 BRESSOLID (DrawablePtr	pDrawable,
     72 	   GCPtr	pGC,
     73 	   int		dashOffset,
     74 	   int		signdx,
     75 	   int		signdy,
     76 	   int		axis,
     77 	   int		x1,
     78 	   int		y1,
     79 	   int		e,
     80 	   int		e1,
     81 	   int		e3,
     82 	   int		len)
     83 {
     84     FbBits	*dst;
     85     FbStride	dstStride;
     86     int		dstBpp;
     87     int		dstXoff, dstYoff;
     88     FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
     89     UNIT	*bits;
     90     FbStride	bitsStride;
     91     FbStride	majorStep, minorStep;
     92     BITS	xor = (BITS) pPriv->xor;
     93 
     94     fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
     95     bits = ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff) * MUL;
     96     bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
     97     if (signdy < 0)
     98 	bitsStride = -bitsStride;
     99     if (axis == X_AXIS)
    100     {
    101 	majorStep = signdx * MUL;
    102 	minorStep = bitsStride;
    103     }
    104     else
    105     {
    106 	majorStep = bitsStride;
    107 	minorStep = signdx * MUL;
    108     }
    109     while (len--)
    110     {
    111 	STORE(bits,xor);
    112 	bits += majorStep;
    113 	e += e1;
    114 	if (e >= 0)
    115 	{
    116 	    bits += minorStep;
    117 	    e += e3;
    118 	}
    119     }
    120 
    121     fbFinishAccess (pDrawable);
    122 }
    123 #endif
    124 
    125 #ifdef BRESDASH
    126 void
    127 BRESDASH (DrawablePtr	pDrawable,
    128 	  GCPtr		pGC,
    129 	  int		dashOffset,
    130 	  int		signdx,
    131 	  int		signdy,
    132 	  int		axis,
    133 	  int		x1,
    134 	  int		y1,
    135 	  int		e,
    136 	  int		e1,
    137 	  int		e3,
    138 	  int		len)
    139 {
    140     FbBits	*dst;
    141     FbStride	dstStride;
    142     int		dstBpp;
    143     int		dstXoff, dstYoff;
    144     FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
    145     UNIT	*bits;
    146     FbStride	bitsStride;
    147     FbStride	majorStep, minorStep;
    148     BITS	xorfg, xorbg;
    149     FbDashDeclare;
    150     int		dashlen;
    151     Bool	even;
    152     Bool	doOdd;
    153 
    154     fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
    155     doOdd = pGC->lineStyle == LineDoubleDash;
    156     xorfg = (BITS) pPriv->xor;
    157     xorbg = (BITS) pPriv->bgxor;
    158 
    159     FbDashInit (pGC, pPriv, dashOffset, dashlen, even);
    160 
    161     bits = ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff) * MUL;
    162     bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
    163     if (signdy < 0)
    164 	bitsStride = -bitsStride;
    165     if (axis == X_AXIS)
    166     {
    167 	majorStep = signdx * MUL;
    168 	minorStep = bitsStride;
    169     }
    170     else
    171     {
    172 	majorStep = bitsStride;
    173 	minorStep = signdx * MUL;
    174     }
    175     if (dashlen >= len)
    176 	dashlen = len;
    177     if (doOdd)
    178     {
    179 	if (!even)
    180 	    goto doubleOdd;
    181 	for (;;)
    182 	{
    183 	    len -= dashlen;
    184 	    while (dashlen--)
    185 	    {
    186 		STORE(bits,xorfg);
    187 		bits += majorStep;
    188 		if ((e += e1) >= 0)
    189 		{
    190 		    e += e3;
    191 		    bits += minorStep;
    192 		}
    193 	    }
    194 	    if (!len)
    195 		break;
    196 
    197 	    FbDashNextEven(dashlen);
    198 
    199 	    if (dashlen >= len)
    200 		dashlen = len;
    201 doubleOdd:
    202 	    len -= dashlen;
    203 	    while (dashlen--)
    204 	    {
    205 		STORE(bits,xorbg);
    206 		bits += majorStep;
    207 		if ((e += e1) >= 0)
    208 		{
    209 		    e += e3;
    210 		    bits += minorStep;
    211 		}
    212 	    }
    213 	    if (!len)
    214 		break;
    215 
    216 	    FbDashNextOdd(dashlen);
    217 
    218 	    if (dashlen >= len)
    219 		dashlen = len;
    220 	}
    221     }
    222     else
    223     {
    224 	if (!even)
    225 	    goto onOffOdd;
    226 	for (;;)
    227 	{
    228 	    len -= dashlen;
    229 	    while (dashlen--)
    230 	    {
    231 		STORE(bits,xorfg);
    232 		bits += majorStep;
    233 		if ((e += e1) >= 0)
    234 		{
    235 		    e += e3;
    236 		    bits += minorStep;
    237 		}
    238 	    }
    239 	    if (!len)
    240 		break;
    241 
    242 	    FbDashNextEven (dashlen);
    243 
    244 	    if (dashlen >= len)
    245 		dashlen = len;
    246 onOffOdd:
    247 	    len -= dashlen;
    248 	    while (dashlen--)
    249 	    {
    250 		bits += majorStep;
    251 		if ((e += e1) >= 0)
    252 		{
    253 		    e += e3;
    254 		    bits += minorStep;
    255 		}
    256 	    }
    257 	    if (!len)
    258 		break;
    259 
    260 	    FbDashNextOdd (dashlen);
    261 
    262 	    if (dashlen >= len)
    263 		dashlen = len;
    264 	}
    265     }
    266 
    267     fbFinishAccess (pDrawable);
    268 }
    269 #endif
    270 
    271 #ifdef DOTS
    272 void
    273 DOTS (FbBits	    *dst,
    274       FbStride	    dstStride,
    275       int	    dstBpp,
    276       BoxPtr	    pBox,
    277       xPoint	    *ptsOrig,
    278       int	    npt,
    279       int	    xorg,
    280       int	    yorg,
    281       int	    xoff,
    282       int	    yoff,
    283       FbBits	    and,
    284       FbBits	    xor)
    285 {
    286     INT32    	*pts = (INT32 *) ptsOrig;
    287     UNIT	*bits = (UNIT *) dst;
    288     UNIT	*point;
    289     BITS	bxor = (BITS) xor;
    290     BITS	band = (BITS) and;
    291     FbStride	bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
    292     INT32    	ul, lr;
    293     INT32    	pt;
    294 
    295     ul = coordToInt(pBox->x1 - xorg,     pBox->y1 - yorg);
    296     lr = coordToInt(pBox->x2 - xorg - 1, pBox->y2 - yorg - 1);
    297 
    298     bits += bitsStride * (yorg + yoff) + (xorg + xoff) * MUL;
    299 
    300     if (and == 0)
    301     {
    302 	while (npt--)
    303 	{
    304 	    pt = *pts++;
    305 	    if (!isClipped(pt,ul,lr))
    306 	    {
    307 		point = bits + intToY(pt) * bitsStride + intToX(pt) * MUL;
    308 		STORE(point,bxor);
    309 	    }
    310 	}
    311     }
    312     else
    313     {
    314 	while (npt--)
    315 	{
    316 	    pt = *pts++;
    317 	    if (!isClipped(pt,ul,lr))
    318 	    {
    319 		point = bits + intToY(pt) * bitsStride + intToX(pt) * MUL;
    320 		RROP(point,band,bxor);
    321 	    }
    322 	}
    323     }
    324 }
    325 #endif
    326 
    327 #ifdef ARC
    328 
    329 #define ARCCOPY(d)  STORE(d,xorBits)
    330 #define ARCRROP(d)  RROP(d,andBits,xorBits)
    331 
    332 void
    333 ARC (FbBits	*dst,
    334      FbStride	dstStride,
    335      int	dstBpp,
    336      xArc	*arc,
    337      int	drawX,
    338      int	drawY,
    339      FbBits	and,
    340      FbBits	xor)
    341 {
    342     UNIT	    *bits;
    343     FbStride	    bitsStride;
    344     miZeroArcRec    info;
    345     Bool	    do360;
    346     int		    x;
    347     UNIT	    *yorgp, *yorgop;
    348     BITS	    andBits, xorBits;
    349     int		    yoffset, dyoffset;
    350     int		    y, a, b, d, mask;
    351     int		    k1, k3, dx, dy;
    352 
    353     bits = (UNIT *) dst;
    354     bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
    355     andBits = (BITS) and;
    356     xorBits = (BITS) xor;
    357     do360 = miZeroArcSetup(arc, &info, TRUE);
    358     yorgp = bits + ((info.yorg + drawY) * bitsStride);
    359     yorgop = bits + ((info.yorgo + drawY) * bitsStride);
    360     info.xorg = (info.xorg + drawX) * MUL;
    361     info.xorgo = (info.xorgo + drawX) * MUL;
    362     MIARCSETUP();
    363     yoffset = y ? bitsStride : 0;
    364     dyoffset = 0;
    365     mask = info.initialMask;
    366 
    367     if (!(arc->width & 1))
    368     {
    369 	if (andBits == 0)
    370 	{
    371 	    if (mask & 2)
    372 		ARCCOPY(yorgp + info.xorgo);
    373 	    if (mask & 8)
    374 		ARCCOPY(yorgop + info.xorgo);
    375 	}
    376 	else
    377 	{
    378 	    if (mask & 2)
    379 		ARCRROP(yorgp + info.xorgo);
    380 	    if (mask & 8)
    381 		ARCRROP(yorgop + info.xorgo);
    382 	}
    383     }
    384     if (!info.end.x || !info.end.y)
    385     {
    386 	mask = info.end.mask;
    387 	info.end = info.altend;
    388     }
    389     if (do360 && (arc->width == arc->height) && !(arc->width & 1))
    390     {
    391 	int xoffset = bitsStride;
    392 	UNIT *yorghb = yorgp + (info.h * bitsStride) + info.xorg;
    393 	UNIT *yorgohb = yorghb - info.h * MUL;
    394 
    395 	yorgp += info.xorg;
    396 	yorgop += info.xorg;
    397 	yorghb += info.h * MUL;
    398 	while (1)
    399 	{
    400 	    if (andBits == 0)
    401 	    {
    402 		ARCCOPY(yorgp + yoffset + x * MUL);
    403 		ARCCOPY(yorgp + yoffset - x * MUL);
    404 		ARCCOPY(yorgop - yoffset - x * MUL);
    405 		ARCCOPY(yorgop - yoffset + x * MUL);
    406 	    }
    407 	    else
    408 	    {
    409 		ARCRROP(yorgp + yoffset + x * MUL);
    410 		ARCRROP(yorgp + yoffset - x * MUL);
    411 		ARCRROP(yorgop - yoffset - x * MUL);
    412 		ARCRROP(yorgop - yoffset + x * MUL);
    413 	    }
    414 	    if (a < 0)
    415 		break;
    416 	    if (andBits == 0)
    417 	    {
    418 		ARCCOPY(yorghb - xoffset - y * MUL);
    419 		ARCCOPY(yorgohb - xoffset + y * MUL);
    420 		ARCCOPY(yorgohb + xoffset + y * MUL);
    421 		ARCCOPY(yorghb + xoffset - y * MUL);
    422 	    }
    423 	    else
    424 	    {
    425 		ARCRROP(yorghb - xoffset - y * MUL);
    426 		ARCRROP(yorgohb - xoffset + y * MUL);
    427 		ARCRROP(yorgohb + xoffset + y * MUL);
    428 		ARCRROP(yorghb + xoffset - y * MUL);
    429 	    }
    430 	    xoffset += bitsStride;
    431 	    MIARCCIRCLESTEP(yoffset += bitsStride;);
    432 	}
    433 	yorgp -= info.xorg;
    434 	yorgop -= info.xorg;
    435 	x = info.w;
    436 	yoffset = info.h * bitsStride;
    437     }
    438     else if (do360)
    439     {
    440 	while (y < info.h || x < info.w)
    441 	{
    442 	    MIARCOCTANTSHIFT(dyoffset = bitsStride;);
    443 	    if (andBits == 0)
    444 	    {
    445 		ARCCOPY(yorgp + yoffset + info.xorg + x * MUL);
    446 		ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL);
    447 		ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL);
    448 		ARCCOPY(yorgop - yoffset + info.xorg + x * MUL);
    449 	    }
    450 	    else
    451 	    {
    452 		ARCRROP(yorgp + yoffset + info.xorg + x * MUL);
    453 		ARCRROP(yorgp + yoffset + info.xorgo - x * MUL);
    454 		ARCRROP(yorgop - yoffset + info.xorgo - x * MUL);
    455 		ARCRROP(yorgop - yoffset + info.xorg + x * MUL);
    456 	    }
    457 	    MIARCSTEP(yoffset += dyoffset;, yoffset += bitsStride;);
    458 	}
    459     }
    460     else
    461     {
    462 	while (y < info.h || x < info.w)
    463 	{
    464 	    MIARCOCTANTSHIFT(dyoffset = bitsStride;);
    465 	    if ((x == info.start.x) || (y == info.start.y))
    466 	    {
    467 		mask = info.start.mask;
    468 		info.start = info.altstart;
    469 	    }
    470 	    if (andBits == 0)
    471 	    {
    472 		if (mask & 1)
    473 		    ARCCOPY(yorgp + yoffset + info.xorg + x * MUL);
    474 		if (mask & 2)
    475 		    ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL);
    476 		if (mask & 4)
    477 		    ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL);
    478 		if (mask & 8)
    479 		    ARCCOPY(yorgop - yoffset + info.xorg + x * MUL);
    480 	    }
    481 	    else
    482 	    {
    483 		if (mask & 1)
    484 		    ARCRROP(yorgp + yoffset + info.xorg + x * MUL);
    485 		if (mask & 2)
    486 		    ARCRROP(yorgp + yoffset + info.xorgo - x * MUL);
    487 		if (mask & 4)
    488 		    ARCRROP(yorgop - yoffset + info.xorgo - x * MUL);
    489 		if (mask & 8)
    490 		    ARCRROP(yorgop - yoffset + info.xorg + x * MUL);
    491 	    }
    492 	    if ((x == info.end.x) || (y == info.end.y))
    493 	    {
    494 		mask = info.end.mask;
    495 		info.end = info.altend;
    496 	    }
    497 	    MIARCSTEP(yoffset += dyoffset;, yoffset += bitsStride;);
    498 	}
    499     }
    500     if ((x == info.start.x) || (y == info.start.y))
    501 	mask = info.start.mask;
    502     if (andBits == 0)
    503     {
    504 	if (mask & 1)
    505 	    ARCCOPY(yorgp + yoffset + info.xorg + x * MUL);
    506 	if (mask & 4)
    507 	    ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL);
    508 	if (arc->height & 1)
    509 	{
    510 	    if (mask & 2)
    511 		ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL);
    512 	    if (mask & 8)
    513 		ARCCOPY(yorgop - yoffset + info.xorg + x * MUL);
    514 	}
    515     }
    516     else
    517     {
    518 	if (mask & 1)
    519 	    ARCRROP(yorgp + yoffset + info.xorg + x * MUL);
    520 	if (mask & 4)
    521 	    ARCRROP(yorgop - yoffset + info.xorgo - x * MUL);
    522 	if (arc->height & 1)
    523 	{
    524 	    if (mask & 2)
    525 		ARCRROP(yorgp + yoffset + info.xorgo - x * MUL);
    526 	    if (mask & 8)
    527 		ARCRROP(yorgop - yoffset + info.xorg + x * MUL);
    528 	}
    529     }
    530 }
    531 #undef ARCCOPY
    532 #undef ARCRROP
    533 #endif
    534 
    535 #ifdef GLYPH
    536 #if BITMAP_BIT_ORDER == LSBFirst
    537 # define WRITE_ADDR1(n)	    (n)
    538 # define WRITE_ADDR2(n)	    (n)
    539 # define WRITE_ADDR4(n)	    (n)
    540 #else
    541 # define WRITE_ADDR1(n)	    ((n) ^ 3)
    542 # define WRITE_ADDR2(n)	    ((n) ^ 2)
    543 # define WRITE_ADDR4(n)	    ((n))
    544 #endif
    545 
    546 #define WRITE1(d,n,fg)	    WRITE(d + WRITE_ADDR1(n), (BITS) (fg))
    547 
    548 #ifdef BITS2
    549 # define WRITE2(d,n,fg)	    WRITE((BITS2 *) &((d)[WRITE_ADDR2(n)]), (BITS2) (fg))
    550 #else
    551 # define WRITE2(d,n,fg)	    (WRITE1(d,n,fg), WRITE1(d,(n)+1,fg))
    552 #endif
    553 
    554 #ifdef BITS4
    555 # define WRITE4(d,n,fg)	    WRITE((BITS4 *) &((d)[WRITE_ADDR4(n)]), (BITS4) (fg))
    556 #else
    557 # define WRITE4(d,n,fg)	    (WRITE2(d,n,fg), WRITE2(d,(n)+2,fg))
    558 #endif
    559 
    560 void
    561 GLYPH (FbBits	*dstBits,
    562    FbStride	dstStride,
    563    int	dstBpp,
    564    FbStip	*stipple,
    565    FbBits	fg,
    566    int	x,
    567    int	height)
    568 {
    569     int	    lshift;
    570     FbStip  bits;
    571     BITS    *dstLine;
    572     BITS    *dst;
    573     int	    n;
    574     int	    shift;
    575 
    576     dstLine = (BITS *) dstBits;
    577     dstLine += x & ~3;
    578     dstStride *= (sizeof (FbBits) / sizeof (BITS));
    579     shift = x & 3;
    580     lshift = 4 - shift;
    581     while (height--)
    582     {
    583 	bits = *stipple++;
    584 	dst = (BITS *) dstLine;
    585 	n = lshift;
    586 	while (bits)
    587 	{
    588 	    switch (FbStipMoveLsb (FbLeftStipBits (bits, n), 4, n)) {
    589 	    case 0:
    590 		break;
    591 	    case 1:
    592 		WRITE1(dst,0,fg);
    593 		break;
    594 	    case 2:
    595 		WRITE1(dst,1,fg);
    596 		break;
    597 	    case 3:
    598 		WRITE2(dst,0,fg);
    599 		break;
    600 	    case 4:
    601 		WRITE1(dst,2,fg);
    602 		break;
    603 	    case 5:
    604 		WRITE1(dst,0,fg);
    605 		WRITE1(dst,2,fg);
    606 		break;
    607 	    case 6:
    608 		WRITE1(dst,1,fg);
    609 		WRITE1(dst,2,fg);
    610 		break;
    611 	    case 7:
    612 		WRITE2(dst,0,fg);
    613 		WRITE1(dst,2,fg);
    614 		break;
    615 	    case 8:
    616 		WRITE1(dst,3,fg);
    617 		break;
    618 	    case 9:
    619 		WRITE1(dst,0,fg);
    620 		WRITE1(dst,3,fg);
    621 		break;
    622 	    case 10:
    623 		WRITE1(dst,1,fg);
    624 		WRITE1(dst,3,fg);
    625 		break;
    626 	    case 11:
    627 		WRITE2(dst,0,fg);
    628 		WRITE1(dst,3,fg);
    629 		break;
    630 	    case 12:
    631 		WRITE2(dst,2,fg);
    632 		break;
    633 	    case 13:
    634 		WRITE1(dst,0,fg);
    635 		WRITE2(dst,2,fg);
    636 		break;
    637 	    case 14:
    638 		WRITE1(dst,1,fg);
    639 		WRITE2(dst,2,fg);
    640 		break;
    641 	    case 15:
    642 		WRITE4(dst,0,fg);
    643 		break;
    644 	    }
    645 	    bits = FbStipLeft (bits, n);
    646 	    n = 4;
    647 	    dst += 4;
    648 	}
    649 	dstLine += dstStride;
    650     }
    651 }
    652 #undef WRITE_ADDR1
    653 #undef WRITE_ADDR2
    654 #undef WRITE_ADDR4
    655 #undef WRITE1
    656 #undef WRITE2
    657 #undef WRITE4
    658 
    659 #endif
    660 
    661 #ifdef POLYLINE
    662 void
    663 POLYLINE (DrawablePtr	pDrawable,
    664 	  GCPtr		pGC,
    665 	  int		mode,
    666 	  int		npt,
    667 	  DDXPointPtr	ptsOrig)
    668 {
    669     INT32	    *pts = (INT32 *) ptsOrig;
    670     int		    xoff = pDrawable->x;
    671     int		    yoff = pDrawable->y;
    672     unsigned int    bias = miGetZeroLineBias(pDrawable->pScreen);
    673     BoxPtr	    pBox = RegionExtents(fbGetCompositeClip (pGC));
    674 
    675     FbBits	    *dst;
    676     int		    dstStride;
    677     int		    dstBpp;
    678     int		    dstXoff, dstYoff;
    679 
    680     UNIT	    *bits, *bitsBase;
    681     FbStride	    bitsStride;
    682     BITS	    xor = fbGetGCPrivate(pGC)->xor;
    683     BITS	    and = fbGetGCPrivate(pGC)->and;
    684     int		    dashoffset = 0;
    685 
    686     INT32	    ul, lr;
    687     INT32	    pt1, pt2;
    688 
    689     int		    e, e1, e3, len;
    690     int		    stepmajor, stepminor;
    691     int		    octant;
    692 
    693     if (mode == CoordModePrevious)
    694 	fbFixCoordModePrevious (npt, ptsOrig);
    695 
    696     fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
    697     bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
    698     bitsBase = ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff) * MUL;
    699     ul = coordToInt(pBox->x1 - xoff,     pBox->y1 - yoff);
    700     lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1);
    701 
    702     pt1 = *pts++;
    703     npt--;
    704     pt2 = *pts++;
    705     npt--;
    706     for (;;)
    707     {
    708 	if (isClipped (pt1, ul, lr) | isClipped (pt2, ul, lr))
    709 	{
    710 	    fbSegment (pDrawable, pGC,
    711 		       intToX(pt1) + xoff, intToY(pt1) + yoff,
    712 		       intToX(pt2) + xoff, intToY(pt2) + yoff,
    713 		       npt == 0 && pGC->capStyle != CapNotLast,
    714 		       &dashoffset);
    715 	    if (!npt) {
    716 		fbFinishAccess (pDrawable);
    717 		return;
    718 	    }
    719 	    pt1 = pt2;
    720 	    pt2 = *pts++;
    721 	    npt--;
    722 	}
    723 	else
    724 	{
    725 	    bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1) * MUL;
    726 	    for (;;)
    727 	    {
    728 		CalcLineDeltas (intToX(pt1), intToY(pt1),
    729 				intToX(pt2), intToY(pt2),
    730 				len, e1, stepmajor, stepminor, 1, bitsStride,
    731 				octant);
    732 		stepmajor *= MUL;
    733 		if (len < e1)
    734 		{
    735 		    e3 = len;
    736 		    len = e1;
    737 		    e1 = e3;
    738 
    739 		    e3 = stepminor;
    740 		    stepminor = stepmajor;
    741 		    stepmajor = e3;
    742 		    SetYMajorOctant(octant);
    743 		}
    744 		e = -len;
    745 		e1 <<= 1;
    746 		e3 = e << 1;
    747 		FIXUP_ERROR (e, octant, bias);
    748 		if (and == 0)
    749 		{
    750 		    while (len--)
    751 		    {
    752 			STORE(bits,xor);
    753 			bits += stepmajor;
    754 			e += e1;
    755 			if (e >= 0)
    756 			{
    757 			    bits += stepminor;
    758 			    e += e3;
    759 			}
    760 		    }
    761 		}
    762 		else
    763 		{
    764 		    while (len--)
    765 		    {
    766 			RROP(bits,and,xor);
    767 			bits += stepmajor;
    768 			e += e1;
    769 			if (e >= 0)
    770 			{
    771 			    bits += stepminor;
    772 			    e += e3;
    773 			}
    774 		    }
    775 		}
    776 		if (!npt)
    777 		{
    778 		    if (pGC->capStyle != CapNotLast &&
    779 			pt2 != *((INT32 *) ptsOrig))
    780 		    {
    781 			RROP(bits,and,xor);
    782 		    }
    783 		    fbFinishAccess (pDrawable);
    784 		    return;
    785 		}
    786 		pt1 = pt2;
    787 		pt2 = *pts++;
    788 		--npt;
    789 		if (isClipped (pt2, ul, lr))
    790 		    break;
    791     	    }
    792 	}
    793     }
    794 
    795     fbFinishAccess (pDrawable);
    796 }
    797 #endif
    798 
    799 #ifdef POLYSEGMENT
    800 void
    801 POLYSEGMENT (DrawablePtr    pDrawable,
    802 	     GCPtr	    pGC,
    803 	     int	    nseg,
    804 	     xSegment	    *pseg)
    805 {
    806     INT32	    *pts = (INT32 *) pseg;
    807     int		    xoff = pDrawable->x;
    808     int		    yoff = pDrawable->y;
    809     unsigned int    bias = miGetZeroLineBias(pDrawable->pScreen);
    810     BoxPtr	    pBox = RegionExtents(fbGetCompositeClip (pGC));
    811 
    812     FbBits	    *dst;
    813     int		    dstStride;
    814     int		    dstBpp;
    815     int		    dstXoff, dstYoff;
    816 
    817     UNIT	    *bits, *bitsBase;
    818     FbStride	    bitsStride;
    819     FbBits	    xorBits = fbGetGCPrivate(pGC)->xor;
    820     FbBits	    andBits = fbGetGCPrivate(pGC)->and;
    821     BITS	    xor = xorBits;
    822     BITS	    and = andBits;
    823     int		    dashoffset = 0;
    824 
    825     INT32	    ul, lr;
    826     INT32	    pt1, pt2;
    827 
    828     int		    e, e1, e3, len;
    829     int		    stepmajor, stepminor;
    830     int		    octant;
    831     Bool	    capNotLast;
    832 
    833     fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
    834     bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
    835     bitsBase = ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff) * MUL;
    836     ul = coordToInt(pBox->x1 - xoff,     pBox->y1 - yoff);
    837     lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1);
    838 
    839     capNotLast = pGC->capStyle == CapNotLast;
    840 
    841     while (nseg--)
    842     {
    843 	pt1 = *pts++;
    844 	pt2 = *pts++;
    845 	if (isClipped (pt1, ul, lr) | isClipped (pt2, ul, lr))
    846 	{
    847 	    fbSegment (pDrawable, pGC,
    848 		       intToX(pt1) + xoff, intToY(pt1) + yoff,
    849 		       intToX(pt2) + xoff, intToY(pt2) + yoff,
    850 		       !capNotLast, &dashoffset);
    851 	}
    852 	else
    853 	{
    854 	    CalcLineDeltas (intToX(pt1), intToY(pt1),
    855 			    intToX(pt2), intToY(pt2),
    856 			    len, e1, stepmajor, stepminor, 1, bitsStride,
    857 			    octant);
    858 	    if (e1 == 0 && len > 3
    859 #if MUL != 1
    860 		&& FbCheck24Pix(and) && FbCheck24Pix(xor)
    861 #endif
    862 		)
    863 	    {
    864 		int	x1, x2;
    865 		FbBits	*dstLine;
    866 		int	dstX, width;
    867 		FbBits	startmask, endmask;
    868 		int	nmiddle;
    869 
    870 		if (stepmajor < 0)
    871 		{
    872 		    x1 = intToX(pt2);
    873 		    x2 = intToX(pt1) + 1;
    874 		    if (capNotLast)
    875 			x1++;
    876 		}
    877 		else
    878 		{
    879 		    x1 = intToX(pt1);
    880 		    x2 = intToX(pt2);
    881 		    if (!capNotLast)
    882 			x2++;
    883 		}
    884 		dstX = (x1 + xoff + dstXoff) * (sizeof (UNIT) * 8 * MUL);
    885 		width = (x2 - x1) * (sizeof (UNIT) * 8 * MUL);
    886 
    887 		dstLine = dst + (intToY(pt1) + yoff + dstYoff) * dstStride;
    888 		dstLine += dstX >> FB_SHIFT;
    889 		dstX &= FB_MASK;
    890 		FbMaskBits (dstX, width, startmask, nmiddle, endmask);
    891 		if (startmask)
    892 		{
    893 		    WRITE(dstLine, FbDoMaskRRop (READ(dstLine), andBits, xorBits, startmask));
    894 		    dstLine++;
    895 		}
    896 		if (!andBits)
    897 		    while (nmiddle--)
    898 			WRITE(dstLine++, xorBits);
    899 		else
    900 		    while (nmiddle--)
    901 		    {
    902 			WRITE(dstLine, FbDoRRop (READ(dstLine), andBits, xorBits));
    903 			dstLine++;
    904 		    }
    905 		if (endmask)
    906 		    WRITE(dstLine, FbDoMaskRRop (READ(dstLine), andBits, xorBits, endmask));
    907 	    }
    908 	    else
    909 	    {
    910 		stepmajor *= MUL;
    911 		bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1) * MUL;
    912 		if (len < e1)
    913 		{
    914 		    e3 = len;
    915 		    len = e1;
    916 		    e1 = e3;
    917 
    918 		    e3 = stepminor;
    919 		    stepminor = stepmajor;
    920 		    stepmajor = e3;
    921 		    SetYMajorOctant(octant);
    922 		}
    923 		e = -len;
    924 		e1 <<= 1;
    925 		e3 = e << 1;
    926 		FIXUP_ERROR (e, octant, bias);
    927 		if (!capNotLast)
    928 		    len++;
    929 		if (and == 0)
    930 		{
    931 		    while (len--)
    932 		    {
    933 			STORE(bits,xor);
    934 			bits += stepmajor;
    935 			e += e1;
    936 			if (e >= 0)
    937 			{
    938 			    bits += stepminor;
    939 			    e += e3;
    940 			}
    941 		    }
    942 		}
    943 		else
    944 		{
    945 		    while (len--)
    946 		    {
    947 			RROP(bits,and,xor);
    948 			bits += stepmajor;
    949 			e += e1;
    950 			if (e >= 0)
    951 			{
    952 			    bits += stepminor;
    953 			    e += e3;
    954 			}
    955 		    }
    956 		}
    957 	    }
    958 	}
    959     }
    960 
    961     fbFinishAccess (pDrawable);
    962 }
    963 #endif
    964 
    965 #undef MUL
    966 #undef STORE
    967 #undef RROP
    968 #undef UNIT
    969 #undef USE_SOLID
    970 
    971 #undef isClipped
    972