Edit

IABSD.fr/xenocara/xserver/fb/fbbits.h

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2006-11-26 18:13:41
    Hash : 889b8606
    Message : Importing xserver from X.Org 7.2RC2

  • xserver/fb/fbbits.h
  • /*
     * $XFree86$
     *
     * Copyright © 1998 Keith Packard
     *
     * Permission to use, copy, modify, distribute, and sell this software and its
     * documentation for any purpose is hereby granted without fee, provided that
     * the above copyright notice appear in all copies and that both that
     * copyright notice and this permission notice appear in supporting
     * documentation, and that the name of Keith Packard not be used in
     * advertising or publicity pertaining to distribution of the software without
     * specific, written prior permission.  Keith Packard makes no
     * representations about the suitability of this software for any purpose.  It
     * is provided "as is" without express or implied warranty.
     *
     * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     * PERFORMANCE OF THIS SOFTWARE.
     */
    
    /*
     * This file defines functions for drawing some primitives using
     * underlying datatypes instead of masks
     */
    
    #define isClipped(c,ul,lr)  ((((c) - (ul)) | ((lr) - (c))) & 0x80008000)
    
    #ifdef HAVE_DIX_CONFIG_H
    #include <dix-config.h>
    #endif
    
    #ifdef BITSMUL
    #define MUL BITSMUL
    #else
    #define MUL 1
    #endif
    
    #ifdef BITSSTORE
    #define STORE(b,x)  BITSSTORE(b,x)
    #else
    #define STORE(b,x)  (*(b) = (x))
    #endif
    
    #ifdef BITSRROP
    #define RROP(b,a,x)	BITSRROP(b,a,x)
    #else
    #define RROP(b,a,x)	(*(b) = FbDoRRop (*(b), (a), (x)))
    #endif
    
    #ifdef BITSUNIT
    #define UNIT BITSUNIT
    #define USE_SOLID
    #else
    #define UNIT BITS
    #endif
    
    /*
     * Define the following before including this file:
     *
     *  BRESSOLID	name of function for drawing a solid segment
     *  BRESDASH	name of function for drawing a dashed segment
     *  DOTS	name of function for drawing dots
     *  ARC		name of function for drawing a solid arc
     *  BITS	type of underlying unit
     */
    
    #ifdef BRESSOLID
    void
    BRESSOLID (DrawablePtr	pDrawable,
    	   GCPtr	pGC,
    	   int		dashOffset,
    	   int		signdx,
    	   int		signdy,
    	   int		axis,
    	   int		x1,
    	   int		y1,
    	   int		e,
    	   int		e1,
    	   int		e3,
    	   int		len)
    {
        FbBits	*dst;
        FbStride	dstStride;
        int		dstBpp;
        int		dstXoff, dstYoff;
        FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
        UNIT	*bits;
        FbStride	bitsStride;
        FbStride	majorStep, minorStep;
        BITS	xor = (BITS) pPriv->xor;
        
        fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
        bits = ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff) * MUL;
        bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
        if (signdy < 0)
    	bitsStride = -bitsStride;
        if (axis == X_AXIS)
        {
    	majorStep = signdx * MUL;
    	minorStep = bitsStride;
        }
        else
        {
    	majorStep = bitsStride;
    	minorStep = signdx * MUL;
        }
        while (len--)
        {
    	STORE(bits,xor);
    	bits += majorStep;
    	e += e1;
    	if (e >= 0)
    	{
    	    bits += minorStep;
    	    e += e3;
    	}
        }
    }
    #endif
    
    #ifdef BRESDASH
    void
    BRESDASH (DrawablePtr	pDrawable,
    	  GCPtr		pGC,
    	  int		dashOffset,
    	  int		signdx,
    	  int		signdy,
    	  int		axis,
    	  int		x1,
    	  int		y1,
    	  int		e,
    	  int		e1,
    	  int		e3,
    	  int		len)
    {
        FbBits	*dst;
        FbStride	dstStride;
        int		dstBpp;
        int		dstXoff, dstYoff;
        FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
        UNIT	*bits;
        FbStride	bitsStride;
        FbStride	majorStep, minorStep;
        BITS	xorfg, xorbg;
        FbDashDeclare;
        int		dashlen;
        Bool	even;
        Bool	doOdd;
        
        fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
        doOdd = pGC->lineStyle == LineDoubleDash;
        xorfg = (BITS) pPriv->xor;
        xorbg = (BITS) pPriv->bgxor;
        
        FbDashInit (pGC, pPriv, dashOffset, dashlen, even);
        
        bits = ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff) * MUL;
        bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
        if (signdy < 0)
    	bitsStride = -bitsStride;
        if (axis == X_AXIS)
        {
    	majorStep = signdx * MUL;
    	minorStep = bitsStride;
        }
        else
        {
    	majorStep = bitsStride;
    	minorStep = signdx * MUL;
        }
        if (dashlen >= len)
    	dashlen = len;
        if (doOdd)
        {
    	if (!even)
    	    goto doubleOdd;
    	for (;;)
    	{
    	    len -= dashlen;
    	    while (dashlen--)
    	    {
    		STORE(bits,xorfg);
    		bits += majorStep;
    		if ((e += e1) >= 0)
    		{
    		    e += e3;
    		    bits += minorStep;
    		}
    	    }
    	    if (!len)
    		break;
    	    
    	    FbDashNextEven(dashlen);
    	    
    	    if (dashlen >= len)
    		dashlen = len;
    doubleOdd:
    	    len -= dashlen;
    	    while (dashlen--)
    	    {
    		STORE(bits,xorbg);
    		bits += majorStep;
    		if ((e += e1) >= 0)
    		{
    		    e += e3;
    		    bits += minorStep;
    		}
    	    }
    	    if (!len)
    		break;
    	    
    	    FbDashNextOdd(dashlen);
    	    
    	    if (dashlen >= len)
    		dashlen = len;
    	}
        }
        else
        {
    	if (!even)
    	    goto onOffOdd;
    	for (;;)
    	{
    	    len -= dashlen;
    	    while (dashlen--)
    	    {
    		STORE(bits,xorfg);
    		bits += majorStep;
    		if ((e += e1) >= 0)
    		{
    		    e += e3;
    		    bits += minorStep;
    		}
    	    }
    	    if (!len)
    		break;
    
    	    FbDashNextEven (dashlen);
    	    
    	    if (dashlen >= len)
    		dashlen = len;
    onOffOdd:
    	    len -= dashlen;
    	    while (dashlen--)
    	    {
    		bits += majorStep;
    		if ((e += e1) >= 0)
    		{
    		    e += e3;
    		    bits += minorStep;
    		}
    	    }
    	    if (!len)
    		break;
    	    
    	    FbDashNextOdd (dashlen);
    	    
    	    if (dashlen >= len)
    		dashlen = len;
    	}
        }
    }
    #endif
    
    #ifdef DOTS
    void
    DOTS (FbBits	    *dst,
          FbStride	    dstStride,
          int	    dstBpp,
          BoxPtr	    pBox,
          xPoint	    *ptsOrig,
          int	    npt,
          int	    xorg,
          int	    yorg,
          int	    xoff,
          int	    yoff,
          FbBits	    and,
          FbBits	    xor)
    {
        INT32    	*pts = (INT32 *) ptsOrig;
        UNIT	*bits = (UNIT *) dst;
        UNIT	*point;
        BITS	bxor = (BITS) xor;
        BITS	band = (BITS) and;
        FbStride	bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
        INT32    	ul, lr;
        INT32    	pt;
    
        ul = coordToInt(pBox->x1 - xorg,     pBox->y1 - yorg);
        lr = coordToInt(pBox->x2 - xorg - 1, pBox->y2 - yorg - 1);
    
        bits += bitsStride * (yorg + yoff) + (xorg + xoff) * MUL;
        
        if (and == 0)
        {
    	while (npt--)
    	{
    	    pt = *pts++;
    	    if (!isClipped(pt,ul,lr))
    	    {
    		point = bits + intToY(pt) * bitsStride + intToX(pt) * MUL;
    		STORE(point,bxor);
    	    }
    	}
        }
        else
        {
    	while (npt--)
    	{
    	    pt = *pts++;
    	    if (!isClipped(pt,ul,lr))
    	    {
    		point = bits + intToY(pt) * bitsStride + intToX(pt) * MUL;
    		RROP(point,band,bxor);
    	    }
    	}
        }
    }
    #endif
    
    #ifdef ARC
    
    #define ARCCOPY(d)  STORE(d,xorBits)
    #define ARCRROP(d)  RROP(d,andBits,xorBits)
    
    void
    ARC (FbBits	*dst,
         FbStride	dstStride,
         int	dstBpp,
         xArc	*arc,
         int	drawX,
         int	drawY,
         FbBits	and,
         FbBits	xor)
    {
        UNIT	    *bits;
        FbStride	    bitsStride;
        miZeroArcRec    info;
        Bool	    do360;
        int		    x;
        UNIT	    *yorgp, *yorgop;
        BITS	    andBits, xorBits;
        int		    yoffset, dyoffset;
        int		    y, a, b, d, mask;
        int		    k1, k3, dx, dy;
        
        bits = (UNIT *) dst;
        bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
        andBits = (BITS) and;
        xorBits = (BITS) xor;
        do360 = miZeroArcSetup(arc, &info, TRUE);
        yorgp = bits + ((info.yorg + drawY) * bitsStride);
        yorgop = bits + ((info.yorgo + drawY) * bitsStride);
        info.xorg = (info.xorg + drawX) * MUL;
        info.xorgo = (info.xorgo + drawX) * MUL;
        MIARCSETUP();
        yoffset = y ? bitsStride : 0;
        dyoffset = 0;
        mask = info.initialMask;
        
        if (!(arc->width & 1))
        {
    	if (andBits == 0)
    	{
    	    if (mask & 2)
    		ARCCOPY(yorgp + info.xorgo);
    	    if (mask & 8)
    		ARCCOPY(yorgop + info.xorgo);
    	}
    	else
    	{
    	    if (mask & 2)
    		ARCRROP(yorgp + info.xorgo);
    	    if (mask & 8)
    		ARCRROP(yorgop + info.xorgo);
    	}
        }
        if (!info.end.x || !info.end.y)
        {
    	mask = info.end.mask;
    	info.end = info.altend;
        }
        if (do360 && (arc->width == arc->height) && !(arc->width & 1))
        {
    	int xoffset = bitsStride;
    	UNIT *yorghb = yorgp + (info.h * bitsStride) + info.xorg;
    	UNIT *yorgohb = yorghb - info.h * MUL;
    
    	yorgp += info.xorg;
    	yorgop += info.xorg;
    	yorghb += info.h * MUL;
    	while (1)
    	{
    	    if (andBits == 0)
    	    {
    		ARCCOPY(yorgp + yoffset + x * MUL);
    		ARCCOPY(yorgp + yoffset - x * MUL);
    		ARCCOPY(yorgop - yoffset - x * MUL);
    		ARCCOPY(yorgop - yoffset + x * MUL);
    	    }
    	    else
    	    {
    		ARCRROP(yorgp + yoffset + x * MUL);
    		ARCRROP(yorgp + yoffset - x * MUL);
    		ARCRROP(yorgop - yoffset - x * MUL);
    		ARCRROP(yorgop - yoffset + x * MUL);
    	    }
    	    if (a < 0)
    		break;
    	    if (andBits == 0)
    	    {
    		ARCCOPY(yorghb - xoffset - y * MUL);
    		ARCCOPY(yorgohb - xoffset + y * MUL);
    		ARCCOPY(yorgohb + xoffset + y * MUL);
    		ARCCOPY(yorghb + xoffset - y * MUL);
    	    }
    	    else
    	    {
    		ARCRROP(yorghb - xoffset - y * MUL);
    		ARCRROP(yorgohb - xoffset + y * MUL);
    		ARCRROP(yorgohb + xoffset + y * MUL);
    		ARCRROP(yorghb + xoffset - y * MUL);
    	    }
    	    xoffset += bitsStride;
    	    MIARCCIRCLESTEP(yoffset += bitsStride;);
    	}
    	yorgp -= info.xorg;
    	yorgop -= info.xorg;
    	x = info.w;
    	yoffset = info.h * bitsStride;
        }
        else if (do360)
        {
    	while (y < info.h || x < info.w)
    	{
    	    MIARCOCTANTSHIFT(dyoffset = bitsStride;);
    	    if (andBits == 0)
    	    {
    		ARCCOPY(yorgp + yoffset + info.xorg + x * MUL);
    		ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL);
    		ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL);
    		ARCCOPY(yorgop - yoffset + info.xorg + x * MUL);
    	    }
    	    else
    	    {
    		ARCRROP(yorgp + yoffset + info.xorg + x * MUL);
    		ARCRROP(yorgp + yoffset + info.xorgo - x * MUL);
    		ARCRROP(yorgop - yoffset + info.xorgo - x * MUL);
    		ARCRROP(yorgop - yoffset + info.xorg + x * MUL);
    	    }
    	    MIARCSTEP(yoffset += dyoffset;, yoffset += bitsStride;);
    	}
        }
        else
        {
    	while (y < info.h || x < info.w)
    	{
    	    MIARCOCTANTSHIFT(dyoffset = bitsStride;);
    	    if ((x == info.start.x) || (y == info.start.y))
    	    {
    		mask = info.start.mask;
    		info.start = info.altstart;
    	    }
    	    if (andBits == 0)
    	    {
    		if (mask & 1)
    		    ARCCOPY(yorgp + yoffset + info.xorg + x * MUL);
    		if (mask & 2)
    		    ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL);
    		if (mask & 4)
    		    ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL);
    		if (mask & 8)
    		    ARCCOPY(yorgop - yoffset + info.xorg + x * MUL);
    	    }
    	    else
    	    {
    		if (mask & 1)
    		    ARCRROP(yorgp + yoffset + info.xorg + x * MUL);
    		if (mask & 2)
    		    ARCRROP(yorgp + yoffset + info.xorgo - x * MUL);
    		if (mask & 4)
    		    ARCRROP(yorgop - yoffset + info.xorgo - x * MUL);
    		if (mask & 8)
    		    ARCRROP(yorgop - yoffset + info.xorg + x * MUL);
    	    }
    	    if ((x == info.end.x) || (y == info.end.y))
    	    {
    		mask = info.end.mask;
    		info.end = info.altend;
    	    }
    	    MIARCSTEP(yoffset += dyoffset;, yoffset += bitsStride;);
    	}
        }
        if ((x == info.start.x) || (y == info.start.y))
    	mask = info.start.mask;
        if (andBits == 0)
        {
    	if (mask & 1)
    	    ARCCOPY(yorgp + yoffset + info.xorg + x * MUL);
    	if (mask & 4)
    	    ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL);
    	if (arc->height & 1)
    	{
    	    if (mask & 2)
    		ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL);
    	    if (mask & 8)
    		ARCCOPY(yorgop - yoffset + info.xorg + x * MUL);
    	}
        }
        else
        {
    	if (mask & 1)
    	    ARCRROP(yorgp + yoffset + info.xorg + x * MUL);
    	if (mask & 4)
    	    ARCRROP(yorgop - yoffset + info.xorgo - x * MUL);
    	if (arc->height & 1)
    	{
    	    if (mask & 2)
    		ARCRROP(yorgp + yoffset + info.xorgo - x * MUL);
    	    if (mask & 8)
    		ARCRROP(yorgop - yoffset + info.xorg + x * MUL);
    	}
        }
    }
    #undef ARCCOPY
    #undef ARCRROP
    #endif
    
    #ifdef GLYPH
    #if BITMAP_BIT_ORDER == LSBFirst
    # define WRITE_ADDR1(n)	    (n)
    # define WRITE_ADDR2(n)	    (n)
    # define WRITE_ADDR4(n)	    (n)
    #else
    # define WRITE_ADDR1(n)	    ((n) ^ 3)
    # define WRITE_ADDR2(n)	    ((n) ^ 2)
    # define WRITE_ADDR4(n)	    ((n))
    #endif
    
    #define WRITE1(d,n,fg)	    ((d)[WRITE_ADDR1(n)] = (BITS) (fg))
    
    #ifdef BITS2
    # define WRITE2(d,n,fg)	    (*((BITS2 *) &((d)[WRITE_ADDR2(n)])) = (BITS2) (fg))
    #else
    # define WRITE2(d,n,fg)	    WRITE1(d,(n)+1,WRITE1(d,n,fg))
    #endif
    
    #ifdef BITS4
    # define WRITE4(d,n,fg)	    (*((BITS4 *) &((d)[WRITE_ADDR4(n)])) = (BITS4) (fg))
    #else
    # define WRITE4(d,n,fg)	    WRITE2(d,(n)+2,WRITE2(d,n,fg))
    #endif
    
    void
    GLYPH (FbBits	*dstBits,
       FbStride	dstStride,
       int	dstBpp,
       FbStip	*stipple,
       FbBits	fg,
       int	x,
       int	height)
    {
        int	    lshift;
        FbStip  bits;
        BITS    *dstLine;
        BITS    *dst;
        int	    n;
        int	    shift;
    
        dstLine = (BITS *) dstBits;
        dstLine += x & ~3;
        dstStride *= (sizeof (FbBits) / sizeof (BITS));
        shift = x & 3;
        lshift = 4 - shift;
        while (height--)
        {
    	bits = *stipple++;
    	dst = (BITS *) dstLine;
    	n = lshift;
    	while (bits)
    	{
    	    switch (FbStipMoveLsb (FbLeftStipBits (bits, n), 4, n)) {
    	    case 0:
    		break;
    	    case 1:
    		WRITE1(dst,0,fg);
    		break;
    	    case 2:
    		WRITE1(dst,1,fg);
    		break;
    	    case 3:
    		WRITE2(dst,0,fg);
    		break;
    	    case 4:
    		WRITE1(dst,2,fg);
    		break;
    	    case 5:
    		WRITE1(dst,0,fg);
    		WRITE1(dst,2,fg);
    		break;
    	    case 6:
    		WRITE1(dst,1,fg);
    		WRITE1(dst,2,fg);
    		break;
    	    case 7:
    		WRITE2(dst,0,fg);
    		WRITE1(dst,2,fg);
    		break;
    	    case 8:
    		WRITE1(dst,3,fg);
    		break;
    	    case 9:
    		WRITE1(dst,0,fg);
    		WRITE1(dst,3,fg);
    		break;
    	    case 10:
    		WRITE1(dst,1,fg);
    		WRITE1(dst,3,fg);
    		break;
    	    case 11:
    		WRITE2(dst,0,fg);
    		WRITE1(dst,3,fg);
    		break;
    	    case 12:
    		WRITE2(dst,2,fg);
    		break;
    	    case 13:
    		WRITE1(dst,0,fg);
    		WRITE2(dst,2,fg);
    		break;
    	    case 14:
    		WRITE1(dst,1,fg);
    		WRITE2(dst,2,fg);
    		break;
    	    case 15:
    		WRITE4(dst,0,fg);
    		break;
    	    }
    	    bits = FbStipLeft (bits, n);
    	    n = 4;
    	    dst += 4;
    	}
    	dstLine += dstStride;
        }
    }
    #undef WRITE_ADDR1
    #undef WRITE_ADDR2
    #undef WRITE_ADDR4
    #undef WRITE1
    #undef WRITE2
    #undef WRITE4
    
    #endif
    
    #ifdef POLYLINE
    void
    POLYLINE (DrawablePtr	pDrawable,
    	  GCPtr		pGC,
    	  int		mode,
    	  int		npt,
    	  DDXPointPtr	ptsOrig)
    {
        INT32	    *pts = (INT32 *) ptsOrig;
        int		    xoff = pDrawable->x;
        int		    yoff = pDrawable->y;
        unsigned int    bias = miGetZeroLineBias(pDrawable->pScreen);
        BoxPtr	    pBox = REGION_EXTENTS (pDrawable->pScreen, fbGetCompositeClip (pGC));
        
        FbBits	    *dst;
        int		    dstStride;
        int		    dstBpp;
        int		    dstXoff, dstYoff;
        
        UNIT	    *bits, *bitsBase;
        FbStride	    bitsStride;
        BITS	    xor = fbGetGCPrivate(pGC)->xor;
        BITS	    and = fbGetGCPrivate(pGC)->and;
        int		    dashoffset = 0;
        
        INT32	    ul, lr;
        INT32	    pt1, pt2;
    
        int		    e, e1, e3, len;
        int		    stepmajor, stepminor;
        int		    octant;
    
        if (mode == CoordModePrevious)
    	fbFixCoordModePrevious (npt, ptsOrig);
        
        fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
        bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
        bitsBase = ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff) * MUL;
        ul = coordToInt(pBox->x1 - xoff,     pBox->y1 - yoff);
        lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1);
    
        pt1 = *pts++;
        npt--;
        pt2 = *pts++;
        npt--;
        for (;;)
        {
    	if (isClipped (pt1, ul, lr) | isClipped (pt2, ul, lr))
    	{
    	    fbSegment (pDrawable, pGC, 
    		       intToX(pt1) + xoff, intToY(pt1) + yoff,
    		       intToX(pt2) + xoff, intToY(pt2) + yoff,
    		       npt == 0 && pGC->capStyle != CapNotLast,
    		       &dashoffset);
    	    if (!npt)
    		return;
    	    pt1 = pt2;
    	    pt2 = *pts++;
    	    npt--;
    	}
    	else
    	{
    	    bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1) * MUL;
    	    for (;;)
    	    {
    		CalcLineDeltas (intToX(pt1), intToY(pt1),
    				intToX(pt2), intToY(pt2),
    				len, e1, stepmajor, stepminor, 1, bitsStride,
    				octant);
    		stepmajor *= MUL;
    		if (len < e1)
    		{
    		    e3 = len;
    		    len = e1;
    		    e1 = e3;
    
    		    e3 = stepminor;
    		    stepminor = stepmajor;
    		    stepmajor = e3;
    		    SetYMajorOctant(octant);
    		}
    		e = -len;
    		e1 <<= 1;
    		e3 = e << 1;
    		FIXUP_ERROR (e, octant, bias);
    		if (and == 0)
    		{
    		    while (len--)
    		    {
    			STORE(bits,xor);
    			bits += stepmajor;
    			e += e1;
    			if (e >= 0)
    			{
    			    bits += stepminor;
    			    e += e3;
    			}
    		    }
    		}
    		else
    		{
    		    while (len--)
    		    {
    			RROP(bits,and,xor);
    			bits += stepmajor;
    			e += e1;
    			if (e >= 0)
    			{
    			    bits += stepminor;
    			    e += e3;
    			}
    		    }
    		}
    		if (!npt)
    		{
    		    if (pGC->capStyle != CapNotLast && 
    			pt2 != *((INT32 *) ptsOrig))
    		    {
    			RROP(bits,and,xor);
    		    }
    		    return;
    		}
    		pt1 = pt2;
    		pt2 = *pts++;
    		--npt;
    		if (isClipped (pt2, ul, lr))
    		    break;
        	    }
    	}
        }
    }
    #endif
    
    #ifdef POLYSEGMENT
    void
    POLYSEGMENT (DrawablePtr    pDrawable,
    	     GCPtr	    pGC,
    	     int	    nseg,
    	     xSegment	    *pseg)
    {
        INT32	    *pts = (INT32 *) pseg;
        int		    xoff = pDrawable->x;
        int		    yoff = pDrawable->y;
        unsigned int    bias = miGetZeroLineBias(pDrawable->pScreen);
        BoxPtr	    pBox = REGION_EXTENTS (pDrawable->pScreen, fbGetCompositeClip (pGC));
        
        FbBits	    *dst;
        int		    dstStride;
        int		    dstBpp;
        int		    dstXoff, dstYoff;
        
        UNIT	    *bits, *bitsBase;
        FbStride	    bitsStride;
        FbBits	    xorBits = fbGetGCPrivate(pGC)->xor;
        FbBits	    andBits = fbGetGCPrivate(pGC)->and;
        BITS	    xor = xorBits;
        BITS	    and = andBits;
        int		    dashoffset = 0;
        
        INT32	    ul, lr;
        INT32	    pt1, pt2;
    
        int		    e, e1, e3, len;
        int		    stepmajor, stepminor;
        int		    octant;
        Bool	    capNotLast;
    
        fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
        bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT));
        bitsBase = ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff) * MUL;
        ul = coordToInt(pBox->x1 - xoff,     pBox->y1 - yoff);
        lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1);
    
        capNotLast = pGC->capStyle == CapNotLast;
        
        while (nseg--)
        {
    	pt1 = *pts++;
    	pt2 = *pts++;
    	if (isClipped (pt1, ul, lr) | isClipped (pt2, ul, lr))
    	{
    	    fbSegment (pDrawable, pGC, 
    		       intToX(pt1) + xoff, intToY(pt1) + yoff,
    		       intToX(pt2) + xoff, intToY(pt2) + yoff,
    		       !capNotLast, &dashoffset);
    	}
    	else
    	{
    	    CalcLineDeltas (intToX(pt1), intToY(pt1),
    			    intToX(pt2), intToY(pt2),
    			    len, e1, stepmajor, stepminor, 1, bitsStride,
    			    octant);
    	    if (e1 == 0 && len > 3
    #if MUL != 1
    		&& FbCheck24Pix(and) && FbCheck24Pix(xor)
    #endif
    		)
    	    {
    		int	x1, x2;
    		FbBits	*dstLine;
    		int	dstX, width;
    		FbBits	startmask, endmask;
    		int	nmiddle;
    		
    		if (stepmajor < 0)
    		{
    		    x1 = intToX(pt2);
    		    x2 = intToX(pt1) + 1;
    		    if (capNotLast)
    			x1++;
    		}
    		else
    		{
    		    x1 = intToX(pt1);
    		    x2 = intToX(pt2);
    		    if (!capNotLast)
    			x2++;
    		}
    		dstX = (x1 + xoff + dstXoff) * (sizeof (UNIT) * 8 * MUL);
    		width = (x2 - x1) * (sizeof (UNIT) * 8 * MUL);
    		
    		dstLine = dst + (intToY(pt1) + yoff + dstYoff) * dstStride;
    		dstLine += dstX >> FB_SHIFT;
    		dstX &= FB_MASK;
    		FbMaskBits (dstX, width, startmask, nmiddle, endmask);
    		if (startmask)
    		{
    		    *dstLine = FbDoMaskRRop (*dstLine, andBits, xorBits, startmask);
    		    dstLine++;
    		}
    		if (!andBits)
    		    while (nmiddle--)
    			*dstLine++ = xorBits;
    		else
    		    while (nmiddle--)
    		    {
    			*dstLine = FbDoRRop (*dstLine, andBits, xorBits);
    			dstLine++;
    		    }
    		if (endmask)
    		    *dstLine = FbDoMaskRRop (*dstLine, andBits, xorBits, endmask);
    	    }
    	    else
    	    {
    		stepmajor *= MUL;
    		bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1) * MUL;
    		if (len < e1)
    		{
    		    e3 = len;
    		    len = e1;
    		    e1 = e3;
        
    		    e3 = stepminor;
    		    stepminor = stepmajor;
    		    stepmajor = e3;
    		    SetYMajorOctant(octant);
    		}
    		e = -len;
    		e1 <<= 1;
    		e3 = e << 1;
    		FIXUP_ERROR (e, octant, bias);
    		if (!capNotLast)
    		    len++;
    		if (and == 0)
    		{
    		    while (len--)
    		    {
    			STORE(bits,xor);
    			bits += stepmajor;
    			e += e1;
    			if (e >= 0)
    			{
    			    bits += stepminor;
    			    e += e3;
    			}
    		    }
    		}
    		else
    		{
    		    while (len--)
    		    {
    			RROP(bits,and,xor);
    			bits += stepmajor;
    			e += e1;
    			if (e >= 0)
    			{
    			    bits += stepminor;
    			    e += e3;
    			}
    		    }
    		}
    	    }
    	}
        }
    }
    #endif
    
    #undef MUL
    #undef STORE
    #undef RROP
    #undef UNIT
    #undef USE_SOLID
    
    #undef isClipped