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