text: /*
   * 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)  WRITE((b), (x))
  #endif
  
  #ifdef BITSRROP
  #define RROP(b,a,x)	BITSRROP(b,a,x)
  #else
  #define RROP(b,a,x)	WRITE((b), FbDoRRop (READ(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;
  	}
      }
  
      fbFinishAccess (pDrawable);
  }
  #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;
  	}
      }
  
      fbFinishAccess (pDrawable);
  }
  #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)	    WRITE(d + WRITE_ADDR1(n), (BITS) (fg))
  
  #ifdef BITS2
  # define WRITE2(d,n,fg)	    WRITE((BITS2 *) &((d)[WRITE_ADDR2(n)]), (BITS2) (fg))
  #else
  # define WRITE2(d,n,fg)	    (WRITE1(d,n,fg), WRITE1(d,(n)+1,fg))
  #endif
  
  #ifdef BITS4
  # define WRITE4(d,n,fg)	    WRITE((BITS4 *) &((d)[WRITE_ADDR4(n)]), (BITS4) (fg))
  #else
  # define WRITE4(d,n,fg)	    (WRITE2(d,n,fg), WRITE2(d,(n)+2,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) {
  		fbFinishAccess (pDrawable);
  		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);
  		    }
  		    fbFinishAccess (pDrawable);
  		    return;
  		}
  		pt1 = pt2;
  		pt2 = *pts++;
  		--npt;
  		if (isClipped (pt2, ul, lr))
  		    break;
      	    }
  	}
      }
  
      fbFinishAccess (pDrawable);
  }
  #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)
  		{
  		    WRITE(dstLine, FbDoMaskRRop (READ(dstLine), andBits, xorBits, startmask));
  		    dstLine++;
  		}
  		if (!andBits)
  		    while (nmiddle--)
  			WRITE(dstLine++, xorBits);
  		else
  		    while (nmiddle--)
  		    {
  			WRITE(dstLine, FbDoRRop (READ(dstLine), andBits, xorBits));
  			dstLine++;
  		    }
  		if (endmask)
  		    WRITE(dstLine, FbDoMaskRRop (READ(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;
  			}
  		    }
  		}
  	    }
  	}
      }
  
      fbFinishAccess (pDrawable);
  }
  #endif
  
  #undef MUL
  #undef STORE
  #undef RROP
  #undef UNIT
  #undef USE_SOLID
  
  #undef isClipped
  