1706f2543Smrg 2706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 3706f2543Smrg#include <xorg-config.h> 4706f2543Smrg#endif 5706f2543Smrg 6706f2543Smrg#include <stdlib.h> 7706f2543Smrg 8706f2543Smrg#include <X11/X.h> 9706f2543Smrg#include "misc.h" 10706f2543Smrg#include "xf86.h" 11706f2543Smrg#include "xf86_OSproc.h" 12706f2543Smrg 13706f2543Smrg#include "scrnintstr.h" 14706f2543Smrg#include "pixmapstr.h" 15706f2543Smrg#include "miline.h" 16706f2543Smrg#include "xf86str.h" 17706f2543Smrg#include "xaa.h" 18706f2543Smrg#include "xaalocal.h" 19706f2543Smrg 20706f2543Smrg 21706f2543Smrgvoid 22706f2543Smrg#ifdef POLYSEGMENT 23706f2543SmrgXAAPolySegment( 24706f2543Smrg DrawablePtr pDrawable, 25706f2543Smrg GCPtr pGC, 26706f2543Smrg int nseg, 27706f2543Smrg xSegment *pSeg 28706f2543Smrg#else 29706f2543SmrgXAAPolyLines( 30706f2543Smrg DrawablePtr pDrawable, 31706f2543Smrg GCPtr pGC, 32706f2543Smrg int mode, /* Origin or Previous */ 33706f2543Smrg int npt, /* number of points */ 34706f2543Smrg DDXPointPtr pptInit 35706f2543Smrg#endif 36706f2543Smrg){ 37706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 38706f2543Smrg BoxPtr pboxInit = RegionRects(pGC->pCompositeClip); 39706f2543Smrg int nboxInit = RegionNumRects(pGC->pCompositeClip); 40706f2543Smrg unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); 41706f2543Smrg int xorg = pDrawable->x; 42706f2543Smrg int yorg = pDrawable->y; 43706f2543Smrg int nbox; 44706f2543Smrg BoxPtr pbox; 45706f2543Smrg#ifndef POLYSEGMENT 46706f2543Smrg DDXPointPtr ppt; 47706f2543Smrg#endif 48706f2543Smrg int x1, x2, y1, y2, tmp, len; 49706f2543Smrg 50706f2543Smrg if(!nboxInit) 51706f2543Smrg return; 52706f2543Smrg 53706f2543Smrg if (infoRec->SolidLineFlags & LINE_LIMIT_COORDS) { 54706f2543Smrg int minValX = infoRec->SolidLineLimits.x1; 55706f2543Smrg int maxValX = infoRec->SolidLineLimits.x2; 56706f2543Smrg int minValY = infoRec->SolidLineLimits.y1; 57706f2543Smrg int maxValY = infoRec->SolidLineLimits.y2; 58706f2543Smrg#ifdef POLYSEGMENT 59706f2543Smrg int n = nseg; 60706f2543Smrg xSegment *s = pSeg; 61706f2543Smrg 62706f2543Smrg while (n--) 63706f2543Smrg#else 64706f2543Smrg int n = npt; 65706f2543Smrg int xorgtmp = xorg; 66706f2543Smrg int yorgtmp = yorg; 67706f2543Smrg 68706f2543Smrg ppt = pptInit; 69706f2543Smrg x2 = ppt->x + xorgtmp; 70706f2543Smrg y2 = ppt->y + yorgtmp; 71706f2543Smrg while (--n) 72706f2543Smrg#endif 73706f2543Smrg { 74706f2543Smrg#ifdef POLYSEGMENT 75706f2543Smrg x1 = s->x1 + xorg; 76706f2543Smrg y1 = s->y1 + yorg; 77706f2543Smrg x2 = s->x2 + xorg; 78706f2543Smrg y2 = s->y2 + yorg; 79706f2543Smrg s++; 80706f2543Smrg#else 81706f2543Smrg x1 = x2; 82706f2543Smrg y1 = y2; 83706f2543Smrg ++ppt; 84706f2543Smrg if (mode == CoordModePrevious) { 85706f2543Smrg xorgtmp = x1; 86706f2543Smrg yorgtmp = y1; 87706f2543Smrg } 88706f2543Smrg x2 = ppt->x + xorgtmp; 89706f2543Smrg y2 = ppt->y + yorgtmp; 90706f2543Smrg#endif 91706f2543Smrg if (x1 > maxValX || x1 < minValX || 92706f2543Smrg x2 > maxValX || x2 < minValX || 93706f2543Smrg y1 > maxValY || y1 < minValY || 94706f2543Smrg y2 > maxValY || y2 < minValY) { 95706f2543Smrg#ifdef POLYSEGMENT 96706f2543Smrg XAAFallbackOps.PolySegment(pDrawable, pGC, nseg, pSeg); 97706f2543Smrg#else 98706f2543Smrg XAAFallbackOps.Polylines(pDrawable, pGC, mode, npt, pptInit); 99706f2543Smrg#endif 100706f2543Smrg return; 101706f2543Smrg } 102706f2543Smrg } 103706f2543Smrg } 104706f2543Smrg 105706f2543Smrg (*infoRec->SetupForSolidLine)(infoRec->pScrn, pGC->fgPixel, 106706f2543Smrg pGC->alu, pGC->planemask); 107706f2543Smrg 108706f2543Smrg#ifdef POLYSEGMENT 109706f2543Smrg while (nseg--) 110706f2543Smrg#else 111706f2543Smrg ppt = pptInit; 112706f2543Smrg x2 = ppt->x + xorg; 113706f2543Smrg y2 = ppt->y + yorg; 114706f2543Smrg while(--npt) 115706f2543Smrg#endif 116706f2543Smrg { 117706f2543Smrg nbox = nboxInit; 118706f2543Smrg pbox = pboxInit; 119706f2543Smrg 120706f2543Smrg#ifdef POLYSEGMENT 121706f2543Smrg x1 = pSeg->x1 + xorg; 122706f2543Smrg y1 = pSeg->y1 + yorg; 123706f2543Smrg x2 = pSeg->x2 + xorg; 124706f2543Smrg y2 = pSeg->y2 + yorg; 125706f2543Smrg pSeg++; 126706f2543Smrg#else 127706f2543Smrg x1 = x2; 128706f2543Smrg y1 = y2; 129706f2543Smrg ++ppt; 130706f2543Smrg if (mode == CoordModePrevious) { 131706f2543Smrg xorg = x1; 132706f2543Smrg yorg = y1; 133706f2543Smrg } 134706f2543Smrg x2 = ppt->x + xorg; 135706f2543Smrg y2 = ppt->y + yorg; 136706f2543Smrg#endif 137706f2543Smrg 138706f2543Smrg if (x1 == x2) { /* vertical line */ 139706f2543Smrg /* make the line go top to bottom of screen, keeping 140706f2543Smrg endpoint semantics 141706f2543Smrg */ 142706f2543Smrg if (y1 > y2) { 143706f2543Smrg tmp = y2; 144706f2543Smrg y2 = y1 + 1; 145706f2543Smrg y1 = tmp + 1; 146706f2543Smrg#ifdef POLYSEGMENT 147706f2543Smrg if (pGC->capStyle != CapNotLast) y1--; 148706f2543Smrg#endif 149706f2543Smrg } 150706f2543Smrg#ifdef POLYSEGMENT 151706f2543Smrg else if (pGC->capStyle != CapNotLast) y2++; 152706f2543Smrg#endif 153706f2543Smrg /* get to first band that might contain part of line */ 154706f2543Smrg while(nbox && (pbox->y2 <= y1)) { 155706f2543Smrg pbox++; 156706f2543Smrg nbox--; 157706f2543Smrg } 158706f2543Smrg 159706f2543Smrg /* stop when lower edge of box is beyond end of line */ 160706f2543Smrg while(nbox && (y2 >= pbox->y1)) { 161706f2543Smrg if ((x1 >= pbox->x1) && (x1 < pbox->x2)) { 162706f2543Smrg tmp = max(y1, pbox->y1); 163706f2543Smrg len = min(y2, pbox->y2) - tmp; 164706f2543Smrg if (len) (*infoRec->SubsequentSolidHorVertLine)( 165706f2543Smrg infoRec->pScrn, x1, tmp, len, DEGREES_270); 166706f2543Smrg } 167706f2543Smrg nbox--; 168706f2543Smrg pbox++; 169706f2543Smrg } 170706f2543Smrg#ifndef POLYSEGMENT 171706f2543Smrg y2 = ppt->y + yorg; 172706f2543Smrg#endif 173706f2543Smrg } else if (y1 == y2) { /* horizontal line */ 174706f2543Smrg /* force line from left to right, keeping endpoint semantics */ 175706f2543Smrg if (x1 > x2) { 176706f2543Smrg tmp = x2; 177706f2543Smrg x2 = x1 + 1; 178706f2543Smrg x1 = tmp + 1; 179706f2543Smrg#ifdef POLYSEGMENT 180706f2543Smrg if (pGC->capStyle != CapNotLast) x1--; 181706f2543Smrg#endif 182706f2543Smrg } 183706f2543Smrg#ifdef POLYSEGMENT 184706f2543Smrg else if (pGC->capStyle != CapNotLast) x2++; 185706f2543Smrg#endif 186706f2543Smrg 187706f2543Smrg /* find the correct band */ 188706f2543Smrg while(nbox && (pbox->y2 <= y1)) { 189706f2543Smrg pbox++; 190706f2543Smrg nbox--; 191706f2543Smrg } 192706f2543Smrg 193706f2543Smrg /* try to draw the line, if we haven't gone beyond it */ 194706f2543Smrg if (nbox && (pbox->y1 <= y1)) { 195706f2543Smrg int orig_y = pbox->y1; 196706f2543Smrg /* when we leave this band, we're done */ 197706f2543Smrg while(nbox && (orig_y == pbox->y1)) { 198706f2543Smrg if (pbox->x2 <= x1) { 199706f2543Smrg /* skip boxes until one might contain start point */ 200706f2543Smrg nbox--; 201706f2543Smrg pbox++; 202706f2543Smrg continue; 203706f2543Smrg } 204706f2543Smrg 205706f2543Smrg /* stop if left of box is beyond right of line */ 206706f2543Smrg if (pbox->x1 >= x2) { 207706f2543Smrg nbox = 0; 208706f2543Smrg break; 209706f2543Smrg } 210706f2543Smrg 211706f2543Smrg tmp = max(x1, pbox->x1); 212706f2543Smrg len = min(x2, pbox->x2) - tmp; 213706f2543Smrg if (len) (*infoRec->SubsequentSolidHorVertLine)( 214706f2543Smrg infoRec->pScrn, tmp, y1, len, DEGREES_0); 215706f2543Smrg nbox--; 216706f2543Smrg pbox++; 217706f2543Smrg } 218706f2543Smrg } 219706f2543Smrg#ifndef POLYSEGMENT 220706f2543Smrg x2 = ppt->x + xorg; 221706f2543Smrg#endif 222706f2543Smrg } else{ /* sloped line */ 223706f2543Smrg unsigned int oc1, oc2; 224706f2543Smrg int dmin, dmaj, e, octant; 225706f2543Smrg 226706f2543Smrg if (infoRec->SubsequentSolidBresenhamLine) { 227706f2543Smrg if((dmaj = x2 - x1) < 0) { 228706f2543Smrg dmaj = -dmaj; 229706f2543Smrg octant = XDECREASING; 230706f2543Smrg } else octant = 0; 231706f2543Smrg 232706f2543Smrg if((dmin = y2 - y1) < 0) { 233706f2543Smrg dmin = -dmin; 234706f2543Smrg octant |= YDECREASING; 235706f2543Smrg } 236706f2543Smrg 237706f2543Smrg if(dmin >= dmaj){ 238706f2543Smrg tmp = dmin; dmin = dmaj; dmaj = tmp; 239706f2543Smrg octant |= YMAJOR; 240706f2543Smrg } 241706f2543Smrg 242706f2543Smrg e = -dmaj - ((bias >> octant) & 1); 243706f2543Smrg len = dmaj; 244706f2543Smrg dmin <<= 1; 245706f2543Smrg dmaj <<= 1; 246706f2543Smrg } else { /* Muffle compiler */ 247706f2543Smrg dmin = dmaj = e = octant = len = 0; 248706f2543Smrg } 249706f2543Smrg 250706f2543Smrg while(nbox--) { 251706f2543Smrg oc1 = oc2 = 0; 252706f2543Smrg OUTCODES(oc1, x1, y1, pbox); 253706f2543Smrg OUTCODES(oc2, x2, y2, pbox); 254706f2543Smrg if (!(oc1 | oc2)) { /* unclipped */ 255706f2543Smrg if(infoRec->SubsequentSolidTwoPointLine) { 256706f2543Smrg (*infoRec->SubsequentSolidTwoPointLine)( 257706f2543Smrg infoRec->pScrn, x1, y1, x2, y2, 258706f2543Smrg#ifdef POLYSEGMENT 259706f2543Smrg (pGC->capStyle != CapNotLast) ? 0 : 260706f2543Smrg#endif 261706f2543Smrg OMIT_LAST 262706f2543Smrg ); 263706f2543Smrg } else { 264706f2543Smrg (*infoRec->SubsequentSolidBresenhamLine)( 265706f2543Smrg infoRec->pScrn, x1, y1, dmaj, dmin, e, 266706f2543Smrg#ifdef POLYSEGMENT 267706f2543Smrg (pGC->capStyle != CapNotLast) ? (len+1) : 268706f2543Smrg#endif 269706f2543Smrg len, octant); 270706f2543Smrg } 271706f2543Smrg break; 272706f2543Smrg } else if (oc1 & oc2) { /* completely clipped */ 273706f2543Smrg pbox++; 274706f2543Smrg } else if (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_LINE) { 275706f2543Smrg (*infoRec->SetClippingRectangle)(infoRec->pScrn, 276706f2543Smrg pbox->x1, pbox->y1, pbox->x2 - 1, pbox->y2 - 1); 277706f2543Smrg 278706f2543Smrg if(infoRec->SubsequentSolidBresenhamLine) { 279706f2543Smrg (*infoRec->SubsequentSolidBresenhamLine)( 280706f2543Smrg infoRec->pScrn, x1, y1, dmaj, dmin, e, 281706f2543Smrg#ifdef POLYSEGMENT 282706f2543Smrg (pGC->capStyle != CapNotLast) ? (len+1) : 283706f2543Smrg#endif 284706f2543Smrg len, octant); 285706f2543Smrg } else { 286706f2543Smrg (*infoRec->SubsequentSolidTwoPointLine)( 287706f2543Smrg infoRec->pScrn, x1, y1, x2, y2, 288706f2543Smrg#ifdef POLYSEGMENT 289706f2543Smrg (pGC->capStyle != CapNotLast) ? 0 : 290706f2543Smrg#endif 291706f2543Smrg OMIT_LAST 292706f2543Smrg ); 293706f2543Smrg } 294706f2543Smrg (*infoRec->DisableClipping)(infoRec->pScrn); 295706f2543Smrg pbox++; 296706f2543Smrg } else { 297706f2543Smrg int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; 298706f2543Smrg int clip1 = 0, clip2 = 0; 299706f2543Smrg int err, adx, ady; 300706f2543Smrg 301706f2543Smrg if(octant & YMAJOR) { 302706f2543Smrg ady = dmaj >> 1; 303706f2543Smrg adx = dmin >> 1; 304706f2543Smrg } else { 305706f2543Smrg ady = dmin >> 1; 306706f2543Smrg adx = dmaj >> 1; 307706f2543Smrg } 308706f2543Smrg 309706f2543Smrg if (miZeroClipLine(pbox->x1, pbox->y1, 310706f2543Smrg pbox->x2 - 1, pbox->y2 - 1, 311706f2543Smrg &new_x1, &new_y1, &new_x2, &new_y2, 312706f2543Smrg adx, ady, &clip1, &clip2, 313706f2543Smrg octant, bias, oc1, oc2) == -1) 314706f2543Smrg { 315706f2543Smrg pbox++; 316706f2543Smrg continue; 317706f2543Smrg } 318706f2543Smrg 319706f2543Smrg if (octant & YMAJOR) 320706f2543Smrg len = abs(new_y2 - new_y1); 321706f2543Smrg else 322706f2543Smrg len = abs(new_x2 - new_x1); 323706f2543Smrg#ifdef POLYSEGMENT 324706f2543Smrg if (clip2 != 0 || pGC->capStyle != CapNotLast) 325706f2543Smrg len++; 326706f2543Smrg#else 327706f2543Smrg len += (clip2 != 0); 328706f2543Smrg#endif 329706f2543Smrg if (len) { 330706f2543Smrg int abserr, clipdx, clipdy; 331706f2543Smrg /* unwind bresenham error term to first point */ 332706f2543Smrg if (clip1) { 333706f2543Smrg clipdx = abs(new_x1 - x1); 334706f2543Smrg clipdy = abs(new_y1 - y1); 335706f2543Smrg 336706f2543Smrg if (octant & YMAJOR) 337706f2543Smrg err = e + clipdy*dmin - clipdx*dmaj; 338706f2543Smrg else 339706f2543Smrg err = e + clipdx*dmin - clipdy*dmaj; 340706f2543Smrg } else 341706f2543Smrg err = e; 342706f2543Smrg 343706f2543Smrg#define range infoRec->SolidBresenhamLineErrorTermBits 344706f2543Smrg abserr = abs(err); 345706f2543Smrg while((abserr & range) || 346706f2543Smrg (dmaj & range) || 347706f2543Smrg (dmin & range)) { 348706f2543Smrg dmin >>= 1; 349706f2543Smrg dmaj >>= 1; 350706f2543Smrg abserr >>= 1; 351706f2543Smrg err /= 2; 352706f2543Smrg } 353706f2543Smrg 354706f2543Smrg (*infoRec->SubsequentSolidBresenhamLine)( 355706f2543Smrg infoRec->pScrn, new_x1, new_y1, 356706f2543Smrg dmaj, dmin, err, len, octant); 357706f2543Smrg } 358706f2543Smrg pbox++; 359706f2543Smrg } 360706f2543Smrg } /* while (nbox--) */ 361706f2543Smrg } /* sloped line */ 362706f2543Smrg } /* while (nline--) */ 363706f2543Smrg 364706f2543Smrg#ifndef POLYSEGMENT 365706f2543Smrg /* paint the last point if the end style isn't CapNotLast. 366706f2543Smrg (Assume that a projecting, butt, or round cap that is one 367706f2543Smrg pixel wide is the same as the single pixel of the endpoint.) 368706f2543Smrg */ 369706f2543Smrg 370706f2543Smrg if ((pGC->capStyle != CapNotLast) && 371706f2543Smrg ((ppt->x + xorg != pptInit->x + pDrawable->x) || 372706f2543Smrg (ppt->y + yorg != pptInit->y + pDrawable->y) || 373706f2543Smrg (ppt == pptInit + 1))) 374706f2543Smrg { 375706f2543Smrg nbox = nboxInit; 376706f2543Smrg pbox = pboxInit; 377706f2543Smrg while (nbox--) 378706f2543Smrg { 379706f2543Smrg if ((x2 >= pbox->x1) && (y2 >= pbox->y1) && 380706f2543Smrg (x2 < pbox->x2) && (y2 < pbox->y2)) 381706f2543Smrg { 382706f2543Smrg (*infoRec->SubsequentSolidHorVertLine)( 383706f2543Smrg infoRec->pScrn, x2, y2, 1, DEGREES_0); 384706f2543Smrg break; 385706f2543Smrg } 386706f2543Smrg else 387706f2543Smrg pbox++; 388706f2543Smrg } 389706f2543Smrg } 390706f2543Smrg#endif 391706f2543Smrg 392706f2543Smrg SET_SYNC_FLAG(infoRec); 393706f2543Smrg} 394706f2543Smrg 395