tga_line.c revision 7706df26
17706df26Smrg/* $XFree86: $ */
27706df26Smrg
37706df26Smrg/*
47706df26Smrg * Copyright 1999 by Matthew Grossman, Seattle, USA.
57706df26Smrg *
67706df26Smrg * Permission to use, copy, modify, distribute, and sell this software
77706df26Smrg * and its documentation for any purpose is hereby granted without
87706df26Smrg * fee, provided that the above copyright notice appear in all copies
97706df26Smrg * and that both that copyright notice and this permission notice
107706df26Smrg * appear in supporting documentation, and that the name of Matthew
117706df26Smrg * Grossman not be used in advertising or publicity pertaining to
127706df26Smrg * distribution of the software without specific, written prior
137706df26Smrg * permission.  Matthew Grossman makes no representations about the
147706df26Smrg * suitability of this software for any purpose.  It is provided "as
157706df26Smrg * is" without express or implied warranty.
167706df26Smrg *
177706df26Smrg * MATTHEW GROSSMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
187706df26Smrg * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
197706df26Smrg * FITNESS, IN NO EVENT SHALL MATTHEW GROSSMAN BE LIABLE FOR ANY
207706df26Smrg * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
217706df26Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
227706df26Smrg * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
237706df26Smrg * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
247706df26Smrg * SOFTWARE.
257706df26Smrg *
267706df26Smrg * Author:  Matthew Grossman, mattg@oz.net
277706df26Smrg *
287706df26Smrg */
297706df26Smrg
307706df26Smrg/* tga_line.c */
317706df26Smrg/* accelerated solid and dashed lines */
327706df26Smrg/* adapted from xaa/xaaLine.c */
337706df26Smrg
347706df26Smrg#ifdef HAVE_CONFIG_H
357706df26Smrg#include "config.h"
367706df26Smrg#endif
377706df26Smrg
387706df26Smrg#include <X11/X.h>
397706df26Smrg#include "misc.h"
407706df26Smrg#include "xf86.h"
417706df26Smrg#include "xf86_OSproc.h"
427706df26Smrg
437706df26Smrg#include "scrnintstr.h"
447706df26Smrg#include "pixmapstr.h"
457706df26Smrg#include "miline.h"
467706df26Smrg#include "xf86str.h"
477706df26Smrg#include "xaa.h"
487706df26Smrg#include "xaalocal.h"
497706df26Smrg
507706df26Smrg/*  #include "tga.h" */
517706df26Smrg#include "tga_regs.h"
527706df26Smrg
537706df26Smrg/* line functions */
547706df26Smrgextern void
557706df26SmrgTGASetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
567706df26Smrg		     unsigned int planemask);
577706df26Smrgextern void
587706df26SmrgTGASubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len,
597706df26Smrg			      int dir);
607706df26Smrgextern void
617706df26SmrgTGASubsequentSolidLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
627706df26Smrg		       int octant, int flags);
637706df26Smrgextern void
647706df26SmrgTGASetupForClippedLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
657706df26Smrg		       int octant);
667706df26Smrgextern void
677706df26SmrgTGASubsequentClippedSolidLine(ScrnInfoPtr pScrn, int x1, int y1, int len,
687706df26Smrg			      int err);
697706df26Smrg
707706df26Smrgextern void
717706df26SmrgTGASetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop,
727706df26Smrg		      unsigned int planemask, int length,
737706df26Smrg		      unsigned char *pattern);
747706df26Smrgextern void
757706df26SmrgTGASubsequentDashedLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
767706df26Smrg			int octant, int flags, int phase);
777706df26Smrgextern void
787706df26SmrgTGASubsequentClippedDashedLine(ScrnInfoPtr pScrn, int x1, int y1, int len,
797706df26Smrg			       int err, int phase);
807706df26Smrg
817706df26Smrg
827706df26Smrgextern void
837706df26SmrgTGASync(ScrnInfoPtr pScrn);
847706df26Smrg
857706df26Smrgvoid TGAPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
867706df26Smrg		    xSegment *pSeg);
877706df26Smrgvoid TGAPolyLines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
887706df26Smrg		  DDXPointPtr pptInit);
897706df26Smrgvoid TGAPolySegmentDashed(DrawablePtr pDrawable, GCPtr pGC, int	nseg,
907706df26Smrg			  xSegment *pSeg);
917706df26Smrgvoid TGAPolyLinesDashed(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
927706df26Smrg			DDXPointPtr pptInit);
937706df26Smrg
947706df26Smrg
957706df26Smrgvoid
967706df26Smrg#ifdef POLYSEGMENT
977706df26SmrgTGAPolySegment(
987706df26Smrg	       DrawablePtr	pDrawable,
997706df26Smrg	       GCPtr	pGC,
1007706df26Smrg	       int		nseg,
1017706df26Smrg	       xSegment	*pSeg
1027706df26Smrg#else
1037706df26Smrg	       TGAPolyLines(
1047706df26Smrg			    DrawablePtr pDrawable,
1057706df26Smrg			    GCPtr	pGC,
1067706df26Smrg			    int		mode,		/* Origin or Previous */
1077706df26Smrg			    int		npt,		/* number of points */
1087706df26Smrg			    DDXPointPtr pptInit
1097706df26Smrg#endif
1107706df26Smrg			    ){
1117706df26Smrg  XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
1127706df26Smrg  BoxPtr pboxInit = REGION_RECTS(pGC->pCompositeClip);
1137706df26Smrg  int nboxInit = REGION_NUM_RECTS(pGC->pCompositeClip);
1147706df26Smrg  unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
1157706df26Smrg  int xorg = pDrawable->x;
1167706df26Smrg  int yorg = pDrawable->y;
1177706df26Smrg  int nbox;
1187706df26Smrg  BoxPtr pbox;
1197706df26Smrg#ifndef POLYSEGMENT
1207706df26Smrg  DDXPointPtr ppt;
1217706df26Smrg#endif
1227706df26Smrg  int x1, x2, y1, y2, tmp, len;
1237706df26Smrg
1247706df26Smrg#ifdef POLYSEGMENT
1257706df26Smrg/*    ErrorF("TGAPolySegment called!\n"); */
1267706df26Smrg#else
1277706df26Smrg/*    ErrorF("TGAPolyLines called\n"); */
1287706df26Smrg#endif
1297706df26Smrg
1307706df26Smrg  if(!nboxInit)
1317706df26Smrg    return;
1327706df26Smrg  /****************/
1337706df26Smrg  /* TGA FUNCTION */
1347706df26Smrg  /****************/
1357706df26Smrg  TGASetupForSolidLine(infoRec->pScrn, pGC->fgPixel, pGC->alu,
1367706df26Smrg		       pGC->planemask);
1377706df26Smrg
1387706df26Smrg#ifdef POLYSEGMENT
1397706df26Smrg  while (nseg--)
1407706df26Smrg#else
1417706df26Smrg    ppt = pptInit;
1427706df26Smrg  x2 = ppt->x + xorg;
1437706df26Smrg  y2 = ppt->y + yorg;
1447706df26Smrg  while(--npt)
1457706df26Smrg#endif
1467706df26Smrg    {
1477706df26Smrg      nbox = nboxInit;
1487706df26Smrg      pbox = pboxInit;
1497706df26Smrg
1507706df26Smrg#ifdef POLYSEGMENT
1517706df26Smrg      x1 = pSeg->x1 + xorg;
1527706df26Smrg      y1 = pSeg->y1 + yorg;
1537706df26Smrg      x2 = pSeg->x2 + xorg;
1547706df26Smrg      y2 = pSeg->y2 + yorg;
1557706df26Smrg      pSeg++;
1567706df26Smrg#else
1577706df26Smrg      x1 = x2;
1587706df26Smrg      y1 = y2;
1597706df26Smrg      ++ppt;
1607706df26Smrg      if (mode == CoordModePrevious) {
1617706df26Smrg	xorg = x1;
1627706df26Smrg	yorg = y1;
1637706df26Smrg      }
1647706df26Smrg      x2 = ppt->x + xorg;
1657706df26Smrg      y2 = ppt->y + yorg;
1667706df26Smrg#endif
1677706df26Smrg
1687706df26Smrg      if (x1 == x2) { /* vertical line */
1697706df26Smrg	/* make the line go top to bottom of screen, keeping
1707706df26Smrg	   endpoint semantics
1717706df26Smrg	*/
1727706df26Smrg	if (y1 > y2) {
1737706df26Smrg	  tmp = y2;
1747706df26Smrg	  y2 = y1 + 1;
1757706df26Smrg	  y1 = tmp + 1;
1767706df26Smrg#ifdef POLYSEGMENT
1777706df26Smrg	  if (pGC->capStyle != CapNotLast) y1--;
1787706df26Smrg#endif
1797706df26Smrg	}
1807706df26Smrg#ifdef POLYSEGMENT
1817706df26Smrg	else if (pGC->capStyle != CapNotLast) y2++;
1827706df26Smrg#endif
1837706df26Smrg	/* get to first band that might contain part of line */
1847706df26Smrg	while(nbox && (pbox->y2 <= y1)) {
1857706df26Smrg	  pbox++;
1867706df26Smrg	  nbox--;
1877706df26Smrg	}
1887706df26Smrg
1897706df26Smrg	/* stop when lower edge of box is beyond end of line */
1907706df26Smrg	while(nbox && (y2 >= pbox->y1)) {
1917706df26Smrg	  if ((x1 >= pbox->x1) && (x1 < pbox->x2)) {
1927706df26Smrg	    tmp = max(y1, pbox->y1);
1937706df26Smrg	    len = min(y2, pbox->y2) - tmp;
1947706df26Smrg	    if (len)
1957706df26Smrg	      TGASubsequentSolidHorVertLine(infoRec->pScrn, x1, tmp,
1967706df26Smrg					    len, DEGREES_270);
1977706df26Smrg	  }
1987706df26Smrg	  nbox--;
1997706df26Smrg	  pbox++;
2007706df26Smrg	}
2017706df26Smrg#ifndef POLYSEGMENT
2027706df26Smrg	y2 = ppt->y + yorg;
2037706df26Smrg#endif
2047706df26Smrg      } else if (y1 == y2) { /* horizontal line */
2057706df26Smrg	/* force line from left to right, keeping endpoint semantics */
2067706df26Smrg	if (x1 > x2) {
2077706df26Smrg	  tmp = x2;
2087706df26Smrg	  x2 = x1 + 1;
2097706df26Smrg	  x1 = tmp + 1;
2107706df26Smrg#ifdef POLYSEGMENT
2117706df26Smrg	  if (pGC->capStyle != CapNotLast)  x1--;
2127706df26Smrg#endif
2137706df26Smrg	}
2147706df26Smrg#ifdef POLYSEGMENT
2157706df26Smrg	else if (pGC->capStyle != CapNotLast) x2++;
2167706df26Smrg#endif
2177706df26Smrg
2187706df26Smrg	/* find the correct band */
2197706df26Smrg	while(nbox && (pbox->y2 <= y1)) {
2207706df26Smrg	  pbox++;
2217706df26Smrg	  nbox--;
2227706df26Smrg	}
2237706df26Smrg
2247706df26Smrg	/* try to draw the line, if we haven't gone beyond it */
2257706df26Smrg	if (nbox && (pbox->y1 <= y1)) {
2267706df26Smrg	  int orig_y = pbox->y1;
2277706df26Smrg	  /* when we leave this band, we're done */
2287706df26Smrg	  while(nbox && (orig_y == pbox->y1)) {
2297706df26Smrg	    if (pbox->x2 <= x1) {
2307706df26Smrg	      /* skip boxes until one might contain start point */
2317706df26Smrg	      nbox--;
2327706df26Smrg	      pbox++;
2337706df26Smrg	      continue;
2347706df26Smrg	    }
2357706df26Smrg
2367706df26Smrg	    /* stop if left of box is beyond right of line */
2377706df26Smrg	    if (pbox->x1 >= x2) {
2387706df26Smrg	      nbox = 0;
2397706df26Smrg	      break;
2407706df26Smrg	    }
2417706df26Smrg
2427706df26Smrg	    tmp = max(x1, pbox->x1);
2437706df26Smrg	    len = min(x2, pbox->x2) - tmp;
2447706df26Smrg	    if (len)
2457706df26Smrg	      TGASubsequentSolidHorVertLine(infoRec->pScrn, tmp,
2467706df26Smrg					    y1, len, DEGREES_0);
2477706df26Smrg	    nbox--;
2487706df26Smrg	    pbox++;
2497706df26Smrg	  }
2507706df26Smrg	}
2517706df26Smrg#ifndef POLYSEGMENT
2527706df26Smrg	x2 = ppt->x + xorg;
2537706df26Smrg#endif
2547706df26Smrg      } else{ /* sloped line */
2557706df26Smrg	unsigned int oc1, oc2;
2567706df26Smrg	int dmin, dmaj, e, octant;
2577706df26Smrg
2587706df26Smrg
2597706df26Smrg	if((dmaj = x2 - x1) < 0) {
2607706df26Smrg	  dmaj = -dmaj;
2617706df26Smrg	  octant = XDECREASING;
2627706df26Smrg	} else octant = 0;
2637706df26Smrg
2647706df26Smrg	if((dmin = y2 - y1) < 0) {
2657706df26Smrg	  dmin = -dmin;
2667706df26Smrg	  octant |= YDECREASING;
2677706df26Smrg	}
2687706df26Smrg
2697706df26Smrg	if(dmin >= dmaj){
2707706df26Smrg	  tmp = dmin; dmin = dmaj; dmaj = tmp;
2717706df26Smrg	  octant |= YMAJOR;
2727706df26Smrg	}
2737706df26Smrg
2747706df26Smrg	e = -dmaj - ((bias >> octant) & 1);
2757706df26Smrg	len = dmaj;
2767706df26Smrg	dmin *= 2;
2777706df26Smrg	dmaj *= 2;
2787706df26Smrg
2797706df26Smrg
2807706df26Smrg	while(nbox--) {
2817706df26Smrg	  oc1 = oc2 = 0;
2827706df26Smrg	  OUTCODES(oc1, x1, y1, pbox);
2837706df26Smrg	  OUTCODES(oc2, x2, y2, pbox);
2847706df26Smrg	  if (!(oc1 | oc2)) {   /* unclipped */
2857706df26Smrg	    TGASubsequentSolidLine(infoRec->pScrn, x1, y1, x2, y2,
2867706df26Smrg				   octant,
2877706df26Smrg#ifdef POLYSEGMENT
2887706df26Smrg				   (pGC->capStyle != CapNotLast) ? 0 :
2897706df26Smrg#endif
2907706df26Smrg				   OMIT_LAST
2917706df26Smrg				   );
2927706df26Smrg	    break;
2937706df26Smrg	  } else if (oc1 & oc2) { /* completely clipped */
2947706df26Smrg	    pbox++;
2957706df26Smrg
2967706df26Smrg	  } else { /* partially clipped */
2977706df26Smrg	    int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
2987706df26Smrg	    int clip1 = 0, clip2 = 0;
2997706df26Smrg	    int err, adx, ady;
3007706df26Smrg
3017706df26Smrg	    if(octant & YMAJOR) {
3027706df26Smrg	      ady = dmaj /= 2;
3037706df26Smrg	      adx = dmin /= 2;
3047706df26Smrg	    } else {
3057706df26Smrg	      ady = dmin /= 2;
3067706df26Smrg	      adx = dmaj /= 2;
3077706df26Smrg	    }
3087706df26Smrg
3097706df26Smrg	    if (miZeroClipLine(pbox->x1, pbox->y1,
3107706df26Smrg			       pbox->x2 - 1, pbox->y2 - 1,
3117706df26Smrg			       &new_x1, &new_y1, &new_x2, &new_y2,
3127706df26Smrg			       adx, ady, &clip1, &clip2,
3137706df26Smrg			       octant, bias, oc1, oc2) == -1)
3147706df26Smrg	      {
3157706df26Smrg		pbox++;
3167706df26Smrg		continue;
3177706df26Smrg	      }
3187706df26Smrg
3197706df26Smrg	    if (octant & YMAJOR)
3207706df26Smrg	      len = abs(new_y2 - new_y1);
3217706df26Smrg	    else
3227706df26Smrg	      len = abs(new_x2 - new_x1);
3237706df26Smrg#ifdef POLYSEGMENT
3247706df26Smrg	    if (clip2 != 0 || pGC->capStyle != CapNotLast)
3257706df26Smrg	      len++;
3267706df26Smrg#else
3277706df26Smrg	    len += (clip2 != 0);
3287706df26Smrg#endif
3297706df26Smrg	    if (len) { /* we have a real line */
3307706df26Smrg	      int abserr, clipdx, clipdy;
3317706df26Smrg
3327706df26Smrg	      /* unwind bresenham error term to first point */
3337706df26Smrg	      if (clip1) {
3347706df26Smrg		clipdx = abs(new_x1 - x1);
3357706df26Smrg		clipdy = abs(new_y1 - y1);
3367706df26Smrg
3377706df26Smrg		if (octant & YMAJOR)
3387706df26Smrg		  err = e + clipdy*dmin - clipdx*dmaj;
3397706df26Smrg		else
3407706df26Smrg		  err = e + clipdx*dmin - clipdy*dmaj;
3417706df26Smrg	      } else
3427706df26Smrg		err = e;
3437706df26Smrg
3447706df26Smrg#define range infoRec->SolidBresenhamLineErrorTermBits
3457706df26Smrg	      abserr = abs(err);
3467706df26Smrg	      while((abserr & range) ||
3477706df26Smrg		    (dmaj & range) ||
3487706df26Smrg		    (dmin & range)) {
3497706df26Smrg		dmin /= 2;
3507706df26Smrg		dmaj /= 2;
3517706df26Smrg		abserr /= 2;
3527706df26Smrg		err /= 2;
3537706df26Smrg	      }
3547706df26Smrg	      TGASetupForClippedLine(infoRec->pScrn, x1, y1, x2,
3557706df26Smrg				     y2, octant);
3567706df26Smrg	      TGASubsequentClippedSolidLine(infoRec->pScrn,
3577706df26Smrg					    new_x1, new_y1, len,
3587706df26Smrg					    err);
3597706df26Smrg
3607706df26Smrg
3617706df26Smrg	    }
3627706df26Smrg	    pbox++;
3637706df26Smrg	  }
3647706df26Smrg	} /* while (nbox--) */
3657706df26Smrg      } /* sloped line */
3667706df26Smrg    } /* while (nline--) */
3677706df26Smrg
3687706df26Smrg#ifndef POLYSEGMENT
3697706df26Smrg  /* paint the last point if the end style isn't CapNotLast.
3707706df26Smrg       (Assume that a projecting, butt, or round cap that is one
3717706df26Smrg        pixel wide is the same as the single pixel of the endpoint.)
3727706df26Smrg    */
3737706df26Smrg
3747706df26Smrg  if ((pGC->capStyle != CapNotLast) &&
3757706df26Smrg      ((ppt->x + xorg != pptInit->x + pDrawable->x) ||
3767706df26Smrg       (ppt->y + yorg != pptInit->y + pDrawable->y) ||
3777706df26Smrg       (ppt == pptInit + 1)))
3787706df26Smrg    {
3797706df26Smrg      nbox = nboxInit;
3807706df26Smrg      pbox = pboxInit;
3817706df26Smrg      while (nbox--)
3827706df26Smrg	{
3837706df26Smrg	  if ((x2 >= pbox->x1) && (y2 >= pbox->y1) &&
3847706df26Smrg	      (x2 <  pbox->x2) && (y2 <  pbox->y2))
3857706df26Smrg	    {
3867706df26Smrg	      TGASubsequentSolidHorVertLine(infoRec->pScrn, x2, y2, 1,
3877706df26Smrg					    DEGREES_0);
3887706df26Smrg	      break;
3897706df26Smrg	    }
3907706df26Smrg	  else
3917706df26Smrg	    pbox++;
3927706df26Smrg	}
3937706df26Smrg    }
3947706df26Smrg#endif
3957706df26Smrg
3967706df26Smrg  TGASync(infoRec->pScrn);
3977706df26Smrg  return;
3987706df26Smrg}
3997706df26Smrg
4007706df26Smrg#undef range
4017706df26Smrg
4027706df26Smrg  void
4037706df26Smrg#ifdef POLYSEGMENT
4047706df26Smrg  TGAPolySegmentDashed(
4057706df26Smrg		       DrawablePtr	pDrawable,
4067706df26Smrg		       GCPtr	pGC,
4077706df26Smrg		       int		nseg,
4087706df26Smrg		       xSegment	*pSeg
4097706df26Smrg#else
4107706df26Smrg		       TGAPolyLinesDashed(
4117706df26Smrg					  DrawablePtr pDrawable,
4127706df26Smrg					  GCPtr	pGC,
4137706df26Smrg					  int		mode,		/* Origin or Previous */
4147706df26Smrg					  int		npt,		/* number of points */
4157706df26Smrg					  DDXPointPtr pptInit
4167706df26Smrg#endif
4177706df26Smrg					  ){
4187706df26Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
4197706df26Smrg    XAAGCPtr   pGCPriv = (XAAGCPtr) (pGC)->devPrivates[XAAGetGCIndex()].ptr;
4207706df26Smrg    BoxPtr pboxInit = REGION_RECTS(pGC->pCompositeClip);
4217706df26Smrg    int nboxInit = REGION_NUM_RECTS(pGC->pCompositeClip);
4227706df26Smrg    unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
4237706df26Smrg    int xorg = pDrawable->x;
4247706df26Smrg    int yorg = pDrawable->y;
4257706df26Smrg    int nbox;
4267706df26Smrg    BoxPtr pbox;
4277706df26Smrg#ifndef POLYSEGMENT
4287706df26Smrg    DDXPointPtr ppt;
4297706df26Smrg#endif
4307706df26Smrg    unsigned int oc1, oc2;
4317706df26Smrg    int dmin, dmaj, e, octant;
4327706df26Smrg    int x1, x2, y1, y2, tmp, len, offset;
4337706df26Smrg    int PatternLength, PatternOffset;
4347706df26Smrg
4357706df26Smrg#ifdef POLYSEGMENT
4367706df26Smrg/*      ErrorF("TGAPolySegmentDashed called\n"); */
4377706df26Smrg#else
4387706df26Smrg/*      ErrorF("TGAPolyLinesDashed called\n"); */
4397706df26Smrg#endif
4407706df26Smrg
4417706df26Smrg    if(!nboxInit)
4427706df26Smrg      return;
4437706df26Smrg
4447706df26Smrg    PatternLength = pGCPriv->DashLength;
4457706df26Smrg    PatternOffset = pGC->dashOffset % PatternLength;
4467706df26Smrg
4477706df26Smrg    TGASetupForDashedLine(infoRec->pScrn, pGC->fgPixel,
4487706df26Smrg			  (pGC->lineStyle == LineDoubleDash) ? pGC->bgPixel : -1,
4497706df26Smrg			  pGC->alu, pGC->planemask, PatternLength, pGCPriv->DashPattern);
4507706df26Smrg
4517706df26Smrg
4527706df26Smrg#ifdef POLYSEGMENT
4537706df26Smrg    while (nseg--)
4547706df26Smrg#else
4557706df26Smrg      ppt = pptInit;
4567706df26Smrg    x2 = ppt->x + xorg;
4577706df26Smrg    y2 = ppt->y + yorg;
4587706df26Smrg    while(--npt)
4597706df26Smrg#endif
4607706df26Smrg      {
4617706df26Smrg	nbox = nboxInit;
4627706df26Smrg	pbox = pboxInit;
4637706df26Smrg
4647706df26Smrg#ifdef POLYSEGMENT
4657706df26Smrg	x1 = pSeg->x1 + xorg;
4667706df26Smrg	y1 = pSeg->y1 + yorg;
4677706df26Smrg	x2 = pSeg->x2 + xorg;
4687706df26Smrg	y2 = pSeg->y2 + yorg;
4697706df26Smrg	pSeg++;
4707706df26Smrg#else
4717706df26Smrg	x1 = x2;
4727706df26Smrg	y1 = y2;
4737706df26Smrg	++ppt;
4747706df26Smrg	if (mode == CoordModePrevious) {
4757706df26Smrg	  xorg = x1;
4767706df26Smrg	  yorg = y1;
4777706df26Smrg	}
4787706df26Smrg	x2 = ppt->x + xorg;
4797706df26Smrg	y2 = ppt->y + yorg;
4807706df26Smrg#endif
4817706df26Smrg
4827706df26Smrg
4837706df26Smrg
4847706df26Smrg	if((dmaj = x2 - x1) < 0) {
4857706df26Smrg	  dmaj = -dmaj;
4867706df26Smrg	  octant = XDECREASING;
4877706df26Smrg	} else octant = 0;
4887706df26Smrg
4897706df26Smrg	if((dmin = y2 - y1) < 0) {
4907706df26Smrg	  dmin = -dmin;
4917706df26Smrg	  octant |= YDECREASING;
4927706df26Smrg	}
4937706df26Smrg
4947706df26Smrg	if(dmin >= dmaj){
4957706df26Smrg	  tmp = dmin; dmin = dmaj; dmaj = tmp;
4967706df26Smrg	  octant |= YMAJOR;
4977706df26Smrg	}
4987706df26Smrg
4997706df26Smrg	e = -dmaj - ((bias >> octant) & 1);
5007706df26Smrg	len = dmaj;
5017706df26Smrg	dmin <<= 1;
5027706df26Smrg	dmaj <<= 1;
5037706df26Smrg
5047706df26Smrg
5057706df26Smrg	while(nbox--) {
5067706df26Smrg	  oc1 = oc2 = 0;
5077706df26Smrg	  OUTCODES(oc1, x1, y1, pbox);
5087706df26Smrg	  OUTCODES(oc2, x2, y2, pbox);
5097706df26Smrg	  if (!(oc1 | oc2)) {   /* unclipped */
5107706df26Smrg	    TGASubsequentDashedLine(infoRec->pScrn, x1, y1, x2, y2,
5117706df26Smrg				    octant,
5127706df26Smrg#ifdef POLYSEGMENT
5137706df26Smrg				    (pGC->capStyle != CapNotLast) ? 0 :
5147706df26Smrg#endif
5157706df26Smrg				    OMIT_LAST, PatternOffset);
5167706df26Smrg	    break;
5177706df26Smrg	  } else if (oc1 & oc2) { /* completely clipped */
5187706df26Smrg	    pbox++;
5197706df26Smrg	  } else { /* partially clipped */
5207706df26Smrg	    int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
5217706df26Smrg	    int clip1 = 0, clip2 = 0;
5227706df26Smrg	    int err, adx, ady;
5237706df26Smrg
5247706df26Smrg	    if(octant & YMAJOR) {
5257706df26Smrg	      ady = dmaj >> 1;
5267706df26Smrg	      adx = dmin >> 1;
5277706df26Smrg	    } else {
5287706df26Smrg	      ady = dmin >> 1;
5297706df26Smrg	      adx = dmaj >> 1;
5307706df26Smrg	    }
5317706df26Smrg
5327706df26Smrg	    if (miZeroClipLine(pbox->x1, pbox->y1,
5337706df26Smrg			       pbox->x2 - 1, pbox->y2 - 1,
5347706df26Smrg			       &new_x1, &new_y1, &new_x2, &new_y2,
5357706df26Smrg			       adx, ady, &clip1, &clip2,
5367706df26Smrg			       octant, bias, oc1, oc2) == -1)
5377706df26Smrg	      {
5387706df26Smrg		pbox++;
5397706df26Smrg		continue;
5407706df26Smrg	      }
5417706df26Smrg
5427706df26Smrg	    if (octant & YMAJOR)
5437706df26Smrg	      len = abs(new_y2 - new_y1);
5447706df26Smrg	    else
5457706df26Smrg	      len = abs(new_x2 - new_x1);
5467706df26Smrg#ifdef POLYSEGMENT
5477706df26Smrg	    if (clip2 != 0 || pGC->capStyle != CapNotLast)
5487706df26Smrg	      len++;
5497706df26Smrg#else
5507706df26Smrg	    len += (clip2 != 0);
5517706df26Smrg#endif
5527706df26Smrg	    if (len) {
5537706df26Smrg	      int abserr, clipdx, clipdy;
5547706df26Smrg	      /* unwind bresenham error term to first point */
5557706df26Smrg	      if (clip1) {
5567706df26Smrg		clipdx = abs(new_x1 - x1);
5577706df26Smrg		clipdy = abs(new_y1 - y1);
5587706df26Smrg
5597706df26Smrg		if (octant & YMAJOR)
5607706df26Smrg		  err = e + clipdy*dmin - clipdx*dmaj;
5617706df26Smrg		else
5627706df26Smrg		  err = e + clipdx*dmin - clipdy*dmaj;
5637706df26Smrg	      } else
5647706df26Smrg		err = e;
5657706df26Smrg
5667706df26Smrg#define range infoRec->DashedBresenhamLineErrorTermBits
5677706df26Smrg	      abserr = abs(err);
5687706df26Smrg	      while((abserr & range) ||
5697706df26Smrg		    (dmaj & range) ||
5707706df26Smrg		    (dmin & range)) {
5717706df26Smrg		dmin >>= 1;
5727706df26Smrg		dmaj >>= 1;
5737706df26Smrg		abserr >>= 1;
5747706df26Smrg		err /= 2;
5757706df26Smrg	      }
5767706df26Smrg
5777706df26Smrg	      if(octant & YMAJOR)
5787706df26Smrg		offset = abs(new_y1 - y1);
5797706df26Smrg	      else
5807706df26Smrg		offset = abs(new_x1 - x1);
5817706df26Smrg
5827706df26Smrg	      offset += PatternOffset;
5837706df26Smrg	      offset %= PatternLength;
5847706df26Smrg
5857706df26Smrg	      TGASetupForClippedLine(infoRec->pScrn, x1, x2, y1, y2,
5867706df26Smrg				     octant);
5877706df26Smrg	      TGASubsequentClippedDashedLine(infoRec->pScrn, new_x1,
5887706df26Smrg					     new_y1, len, err,
5897706df26Smrg					     PatternOffset);
5907706df26Smrg	    }
5917706df26Smrg	    pbox++;
5927706df26Smrg	  }
5937706df26Smrg	} /* while (nbox--) */
5947706df26Smrg#ifndef POLYSEGMENT
5957706df26Smrg	len = abs(y2 - y1);
5967706df26Smrg	tmp = abs(x2 - x1);
5977706df26Smrg	PatternOffset += (len > tmp) ? len : tmp;
5987706df26Smrg	PatternOffset %= PatternLength;
5997706df26Smrg#endif
6007706df26Smrg      } /* while (nline--) */
6017706df26Smrg
6027706df26Smrg#ifndef POLYSEGMENT
6037706df26Smrg    /* paint the last point if the end style isn't CapNotLast.
6047706df26Smrg       (Assume that a projecting, butt, or round cap that is one
6057706df26Smrg        pixel wide is the same as the single pixel of the endpoint.)
6067706df26Smrg    */
6077706df26Smrg
6087706df26Smrg    if ((pGC->capStyle != CapNotLast) &&
6097706df26Smrg	((ppt->x + xorg != pptInit->x + pDrawable->x) ||
6107706df26Smrg	 (ppt->y + yorg != pptInit->y + pDrawable->y) ||
6117706df26Smrg	 (ppt == pptInit + 1)))
6127706df26Smrg      {
6137706df26Smrg	nbox = nboxInit;
6147706df26Smrg	pbox = pboxInit;
6157706df26Smrg	while (nbox--) {
6167706df26Smrg	  if ((x2 >= pbox->x1) && (y2 >= pbox->y1) &&
6177706df26Smrg	      (x2 <  pbox->x2) && (y2 <  pbox->y2))
6187706df26Smrg	    {
6197706df26Smrg	      TGASubsequentDashedLine(infoRec->pScrn, x2, y2, x2, y2, 0, 0,
6207706df26Smrg				      PatternOffset);
6217706df26Smrg	      break;
6227706df26Smrg	    } else
6237706df26Smrg		pbox++;
6247706df26Smrg	}
6257706df26Smrg    }
6267706df26Smrg#endif
6277706df26Smrg
6287706df26Smrg    TGASync(infoRec->pScrn);
6297706df26Smrg    return;
6307706df26Smrg}
6317706df26Smrg
6327706df26Smrg
633