735 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			735 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * 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.
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #include "fb.h"
 | |
| #include "miline.h"
 | |
| 
 | |
| #define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \
 | |
| 					((dir < 0) ? FbStipLeft(mask,bpp) : \
 | |
| 					 FbStipRight(mask,bpp)))
 | |
| 
 | |
| void
 | |
| fbBresSolid (DrawablePtr    pDrawable,
 | |
| 	     GCPtr	    pGC,
 | |
| 	     int	    dashOffset,
 | |
| 	     int	    signdx,
 | |
| 	     int	    signdy,
 | |
| 	     int	    axis,
 | |
| 	     int	    x1,
 | |
| 	     int	    y1,
 | |
| 	     int	    e,
 | |
| 	     int	    e1,
 | |
| 	     int	    e3,
 | |
| 	     int	    len)
 | |
| {
 | |
|     FbStip	*dst;
 | |
|     FbStride	dstStride;
 | |
|     int		dstBpp;
 | |
|     int		dstXoff, dstYoff;
 | |
|     FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
 | |
|     FbStip	and = (FbStip) pPriv->and;
 | |
|     FbStip	xor = (FbStip) pPriv->xor;
 | |
|     FbStip	mask, mask0;
 | |
|     FbStip	bits;
 | |
|     
 | |
|     fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
 | |
|     dst += ((y1 + dstYoff) * dstStride);
 | |
|     x1 = (x1 + dstXoff) * dstBpp;
 | |
|     dst += x1 >> FB_STIP_SHIFT;
 | |
|     x1 &= FB_STIP_MASK;
 | |
|     mask0 = FbStipMask(0, dstBpp);
 | |
|     mask = FbStipRight (mask0, x1);
 | |
|     if (signdx < 0)
 | |
| 	mask0 = FbStipRight (mask0, FB_STIP_UNIT - dstBpp);
 | |
|     if (signdy < 0)
 | |
| 	dstStride = -dstStride;
 | |
|     if (axis == X_AXIS)
 | |
|     {
 | |
| 	bits = 0;
 | |
| 	while (len--)
 | |
| 	{
 | |
| 	    bits |= mask;
 | |
| 	    mask = fbBresShiftMask(mask,signdx,dstBpp);
 | |
| 	    if (!mask)
 | |
| 	    {
 | |
| 		WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits));
 | |
| 		bits = 0;
 | |
| 		dst += signdx;
 | |
| 		mask = mask0;
 | |
| 	    }
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits));
 | |
| 		bits = 0;
 | |
| 		dst += dstStride;
 | |
| 		e += e3;
 | |
| 	    }
 | |
| 	}
 | |
| 	if (bits)
 | |
| 	    WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits));
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	while (len--)
 | |
| 	{
 | |
| 	    WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, mask));
 | |
| 	    dst += dstStride;
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		e += e3;
 | |
| 		mask = fbBresShiftMask(mask,signdx,dstBpp);
 | |
| 		if (!mask)
 | |
| 		{
 | |
| 		    dst += signdx;
 | |
| 		    mask = mask0;
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     fbFinishAccess (pDrawable);
 | |
| }
 | |
| 
 | |
| void
 | |
| fbBresDash (DrawablePtr	pDrawable,
 | |
| 	    GCPtr	pGC,
 | |
| 	    int		dashOffset,
 | |
| 	    int		signdx,
 | |
| 	    int		signdy,
 | |
| 	    int		axis,
 | |
| 	    int		x1,
 | |
| 	    int		y1,
 | |
| 	    int		e,
 | |
| 	    int		e1,
 | |
| 	    int		e3,
 | |
| 	    int		len)
 | |
