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 23XAAPolySegmentDashed( 24 DrawablePtr pDrawable, 25 GCPtr pGC, 26 int nseg, 27 xSegment *pSeg 28#else 29XAAPolyLinesDashed( 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 XAAGCPtr pGCPriv = (XAAGCPtr)dixLookupPrivate(&pGC->devPrivates, 39 XAAGetGCKey()); 40 BoxPtr pboxInit = RegionRects(pGC->pCompositeClip); 41 int nboxInit = RegionNumRects(pGC->pCompositeClip); 42 unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); 43 int xorg = pDrawable->x; 44 int yorg = pDrawable->y; 45 int nbox; 46 BoxPtr pbox; 47#ifndef POLYSEGMENT 48 DDXPointPtr ppt; 49#endif 50 unsigned int oc1, oc2; 51 int dmin, dmaj, e, octant; 52 int x1, x2, y1, y2, tmp, len, offset; 53 int PatternLength, PatternOffset; 54 55 if(!nboxInit) 56 return; 57 58 if (infoRec->DashedLineFlags & LINE_LIMIT_COORDS) { 59 int minValX = infoRec->DashedLineLimits.x1; 60 int maxValX = infoRec->DashedLineLimits.x2; 61 int minValY = infoRec->DashedLineLimits.y1; 62 int maxValY = infoRec->DashedLineLimits.y2; 63#ifdef POLYSEGMENT 64 int n = nseg; 65 xSegment *s = pSeg; 66 67 while (n--) 68#else 69 int n = npt; 70 int xorgtmp = xorg; 71 int yorgtmp = yorg; 72 73 ppt = pptInit; 74 x2 = ppt->x + xorgtmp; 75 y2 = ppt->y + yorgtmp; 76 while (--n) 77#endif 78 { 79#ifdef POLYSEGMENT 80 x1 = s->x1 + xorg; 81 y1 = s->y1 + yorg; 82 x2 = s->x2 + xorg; 83 y2 = s->y2 + yorg; 84 s++; 85#else 86 x1 = x2; 87 y1 = y2; 88 ++ppt; 89 if (mode == CoordModePrevious) { 90 xorgtmp = x1; 91 yorgtmp = y1; 92 } 93 x2 = ppt->x + xorgtmp; 94 y2 = ppt->y + yorgtmp; 95#endif 96 if (x1 > maxValX || x1 < minValX || 97 x2 > maxValX || x2 < minValX || 98 y1 > maxValY || y1 < minValY || 99 y2 > maxValY || y2 < minValY) { 100#ifdef POLYSEGMENT 101 XAAFallbackOps.PolySegment(pDrawable, pGC, nseg, pSeg); 102#else 103 XAAFallbackOps.Polylines(pDrawable, pGC, mode, npt, pptInit); 104#endif 105 return; 106 } 107 } 108 } 109 110 PatternLength = pGCPriv->DashLength; 111 PatternOffset = pGC->dashOffset % PatternLength; 112 113 (*infoRec->SetupForDashedLine)(infoRec->pScrn, pGC->fgPixel, 114 (pGC->lineStyle == LineDoubleDash) ? pGC->bgPixel : -1, 115 pGC->alu, pGC->planemask, PatternLength, pGCPriv->DashPattern); 116 117 118#ifdef POLYSEGMENT 119 while (nseg--) 120#else 121 ppt = pptInit; 122 x2 = ppt->x + xorg; 123 y2 = ppt->y + yorg; 124 while(--npt) 125#endif 126 { 127 nbox = nboxInit; 128 pbox = pboxInit; 129 130#ifdef POLYSEGMENT 131 x1 = pSeg->x1 + xorg; 132 y1 = pSeg->y1 + yorg; 133 x2 = pSeg->x2 + xorg; 134 y2 = pSeg->y2 + yorg; 135 pSeg++; 136#else 137 x1 = x2; 138 y1 = y2; 139 ++ppt; 140 if (mode == CoordModePrevious) { 141 xorg = x1; 142 yorg = y1; 143 } 144 x2 = ppt->x + xorg; 145 y2 = ppt->y + yorg; 146#endif 147 148 149 if (infoRec->SubsequentDashedBresenhamLine) { 150 if((dmaj = x2 - x1) < 0) { 151 dmaj = -dmaj; 152 octant = XDECREASING; 153 } else octant = 0; 154 155 if((dmin = y2 - y1) < 0) { 156 dmin = -dmin; 157 octant |= YDECREASING; 158 } 159 160 if(dmin >= dmaj){ 161 tmp = dmin; dmin = dmaj; dmaj = tmp; 162 octant |= YMAJOR; 163 } 164 165 e = -dmaj - ((bias >> octant) & 1); 166 len = dmaj; 167 dmin <<= 1; 168 dmaj <<= 1; 169 } else { /* Muffle compiler */ 170 dmin = dmaj = e = octant = len = 0; 171 } 172 173 while(nbox--) { 174 oc1 = oc2 = 0; 175 OUTCODES(oc1, x1, y1, pbox); 176 OUTCODES(oc2, x2, y2, pbox); 177 if (!(oc1 | oc2)) { /* uncliped */ 178 if(infoRec->SubsequentDashedTwoPointLine) { 179 (*infoRec->SubsequentDashedTwoPointLine)( 180 infoRec->pScrn, x1, y1, x2, y2, 181#ifdef POLYSEGMENT 182 (pGC->capStyle != CapNotLast) ? 0 : 183#endif 184 OMIT_LAST, PatternOffset); 185 } else { 186 (*infoRec->SubsequentDashedBresenhamLine)( 187 infoRec->pScrn, x1, y1, dmaj, dmin, e, 188#ifdef POLYSEGMENT 189 (pGC->capStyle != CapNotLast) ? (len+1) : 190#endif 191 len, octant, PatternOffset); 192 } 193 break; 194 } else if (oc1 & oc2) { /* completely clipped */ 195 pbox++; 196 } else if (infoRec->ClippingFlags & HARDWARE_CLIP_DASHED_LINE) { 197 (*infoRec->SetClippingRectangle)(infoRec->pScrn, 198 pbox->x1, pbox->y1, pbox->x2 - 1, pbox->y2 - 1); 199 200 if(infoRec->SubsequentDashedBresenhamLine) { 201 (*infoRec->SubsequentDashedBresenhamLine)( 202 infoRec->pScrn, x1, y1, dmaj, dmin, e, 203#ifdef POLYSEGMENT 204 (pGC->capStyle != CapNotLast) ? (len+1) : 205#endif 206 len, octant, PatternOffset); 207 } else { 208 (*infoRec->SubsequentDashedTwoPointLine)( 209 infoRec->pScrn, x1, y1, x2, y2, 210#ifdef POLYSEGMENT 211 (pGC->capStyle != CapNotLast) ? 0 : 212#endif 213 OMIT_LAST, PatternOffset 214 ); 215 } 216 (*infoRec->DisableClipping)(infoRec->pScrn); 217 pbox++; 218 } else { 219 int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; 220 int clip1 = 0, clip2 = 0; 221 int err, adx, ady; 222 223 if(octant & YMAJOR) { 224 ady = dmaj >> 1; 225 adx = dmin >> 1; 226 } else { 227 ady = dmin >> 1; 228 adx = dmaj >> 1; 229 } 230 231 if (miZeroClipLine(pbox->x1, pbox->y1, 232 pbox->x2 - 1, pbox->y2 - 1, 233 &new_x1, &new_y1, &new_x2, &new_y2, 234 adx, ady, &clip1, &clip2, 235 octant, bias, oc1, oc2) == -1) 236 { 237 pbox++; 238 continue; 239 } 240 241 if (octant & YMAJOR) 242 len = abs(new_y2 - new_y1); 243 else 244 len = abs(new_x2 - new_x1); 245#ifdef POLYSEGMENT 246 if (clip2 != 0 || pGC->capStyle != CapNotLast) 247 len++; 248#else 249 len += (clip2 != 0); 250#endif 251 if (len) { 252 int abserr, clipdx, clipdy; 253 /* unwind bresenham error term to first point */ 254 if (clip1) { 255 clipdx = abs(new_x1 - x1); 256 clipdy = abs(new_y1 - y1); 257 258 if (octant & YMAJOR) 259 err = e + clipdy*dmin - clipdx*dmaj; 260 else 261 err = e + clipdx*dmin - clipdy*dmaj; 262 } else 263 err = e; 264 265#define range infoRec->DashedBresenhamLineErrorTermBits 266 abserr = abs(err); 267 while((abserr & range) || 268 (dmaj & range) || 269 (dmin & range)) { 270 dmin >>= 1; 271 dmaj >>= 1; 272 abserr >>= 1; 273 err /= 2; 274 } 275 276 if(octant & YMAJOR) 277 offset = abs(new_y1 - y1); 278 else 279 offset = abs(new_x1 - x1); 280 281 offset += PatternOffset; 282 offset %= PatternLength; 283 284 (*infoRec->SubsequentDashedBresenhamLine)( 285 infoRec->pScrn, new_x1, new_y1, 286 dmaj, dmin, err, len, octant, offset); 287 } 288 pbox++; 289 } 290 } /* while (nbox--) */ 291#ifndef POLYSEGMENT 292 len = abs(y2 - y1); 293 tmp = abs(x2 - x1); 294 PatternOffset += (len > tmp) ? len : tmp; 295 PatternOffset %= PatternLength; 296#endif 297 } /* while (nline--) */ 298 299#ifndef POLYSEGMENT 300 /* paint the last point if the end style isn't CapNotLast. 301 (Assume that a projecting, butt, or round cap that is one 302 pixel wide is the same as the single pixel of the endpoint.) 303 */ 304 305 if ((pGC->capStyle != CapNotLast) && 306 ((ppt->x + xorg != pptInit->x + pDrawable->x) || 307 (ppt->y + yorg != pptInit->y + pDrawable->y) || 308 (ppt == pptInit + 1))) 309 { 310 nbox = nboxInit; 311 pbox = pboxInit; 312 while (nbox--) { 313 if ((x2 >= pbox->x1) && (y2 >= pbox->y1) && 314 (x2 < pbox->x2) && (y2 < pbox->y2)) 315 { 316 if(infoRec->SubsequentDashedTwoPointLine) { 317 (*infoRec->SubsequentDashedTwoPointLine)( 318 infoRec->pScrn, x2, y2, x2, y2, 0, 319 PatternOffset); 320 } else { 321 (*infoRec->SubsequentDashedBresenhamLine)( 322 infoRec->pScrn, x2, y2, 2, 0, -1, 323 1, 0, PatternOffset); 324 } 325 break; 326 } else 327 pbox++; 328 } 329 } 330#endif 331 332 SET_SYNC_FLAG(infoRec); 333} 334 335