1 2#ifdef HAVE_XORG_CONFIG_H 3#include <xorg-config.h> 4#endif 5 6#include <stdlib.h> 7 8#include <X11/X.h> 9#include "misc.h" 10#include "xf86.h" 11#include "xf86_OSproc.h" 12 13#include "scrnintstr.h" 14#include "pixmapstr.h" 15#include "miline.h" 16#include "xf86str.h" 17#include "xaa.h" 18#include "xaalocal.h" 19 20 21void 22#ifdef POLYSEGMENT 23XAAPolySegment( 24 DrawablePtr pDrawable, 25 GCPtr pGC, 26 int nseg, 27 xSegment *pSeg 28#else 29XAAPolyLines( 30 DrawablePtr pDrawable, 31 GCPtr pGC, 32 int mode, /* Origin or Previous */ 33 int npt, /* number of points */ 34 DDXPointPtr pptInit 35#endif 36){ 37 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 38 BoxPtr pboxInit = RegionRects(pGC->pCompositeClip); 39 int nboxInit = RegionNumRects(pGC->pCompositeClip); 40 unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); 41 int xorg = pDrawable->x; 42 int yorg = pDrawable->y; 43 int nbox; 44 BoxPtr pbox; 45#ifndef POLYSEGMENT 46 DDXPointPtr ppt; 47#endif 48 int x1, x2, y1, y2, tmp, len; 49 50 if(!nboxInit) 51 return; 52 53 if (infoRec->SolidLineFlags & LINE_LIMIT_COORDS) { 54 int minValX = infoRec->SolidLineLimits.x1; 55 int maxValX = infoRec->SolidLineLimits.x2; 56 int minValY = infoRec->SolidLineLimits.y1; 57 int maxValY = infoRec->SolidLineLimits.y2; 58#ifdef POLYSEGMENT 59 int n = nseg; 60 xSegment *s = pSeg; 61 62 while (n--) 63#else 64 int n = npt; 65 int xorgtmp = xorg; 66 int yorgtmp = yorg; 67 68 ppt = pptInit; 69 x2 = ppt->x + xorgtmp; 70 y2 = ppt->y + yorgtmp; 71 while (--n) 72#endif 73 { 74#ifdef POLYSEGMENT 75 x1 = s->x1 + xorg; 76 y1 = s->y1 + yorg; 77 x2 = s->x2 + xorg; 78 y2 = s->y2 + yorg; 79 s++; 80#else 81 x1 = x2; 82 y1 = y2; 83 ++ppt; 84 if (mode == CoordModePrevious) { 85 xorgtmp = x1; 86 yorgtmp = y1; 87 } 88 x2 = ppt->x + xorgtmp; 89 y2 = ppt->y + yorgtmp; 90#endif 91 if (x1 > maxValX || x1 < minValX || 92 x2 > maxValX || x2 < minValX || 93 y1 > maxValY || y1 < minValY || 94 y2 > maxValY || y2 < minValY) { 95#ifdef POLYSEGMENT 96 XAAFallbackOps.PolySegment(pDrawable, pGC, nseg, pSeg); 97#else 98 XAAFallbackOps.Polylines(pDrawable, pGC, mode, npt, pptInit); 99#endif 100 return; 101 } 102 } 103 } 104 105 (*infoRec->SetupForSolidLine)(infoRec->pScrn, pGC->fgPixel, 106 pGC->alu, pGC->planemask); 107 108#ifdef POLYSEGMENT 109 while (nseg--) 110#else 111 ppt = pptInit; 112 x2 = ppt->x + xorg; 113 y2 = ppt->y + yorg; 114 while(--npt) 115#endif 116 { 117 nbox = nboxInit; 118 pbox = pboxInit; 119 120#ifdef POLYSEGMENT 121 x1 = pSeg->x1 + xorg; 122 y1 = pSeg->y1 + yorg; 123 x2 = pSeg->x2 + xorg; 124 y2 = pSeg->y2 + yorg; 125 pSeg++; 126#else 127 x1 = x2; 128 y1 = y2; 129 ++ppt; 130 if (mode == CoordModePrevious) { 131 xorg = x1; 132 yorg = y1; 133 } 134 x2 = ppt->x + xorg; 135 y2 = ppt->y + yorg; 136#endif 137 138 if (x1 == x2) { /* vertical line */ 139 /* make the line go top to bottom of screen, keeping 140 endpoint semantics 141 */ 142 if (y1 > y2) { 143 tmp = y2; 144 y2 = y1 + 1; 145 y1 = tmp + 1; 146#ifdef POLYSEGMENT 147 if (pGC->capStyle != CapNotLast) y1--; 148#endif 149 } 150#ifdef POLYSEGMENT 151 else if (pGC->capStyle != CapNotLast) y2++; 152#endif 153 /* get to first band that might contain part of line */ 154 while(nbox && (pbox->y2 <= y1)) { 155 pbox++; 156 nbox--; 157 } 158 159 /* stop when lower edge of box is beyond end of line */ 160 while(nbox && (y2 >= pbox->y1)) { 161 if ((x1 >= pbox->x1) && (x1 < pbox->x2)) { 162 tmp = max(y1, pbox->y1); 163 len = min(y2, pbox->y2) - tmp; 164 if (len) (*infoRec->SubsequentSolidHorVertLine)( 165 infoRec->pScrn, x1, tmp, len, DEGREES_270); 166 } 167 nbox--; 168 pbox++; 169 } 170#ifndef POLYSEGMENT 171 y2 = ppt->y + yorg; 172#endif 173 } else if (y1 == y2) { /* horizontal line */ 174 /* force line from left to right, keeping endpoint semantics */ 175 if (x1 > x2) { 176 tmp = x2; 177 x2 = x1 + 1; 178 x1 = tmp + 1; 179#ifdef POLYSEGMENT 180 if (pGC->capStyle != CapNotLast) x1--; 181#endif 182 } 183#ifdef POLYSEGMENT 184 else if (pGC->capStyle != CapNotLast) x2++; 185#endif 186 187 /* find the correct band */ 188 while(nbox && (pbox->y2 <= y1)) { 189 pbox++; 190 nbox--; 191 } 192 193 /* try to draw the line, if we haven't gone beyond it */ 194 if (nbox && (pbox->y1 <= y1)) { 195 int orig_y = pbox->y1; 196 /* when we leave this band, we're done */ 197 while(nbox && (orig_y == pbox->y1)) { 198 if (pbox->x2 <= x1) { 199 /* skip boxes until one might contain start point */ 200 nbox--; 201 pbox++; 202 continue; 203 } 204 205 /* stop if left of box is beyond right of line */ 206 if (pbox->x1 >= x2) { 207 nbox = 0; 208 break; 209 } 210 211 tmp = max(x1, pbox->x1); 212 len = min(x2, pbox->x2) - tmp; 213 if (len) (*infoRec->SubsequentSolidHorVertLine)( 214 infoRec->pScrn, tmp, y1, len, DEGREES_0); 215 nbox--; 216 pbox++; 217 } 218 } 219#ifndef POLYSEGMENT 220 x2 = ppt->x + xorg; 221#endif 222 } else{ /* sloped line */ 223 unsigned int oc1, oc2; 224 int dmin, dmaj, e, octant; 225 226 if (infoRec->SubsequentSolidBresenhamLine) { 227 if((dmaj = x2 - x1) < 0) { 228 dmaj = -dmaj; 229 octant = XDECREASING; 230 } else octant = 0; 231 232 if((dmin = y2 - y1) < 0) { 233 dmin = -dmin; 234 octant |= YDECREASING; 235 } 236 237 if(dmin >= dmaj){ 238 tmp = dmin; dmin = dmaj; dmaj = tmp; 239 octant |= YMAJOR; 240 } 241 242 e = -dmaj - ((bias >> octant) & 1); 243 len = dmaj; 244 dmin <<= 1; 245 dmaj <<= 1; 246 } else { /* Muffle compiler */ 247 dmin = dmaj = e = octant = len = 0; 248 } 249 250 while(nbox--) { 251 oc1 = oc2 = 0; 252 OUTCODES(oc1, x1, y1, pbox); 253 OUTCODES(oc2, x2, y2, pbox); 254 if (!(oc1 | oc2)) { /* unclipped */ 255 if(infoRec->SubsequentSolidTwoPointLine) { 256 (*infoRec->SubsequentSolidTwoPointLine)( 257 infoRec->pScrn, x1, y1, x2, y2, 258#ifdef POLYSEGMENT 259 (pGC->capStyle != CapNotLast) ? 0 : 260#endif 261 OMIT_LAST 262 ); 263 } else { 264 (*infoRec->SubsequentSolidBresenhamLine)( 265 infoRec->pScrn, x1, y1, dmaj, dmin, e, 266#ifdef POLYSEGMENT 267 (pGC->capStyle != CapNotLast) ? (len+1) : 268#endif 269 len, octant); 270 } 271 break; 272 } else if (oc1 & oc2) { /* completely clipped */ 273 pbox++; 274 } else if (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_LINE) { 275 (*infoRec->SetClippingRectangle)(infoRec->pScrn, 276 pbox->x1, pbox->y1, pbox->x2 - 1, pbox->y2 - 1); 277 278 if(infoRec->SubsequentSolidBresenhamLine) { 279 (*infoRec->SubsequentSolidBresenhamLine)( 280 infoRec->pScrn, x1, y1, dmaj, dmin, e, 281#ifdef POLYSEGMENT 282 (pGC->capStyle != CapNotLast) ? (len+1) : 283#endif 284 len, octant); 285 } else { 286 (*infoRec->SubsequentSolidTwoPointLine)( 287 infoRec->pScrn, x1, y1, x2, y2, 288#ifdef POLYSEGMENT 289 (pGC->capStyle != CapNotLast) ? 0 : 290#endif 291 OMIT_LAST 292 ); 293 } 294 (*infoRec->DisableClipping)(infoRec->pScrn); 295 pbox++; 296 } else { 297 int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; 298 int clip1 = 0, clip2 = 0; 299 int err, adx, ady; 300 301 if(octant & YMAJOR) { 302 ady = dmaj >> 1; 303 adx = dmin >> 1; 304 } else { 305 ady = dmin >> 1; 306 adx = dmaj >> 1; 307 } 308 309 if (miZeroClipLine(pbox->x1, pbox->y1, 310 pbox->x2 - 1, pbox->y2 - 1, 311 &new_x1, &new_y1, &new_x2, &new_y2, 312 adx, ady, &clip1, &clip2, 313 octant, bias, oc1, oc2) == -1) 314 { 315 pbox++; 316 continue; 317 } 318 319 if (octant & YMAJOR) 320 len = abs(new_y2 - new_y1); 321 else 322 len = abs(new_x2 - new_x1); 323#ifdef POLYSEGMENT 324 if (clip2 != 0 || pGC->capStyle != CapNotLast) 325 len++; 326#else 327 len += (clip2 != 0); 328#endif 329 if (len) { 330 int abserr, clipdx, clipdy; 331 /* unwind bresenham error term to first point */ 332 if (clip1) { 333 clipdx = abs(new_x1 - x1); 334 clipdy = abs(new_y1 - y1); 335 336 if (octant & YMAJOR) 337 err = e + clipdy*dmin - clipdx*dmaj; 338 else 339 err = e + clipdx*dmin - clipdy*dmaj; 340 } else 341 err = e; 342 343#define range infoRec->SolidBresenhamLineErrorTermBits 344 abserr = abs(err); 345 while((abserr & range) || 346 (dmaj & range) || 347 (dmin & range)) { 348 dmin >>= 1; 349 dmaj >>= 1; 350 abserr >>= 1; 351 err /= 2; 352 } 353 354 (*infoRec->SubsequentSolidBresenhamLine)( 355 infoRec->pScrn, new_x1, new_y1, 356 dmaj, dmin, err, len, octant); 357 } 358 pbox++; 359 } 360 } /* while (nbox--) */ 361 } /* sloped line */ 362 } /* while (nline--) */ 363 364#ifndef POLYSEGMENT 365 /* paint the last point if the end style isn't CapNotLast. 366 (Assume that a projecting, butt, or round cap that is one 367 pixel wide is the same as the single pixel of the endpoint.) 368 */ 369 370 if ((pGC->capStyle != CapNotLast) && 371 ((ppt->x + xorg != pptInit->x + pDrawable->x) || 372 (ppt->y + yorg != pptInit->y + pDrawable->y) || 373 (ppt == pptInit + 1))) 374 { 375 nbox = nboxInit; 376 pbox = pboxInit; 377 while (nbox--) 378 { 379 if ((x2 >= pbox->x1) && (y2 >= pbox->y1) && 380 (x2 < pbox->x2) && (y2 < pbox->y2)) 381 { 382 (*infoRec->SubsequentSolidHorVertLine)( 383 infoRec->pScrn, x2, y2, 1, DEGREES_0); 384 break; 385 } 386 else 387 pbox++; 388 } 389 } 390#endif 391 392 SET_SYNC_FLAG(infoRec); 393} 394 395