| {
 | |
|     FbStip	*dst;
 | |
|     FbStride	dstStride;
 | |
|     int		dstBpp;
 | |
|     int		dstXoff, dstYoff;
 | |
|     FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
 | |
|     FbStip	and = (FbStip) pPriv->and;
 | |
|     FbStip	xor = (FbStip) pPriv->xor;
 | |
|     FbStip	bgand = (FbStip) pPriv->bgand;
 | |
|     FbStip	bgxor = (FbStip) pPriv->bgxor;
 | |
|     FbStip	mask, mask0;
 | |
|     FbDashDeclare;
 | |
|     int		dashlen;
 | |
|     Bool	even;
 | |
|     Bool	doOdd;
 | |
|     
 | |
|     fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
 | |
|     doOdd = pGC->lineStyle == LineDoubleDash;
 | |
| 
 | |
|     FbDashInit (pGC, pPriv, dashOffset, dashlen, even);
 | |
|     
 | |
|     dst += ((y1 + dstYoff) * dstStride);
 | |
|     x1 = (x1 + dstXoff) * dstBpp;
 | |
|     dst += x1 >> FB_STIP_SHIFT;
 | |
|     x1 &= FB_STIP_MASK;
 | |
|     mask0 = FbStipMask(0, dstBpp);
 | |
|     mask = FbStipRight (mask0, x1);
 | |
|     if (signdx < 0)
 | |
| 	mask0 = FbStipRight (mask0, FB_STIP_UNIT - dstBpp);
 | |
|     if (signdy < 0)
 | |
| 	dstStride = -dstStride;
 | |
|     while (len--)
 | |
|     {
 | |
| 	if (even)
 | |
| 	    WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, mask));
 | |
| 	else if (doOdd)
 | |
| 	    WRITE(dst, FbDoMaskRRop (READ(dst), bgand, bgxor, mask));
 | |
| 	if (axis == X_AXIS)
 | |
| 	{
 | |
| 	    mask = fbBresShiftMask(mask,signdx,dstBpp);
 | |
| 	    if (!mask)
 | |
| 	    {
 | |
| 		dst += signdx;
 | |
| 		mask = mask0;
 | |
| 	    }
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		dst += dstStride;
 | |
| 		e += e3;
 | |
| 	    }
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    dst += dstStride;
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		e += e3;
 | |
| 		mask = fbBresShiftMask(mask,signdx,dstBpp);
 | |
| 		if (!mask)
 | |
| 		{
 | |
| 		    dst += signdx;
 | |
| 		    mask = mask0;
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
| 	FbDashStep (dashlen, even);
 | |
|     }
 | |
| 
 | |
|     fbFinishAccess (pDrawable);
 | |
| }
 | |
| 
 | |
| void
 | |
| fbBresFill (DrawablePtr	pDrawable,
 | |
| 	    GCPtr	pGC,
 | |
| 	    int		dashOffset,
 | |
| 	    int		signdx,
 | |
| 	    int		signdy,
 | |
| 	    int		axis,
 | |
| 	    int		x1,
 | |
| 	    int		y1,
 | |
| 	    int		e,
 | |
| 	    int		e1,
 | |
| 	    int		e3,
 | |
| 	    int		len)
 | |
