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