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