| {
 | |
|     while (len--)
 | |
|     {
 | |
| 	fbFill (pDrawable, pGC, x1, y1, 1, 1);
 | |
| 	if (axis == X_AXIS)
 | |
| 	{
 | |
| 	    x1 += signdx;
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		e += e3;
 | |
| 		y1 += signdy;
 | |
| 	    }
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    y1 += signdy;
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		e += e3;
 | |
| 		x1 += signdx;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| fbSetFg (DrawablePtr	pDrawable,
 | |
| 	 GCPtr		pGC,
 | |
| 	 Pixel		fg)
 | |
| {
 | |
|     if (fg != pGC->fgPixel)
 | |
|     {
 | |
| 	DoChangeGC (pGC, GCForeground, (XID *) &fg, FALSE);
 | |
| 	ValidateGC (pDrawable, pGC);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| fbBresFillDash (DrawablePtr pDrawable,
 | |
| 		GCPtr	    pGC,
 | |
| 		int	    dashOffset,
 | |
| 		int	    signdx,
 | |
| 		int	    signdy,
 | |
| 		int	    axis,
 | |
| 		int	    x1,
 | |
| 		int	    y1,
 | |
| 		int	    e,
 | |
| 		int	    e1,
 | |
| 		int	    e3,
 | |
| 		int	    len)
 | |
| {
 | |
|     FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
 | |
|     FbDashDeclare;
 | |
|     int		dashlen;
 | |
|     Bool	even;
 | |
|     Bool	doOdd;
 | |
|     Bool	doBg;
 | |
|     Pixel	fg, bg;
 | |
|     
 | |
|     fg = pGC->fgPixel;
 | |
|     bg = pGC->bgPixel;
 | |
|     
 | |
|     /* whether to fill the odd dashes */
 | |
|     doOdd = pGC->lineStyle == LineDoubleDash;
 | |
|     /* whether to switch fg to bg when filling odd dashes */
 | |
|     doBg = doOdd && (pGC->fillStyle == FillSolid || 
 | |
| 		     pGC->fillStyle == FillStippled);
 | |
|     
 | |
|     /* compute current dash position */
 | |
|     FbDashInit (pGC, pPriv, dashOffset, dashlen, even);
 | |
|     
 | |
|     while (len--)
 | |
|     {
 | |
| 	if (even || doOdd)
 | |
| 	{
 | |
| 	    if (doBg)
 | |
| 	    {
 | |
| 		if (even)
 | |
| 		    fbSetFg (pDrawable, pGC, fg);
 | |
| 		else
 | |
| 		    fbSetFg (pDrawable, pGC, bg);
 | |
| 	    }
 | |
| 	    fbFill (pDrawable, pGC, x1, y1, 1, 1);
 | |
| 	}
 | |
| 	if (axis == X_AXIS)
 | |
| 	{
 | |
| 	    x1 += signdx;
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		e += e3;
 | |
| 		y1 += signdy;
 | |
| 	    }
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    y1 += signdy;
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		e += e3;
 | |
| 		x1 += signdx;
 | |
| 	    }
 | |
| 	}
 | |
| 	FbDashStep (dashlen, even);
 | |
|     }
 | |
|     if (doBg)
 | |
| 	fbSetFg (pDrawable, pGC, fg);
 | |
| }
 | |
| 
 | |
| #ifdef FB_24BIT
 | |
| static void
 | |
| fbBresSolid24RRop (DrawablePtr  pDrawable,
 | |
| 		   GCPtr	pGC,
 | |
| 		   int		dashOffset,
 | |
| 		   int		signdx,
 | |
| 		   int		signdy,
 | |
| 		   int		axis,
 | |
| 		   int		x1,
 | |
| 		   int		y1,
 | |
| 		   int		e,
 | |
| 		   int		e1,
 | |
| 		   int		e3,
 | |
| 		   int		len)
 | |
| {
 | |
|     FbStip	*dst;
 | |
|     FbStride	dstStride;
 | |
|     int		dstBpp;
 | |
|     int		dstXoff, dstYoff;
 | |
|     FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
 | |
|     FbStip	and = pPriv->and;
 | |
|     FbStip	xor = pPriv->xor;
 | |
|     FbStip	leftMask, rightMask;
 | |
|     int		nl;
 | |
|     FbStip	*d;
 | |
|     int		x;
 | |
|     int		rot;
 | |
|     FbStip	andT, xorT;
 | |
|     
 | |
|     fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
 | |
|     dst += ((y1 + dstYoff) * dstStride);
 | |
|     x1 = (x1 + dstXoff) * 24;
 | |
|     if (signdy < 0)
 | |
| 	dstStride = -dstStride;
 | |
|     signdx *= 24;
 | |
|     while (len--)
 | |
|     {
 | |
| 	d = dst + (x1 >> FB_STIP_SHIFT);
 | |
| 	x = x1 & FB_STIP_MASK;
 | |
| 	rot = FbFirst24Rot (x);
 | |
| 	andT = FbRot24Stip(and,rot);
 | |
| 	xorT = FbRot24Stip(xor,rot);
 | |
| 	FbMaskStip (x, 24, leftMask, nl, rightMask);
 | |
| 	if (leftMask)
 | |
| 	{
 | |
| 	    WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, leftMask));
 | |
| 	    d++;
 | |
| 	    andT = FbNext24Stip (andT);
 | |
| 	    xorT = FbNext24Stip (xorT);
 | |
| 	}
 | |
| 	if (rightMask)
 | |
| 	    WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, rightMask));
 | |
| 	if (axis == X_AXIS)
 | |
| 	{
 | |
| 	    x1 += signdx;
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		e += e3;
 | |
| 		dst += dstStride;
 | |
| 	    }
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    dst += dstStride;
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		e += e3;
 | |
| 		x1 += signdx;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     fbFinishAccess (pDrawable);
 | |
| }
 | |
| 
 | |
| static void
 | |
| fbBresDash24RRop (DrawablePtr	pDrawable,
 | |
| 		  GCPtr		pGC,
 | |
| 		  int		dashOffset,
 | |
| 		  int		signdx,
 | |
| 		  int		signdy,
 | |
| 		  int		axis,
 | |
| 		  int		x1,
 | |
| 		  int		y1,
 | |
| 		  int		e,
 | |
| 		  int		e1,
 | |
| 		  int		e3,
 | |
| 		  int		len)
 | |
| {
 | |
|     FbStip	*dst;
 | |
|     FbStride	dstStride;
 | |
|     int		dstBpp;
 | |
|     int		dstXoff, dstYoff;
 | |
|     FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
 | |
|     FbStip	andT, xorT;
 | |
|     FbStip	fgand = pPriv->and;
 | |
|     FbStip	fgxor = pPriv->xor;
 | |
|     FbStip	bgand = pPriv->bgand;
 | |
|     FbStip	bgxor = pPriv->bgxor;
 | |
|     FbStip	leftMask, rightMask;
 | |
|     int		nl;
 | |
|     FbStip	*d;
 | |
|     int		x;
 | |
|     int		rot;
 | |
|     FbDashDeclare;
 | |
|     int		dashlen;
 | |
|     Bool	even;
 | |
|     Bool	doOdd;
 | |
|     
 | |
|     fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
 | |
|     doOdd = pGC->lineStyle == LineDoubleDash;
 | |
| 
 | |
|     /* compute current dash position */
 | |
|     FbDashInit(pGC, pPriv, dashOffset, dashlen, even);
 | |
|     
 | |
|     dst += ((y1 + dstYoff) * dstStride);
 | |
|     x1 = (x1 + dstXoff) * 24;
 | |
|     if (signdy < 0)
 | |
| 	dstStride = -dstStride;
 | |
|     signdx *= 24;
 | |
|     while (len--)
 | |
|     {
 | |
| 	if (even || doOdd)
 | |
| 	{
 | |
| 	    if (even)
 | |
| 	    {
 | |
| 		andT = fgand;
 | |
| 		xorT = fgxor;
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		andT = bgand;
 | |
| 		xorT = bgxor;
 | |
| 	    }
 | |
| 	    d = dst + (x1 >> FB_STIP_SHIFT);
 | |
| 	    x = x1 & FB_STIP_MASK;
 | |
| 	    rot = FbFirst24Rot (x);
 | |
| 	    andT = FbRot24Stip (andT, rot);
 | |
| 	    xorT = FbRot24Stip (xorT, rot);
 | |
| 	    FbMaskStip (x, 24, leftMask, nl, rightMask);
 | |
| 	    if (leftMask)
 | |
| 	    {
 | |
| 		WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, leftMask));
 | |
| 		d++;
 | |
| 		andT = FbNext24Stip (andT);
 | |
| 		xorT = FbNext24Stip (xorT);
 | |
| 	    }
 | |
| 	    if (rightMask)
 | |
| 		WRITE(d, FbDoMaskRRop (READ(d), andT, xorT, rightMask));
 | |
| 	}
 | |
| 	if (axis == X_AXIS)
 | |
| 	{
 | |
| 	    x1 += signdx;
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		e += e3;
 | |
| 		dst += dstStride;
 | |
| 	    }
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    dst += dstStride;
 | |
| 	    e += e1;
 | |
| 	    if (e >= 0)
 | |
| 	    {
 | |
| 		e += e3;
 | |
| 		x1 += signdx;
 | |
| 	    }
 | |
| 	}
 | |
| 	FbDashStep (dashlen, even);
 | |
|     }
 | |
| 
 | |
|     fbFinishAccess (pDrawable);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * For drivers that want to bail drawing some lines, this
 | |
|  * function takes care of selecting the appropriate rasterizer
 | |
|  * based on the contents of the specified GC.
 | |
|  */
 | |
| 
 | |
| FbBres *
 | |
| fbSelectBres (DrawablePtr   pDrawable,
 | |
| 	      GCPtr	    pGC)
 | |
| {
 | |
|     FbGCPrivPtr	pPriv = fbGetGCPrivate(pGC);
 | |
|     int		dstBpp = pDrawable->bitsPerPixel;
 | |
|     FbBres *	bres;
 | |
|     
 | |
|     if (pGC->lineStyle == LineSolid)
 | |
|     {
 | |
| 	bres = fbBresFill;
 | |
| 	if (pGC->fillStyle == FillSolid)
 | |
| 	{
 | |
| 	    bres = fbBresSolid;
 | |
| #ifdef FB_24BIT
 | |
| 	    if (dstBpp == 24)
 | |
| 		bres = fbBresSolid24RRop;
 | |
| #endif
 | |
| #ifndef FBNOPIXADDR
 | |
| 	    if (pPriv->and == 0)
 | |
| 	    {
 | |
| 		switch (dstBpp) {
 | |
| 		case 8:	bres = fbBresSolid8; break;
 | |
| 		case 16: bres = fbBresSolid16; break;
 | |
| #ifdef FB_24BIT
 | |
| 		case 24: bres = fbBresSolid24; break;
 | |
| #endif
 | |
| 		case 32: bres = fbBresSolid32; break;
 | |
| 		}
 | |
| 	    }
 | |
| #endif
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	bres = fbBresFillDash;
 | |
| 	if (pGC->fillStyle == FillSolid)
 | |
| 	{
 | |
| 	    bres = fbBresDash;
 | |
| #ifdef FB_24BIT
 | |
| 	    if (dstBpp == 24)
 | |
| 		bres = fbBresDash24RRop;
 | |
| #endif
 | |
| #ifndef FBNOPIXADDR
 | |
| 	    if (pPriv->and == 0 && 
 | |
| 		(pGC->lineStyle == LineOnOffDash || pPriv->bgand == 0))
 | |
| 	    {
 | |
| 		switch (dstBpp) {
 | |
| 		case 8:	bres = fbBresDash8; break;
 | |
| 		case 16: bres = fbBresDash16; break;
 | |
| #ifdef FB_24BIT
 | |
| 		case 24: bres = fbBresDash24; break;
 | |
| #endif
 | |
| 		case 32: bres = fbBresDash32; break;
 | |
| 		}
 | |
| 	    }
 | |
| #endif
 | |
| 	}
 | |
|     }
 | |
|     return bres;
 | |
| }
 | |
| 
 | |
| void
 | |
| fbBres (DrawablePtr	pDrawable,
 | |
| 	GCPtr		pGC,
 | |
| 	int		dashOffset,
 | |
| 	int		signdx,
 | |
| 	int		signdy,
 | |
| 	int		axis,
 | |
| 	int		x1,
 | |
| 	int		y1,
 | |
| 	int		e,
 | |
| 	int		e1,
 | |
| 	int		e3,
 | |
| 	int		len)
 | |
| {
 | |
|     (*fbSelectBres (pDrawable, pGC)) (pDrawable, pGC, dashOffset,
 | |
| 				      signdx, signdy, axis, x1, y1,
 | |
| 				      e, e1, e3, len);
 | |
| }
 | |
| 
 | |
| void
 | |
| fbSegment (DrawablePtr	pDrawable,
 | |
| 	   GCPtr	pGC,
 | |
| 	   int		x1,
 | |
| 	   int		y1,
 | |
| 	   int		x2,
 | |
| 	   int		y2,
 | |
| 	   Bool		drawLast,
 | |
| 	   int		*dashOffset)
 | |
| {
 | |
|     FbBres *	bres;
 | |
|     RegionPtr	pClip = fbGetCompositeClip(pGC);
 | |
|     BoxPtr	pBox;
 | |
|     int		nBox;
 | |
|     int		adx;		/* abs values of dx and dy */
 | |
|     int		ady;
 | |
|     int		signdx;		/* sign of dx and dy */
 | |
|     int		signdy;
 | |
|     int		e, e1, e2, e3;		/* bresenham error and increments */
 | |
|     int		len;			/* length of segment */
 | |
|     int		axis;			/* major axis */
 | |
|     int		octant;
 | |
|     int		dashoff;
 | |
|     int		doff;
 | |
|     unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
 | |
|     unsigned int oc1;	/* outcode of point 1 */
 | |
|     unsigned int oc2;	/* outcode of point 2 */
 | |
| 
 | |
|     nBox = REGION_NUM_RECTS (pClip);
 | |
|     pBox = REGION_RECTS (pClip);
 | |
|     
 | |
|     bres = fbSelectBres (pDrawable, pGC);
 | |
|     
 | |
|     CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy,
 | |
| 		   1, 1, octant);
 | |
| 
 | |
|     if (adx > ady)
 | |
|     {
 | |
| 	axis = X_AXIS;
 | |
| 	e1 = ady << 1;
 | |
| 	e2 = e1 - (adx << 1);
 | |
| 	e = e1 - adx;
 | |
| 	len = adx;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	axis = Y_AXIS;
 | |
| 	e1 = adx << 1;
 | |
| 	e2 = e1 - (ady << 1);
 | |
| 	e = e1 - ady;
 | |
| 	SetYMajorOctant(octant);
 | |
| 	len = ady;
 | |
|     }
 | |
| 
 | |
|     FIXUP_ERROR (e, octant, bias);
 | |
|     
 | |
|     /*
 | |
|      * Adjust error terms to compare against zero
 | |
|      */
 | |
|     e3 = e2 - e1;
 | |
|     e = e - e1;
 | |
|     
 | |
|     /* we have bresenham parameters and two points.
 | |
|        all we have to do now is clip and draw.
 | |
|     */
 | |
| 
 | |
|     if (drawLast)
 | |
| 	len++;
 | |
|     dashoff = *dashOffset;
 | |
|     *dashOffset = dashoff + len;
 | |
|     while(nBox--)
 | |
|     {
 | |
| 	oc1 = 0;
 | |
| 	oc2 = 0;
 | |
| 	OUTCODES(oc1, x1, y1, pBox);
 | |
| 	OUTCODES(oc2, x2, y2, pBox);
 | |
| 	if ((oc1 | oc2) == 0)
 | |
| 	{
 | |
| 	    (*bres) (pDrawable, pGC, dashoff,
 | |
| 		     signdx, signdy, axis, x1, y1,
 | |
| 		     e, e1, e3, len);
 | |
| 	    break;
 | |
| 	}
 | |
| 	else if (oc1 & oc2)
 | |
| 	{
 | |
| 	    pBox++;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
 | |
| 	    int clip1 = 0, clip2 = 0;
 | |
| 	    int clipdx, clipdy;
 | |
| 	    int err;
 | |
| 	    
 | |
| 	    if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2-1,
 | |
| 			       pBox->y2-1,
 | |
| 			       &new_x1, &new_y1, &new_x2, &new_y2,
 | |
| 			       adx, ady, &clip1, &clip2,
 | |
| 			       octant, bias, oc1, oc2) == -1)
 | |
| 	    {
 | |
| 		pBox++;
 | |
| 		continue;
 | |
| 	    }
 | |
| 
 | |
| 	    if (axis == X_AXIS)
 | |
| 		len = abs(new_x2 - new_x1);
 | |
| 	    else
 | |
| 		len = abs(new_y2 - new_y1);
 | |
| 	    if (clip2 != 0 || drawLast)
 | |
| 		len++;
 | |
| 	    if (len)
 | |
| 	    {
 | |
| 		/* unwind bresenham error term to first point */
 | |
| 		doff = dashoff;
 | |
| 		err = e;
 | |
| 		if (clip1)
 | |
| 		{
 | |
| 		    clipdx = abs(new_x1 - x1);
 | |
| 		    clipdy = abs(new_y1 - y1);
 | |
| 		    if (axis == X_AXIS)
 | |
| 		    {
 | |
| 			doff += clipdx;
 | |
| 			err  += e3 * clipdy + e1 * clipdx;
 | |
| 		    }
 | |
| 		    else
 | |
| 		    {
 | |
| 			doff += clipdy;
 | |
| 			err  += e3 * clipdx + e1 * clipdy;
 | |
| 		    }
 | |
| 		}
 | |
| 		(*bres) (pDrawable, pGC, doff,
 | |
| 			 signdx, signdy, axis, new_x1, new_y1,
 | |
| 			 err, e1, e3, len);
 | |
| 	    }
 | |
| 	    pBox++;
 | |
| 	}
 | |
|     } /* while (nBox--) */
 | |
| }
 |