1706f2543Smrg/* 2706f2543Smrg 3706f2543SmrgXAAPolylinesWideSolid does not maintain a span list and subsequently does 4706f2543Smrgnot follow the "touch-each-pixel-once" rules for wide lines and arcs. 5706f2543SmrgThis means it can only be used in the case where we have 6706f2543SmrgmiSpansEasyRop(pGC->alu). Since we clip spans on the fly, we 7706f2543Smrglimited usage of this function to one rect situations. This 8706f2543Smrgfunction is used only for solid lines. 9706f2543Smrg 10706f2543Smrg Adapted from miWideLine by Mark Vojkovich (mvojkovi@ucsd.edu) 11706f2543SmrgOriginal mi code written by Keith Packard. 12706f2543Smrg 13706f2543Smrg*/ 14706f2543Smrg 15706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 16706f2543Smrg#include <xorg-config.h> 17706f2543Smrg#endif 18706f2543Smrg 19706f2543Smrg#include <math.h> 20706f2543Smrg 21706f2543Smrg#include "misc.h" 22706f2543Smrg#include "xf86.h" 23706f2543Smrg#include "xf86_OSproc.h" 24706f2543Smrg 25706f2543Smrg#include <X11/X.h> 26706f2543Smrg#include "windowstr.h" 27706f2543Smrg#include "gcstruct.h" 28706f2543Smrg#include "regionstr.h" 29706f2543Smrg#include "miwideline.h" 30706f2543Smrg#include "mi.h" 31706f2543Smrg#include "xf86str.h" 32706f2543Smrg#include "xaa.h" 33706f2543Smrg#include "xaalocal.h" 34706f2543Smrg 35706f2543Smrg#define DRAW_POINT(pScrn, x, y) \ 36706f2543Smrg if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, 1); \ 37706f2543Smrg else XAAPointHelper(pScrn, x, y) 38706f2543Smrg 39706f2543Smrg#define FILL_RECT(pScrn, x, y, w, h) \ 40706f2543Smrg if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); \ 41706f2543Smrg else XAAFillRectHelper(pScrn, x, y, w, h) 42706f2543Smrg 43706f2543Smrg#define FILL_SPAN(pScrn, x, y, w) \ 44706f2543Smrg if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, 1); \ 45706f2543Smrg else XAASpanHelper(pScrn, x, y, w) 46706f2543Smrg 47706f2543Smrg 48706f2543Smrg#define CLIPSTEPEDGE(edgey,edge,edgeleft) \ 49706f2543Smrg if (ybase == edgey) { \ 50706f2543Smrg if (edgeleft) { \ 51706f2543Smrg if (edge->x > xcl) \ 52706f2543Smrg xcl = edge->x; \ 53706f2543Smrg } else { \ 54706f2543Smrg if (edge->x < xcr) \ 55706f2543Smrg xcr = edge->x; \ 56706f2543Smrg } \ 57706f2543Smrg edgey++; \ 58706f2543Smrg edge->x += edge->stepx; \ 59706f2543Smrg edge->e += edge->dx; \ 60706f2543Smrg if (edge->e > 0) { \ 61706f2543Smrg edge->x += edge->signdx; \ 62706f2543Smrg edge->e -= edge->dy; \ 63706f2543Smrg } \ 64706f2543Smrg } 65706f2543Smrg 66706f2543Smrgstatic void 67706f2543SmrgXAAPointHelper(ScrnInfoPtr pScrn, int x, int y) 68706f2543Smrg{ 69706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 70706f2543Smrg BoxPtr extents = infoRec->ClipBox; 71706f2543Smrg 72706f2543Smrg if((x >= extents->x1) && (x < extents->x2) && 73706f2543Smrg (y >= extents->y1) && (y < extents->y2)) 74706f2543Smrg (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, 1); 75706f2543Smrg} 76706f2543Smrg 77706f2543Smrgstatic void 78706f2543SmrgXAAFillRectHelper(ScrnInfoPtr pScrn, int x1, int y1, int dx, int dy) 79706f2543Smrg{ 80706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 81706f2543Smrg BoxPtr extents = infoRec->ClipBox; 82706f2543Smrg int x2 = x1 + dx; 83706f2543Smrg int y2 = y1 + dy; 84706f2543Smrg 85706f2543Smrg if(x1 < extents->x1) x1 = extents->x1; 86706f2543Smrg if(x2 >= extents->x2) x2 = extents->x2; 87706f2543Smrg if((dx = x2 - x1)<1) return; 88706f2543Smrg if(y1 < extents->y1) y1 = extents->y1; 89706f2543Smrg if(y2 >= extents->y2) y2 = extents->y2; 90706f2543Smrg if((dy = y2 - y1)<1) return; 91706f2543Smrg 92706f2543Smrg (*infoRec->SubsequentSolidFillRect)(pScrn, x1, y1, dx, dy); 93706f2543Smrg} 94706f2543Smrg 95706f2543Smrg 96706f2543Smrgstatic void 97706f2543SmrgXAASpanHelper(ScrnInfoPtr pScrn, int x1, int y, int width) 98706f2543Smrg{ 99706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 100706f2543Smrg BoxPtr extents = infoRec->ClipBox; 101706f2543Smrg int x2; 102706f2543Smrg 103706f2543Smrg if((y < extents->y1) || (y >= extents->y2)) return; 104706f2543Smrg 105706f2543Smrg x2 = x1 + width; 106706f2543Smrg if(x1 < extents->x1) x1 = extents->x1; 107706f2543Smrg if(x2 > extents->x2) x2 = extents->x2; 108706f2543Smrg width = x2 - x1; 109706f2543Smrg 110706f2543Smrg if(width > 0) 111706f2543Smrg (*infoRec->SubsequentSolidFillRect)(pScrn, x1, y, width, 1); 112706f2543Smrg 113706f2543Smrg} 114706f2543Smrg 115706f2543Smrg#define FixError(x, dx, dy, e, sign, step, h) { \ 116706f2543Smrg e += (h) * dx; \ 117706f2543Smrg x += (h) * step; \ 118706f2543Smrg if(e > 0) { \ 119706f2543Smrg x += e * sign/dy; \ 120706f2543Smrg e %= dy; \ 121706f2543Smrg if(e) { \ 122706f2543Smrg x += sign; \ 123706f2543Smrg e -= dy; \ 124706f2543Smrg } \ 125706f2543Smrg } \ 126706f2543Smrg} 127706f2543Smrg 128706f2543Smrg 129706f2543Smrgstatic void 130706f2543SmrgXAAFillPolyHelper ( 131706f2543Smrg GCPtr pGC, 132706f2543Smrg int y, /* start y coordinate */ 133706f2543Smrg int overall_height, /* height of entire segment */ 134706f2543Smrg PolyEdgePtr left, PolyEdgePtr right, 135706f2543Smrg int left_count, int right_count ) 136706f2543Smrg{ 137706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 138706f2543Smrg BoxPtr extents = infoRec->ClipBox; 139706f2543Smrg int left_x, left_e, left_stepx, left_signdx, left_dy, left_dx; 140706f2543Smrg int right_x, right_e, right_stepx, right_signdx, right_dy, right_dx; 141706f2543Smrg int height, left_height, right_height; 142706f2543Smrg int xorg; 143706f2543Smrg Bool hardClip; 144706f2543Smrg 145706f2543Smrg if((y >= extents->y2) || ((y + overall_height) <= extents->y1)) 146706f2543Smrg return; 147706f2543Smrg 148706f2543Smrg /* Muffle compiler */ 149706f2543Smrg left_x = left_e = left_stepx = left_signdx = left_dy = left_dx = 0; 150706f2543Smrg right_x = right_e = right_stepx = right_signdx = right_dy = right_dx = 0; 151706f2543Smrg 152706f2543Smrg left_height = right_height = 0; 153706f2543Smrg xorg = 0; 154706f2543Smrg 155706f2543Smrg hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 156706f2543Smrg 157706f2543Smrg while ((left_count || left_height) && (right_count || right_height)) { 158706f2543Smrg if (!left_height && left_count) { 159706f2543Smrg left_height = left->height; 160706f2543Smrg left_x = left->x + xorg; 161706f2543Smrg left_stepx = left->stepx; 162706f2543Smrg left_signdx = left->signdx; 163706f2543Smrg left_e = left->e; 164706f2543Smrg left_dy = left->dy; 165706f2543Smrg left_dx = left->dx; 166706f2543Smrg left_count--; 167706f2543Smrg left++; 168706f2543Smrg } 169706f2543Smrg if (!right_height && right_count) { 170706f2543Smrg right_height = right->height; 171706f2543Smrg right_x = right->x + xorg + 1; 172706f2543Smrg right_stepx = right->stepx; 173706f2543Smrg right_signdx = right->signdx; 174706f2543Smrg right_e = right->e; 175706f2543Smrg right_dy = right->dy; 176706f2543Smrg right_dx = right->dx; 177706f2543Smrg right_count--; 178706f2543Smrg right++; 179706f2543Smrg } 180706f2543Smrg 181706f2543Smrg height = (left_height > right_height) ? right_height : left_height; 182706f2543Smrg 183706f2543Smrg left_height -= height; 184706f2543Smrg right_height -= height; 185706f2543Smrg 186706f2543Smrg if(hardClip && infoRec->SubsequentSolidFillTrap && (height > 6)) { 187706f2543Smrg int right_DX, left_DX; 188706f2543Smrg 189706f2543Smrg right_DX = (right_dx * right_signdx) + (right_stepx * right_dy); 190706f2543Smrg left_DX = (left_dx * left_signdx) + (left_stepx * left_dy); 191706f2543Smrg 192706f2543Smrg (*infoRec->SubsequentSolidFillTrap)(infoRec->pScrn, y, height, 193706f2543Smrg left_x, left_DX, left_dy, left_e, 194706f2543Smrg right_x - 1, right_DX, right_dy, right_e); 195706f2543Smrg 196706f2543Smrg FixError(left_x, left_dx, left_dy, left_e, left_signdx, 197706f2543Smrg left_stepx, height); 198706f2543Smrg FixError(right_x, right_dx, right_dy, right_e, right_signdx, 199706f2543Smrg right_stepx, height); 200706f2543Smrg y += height; 201706f2543Smrg continue; 202706f2543Smrg } 203706f2543Smrg 204706f2543Smrg while (height--) { 205706f2543Smrg if(right_x > left_x) { 206706f2543Smrg FILL_SPAN(infoRec->pScrn, left_x, y, right_x - left_x); 207706f2543Smrg } 208706f2543Smrg y++; 209706f2543Smrg 210706f2543Smrg left_x += left_stepx; 211706f2543Smrg left_e += left_dx; 212706f2543Smrg if (left_e > 0) { 213706f2543Smrg left_x += left_signdx; 214706f2543Smrg left_e -= left_dy; 215706f2543Smrg } 216706f2543Smrg right_x += right_stepx; 217706f2543Smrg right_e += right_dx; 218706f2543Smrg if (right_e > 0) { 219706f2543Smrg right_x += right_signdx; 220706f2543Smrg right_e -= right_dy; 221706f2543Smrg } 222706f2543Smrg 223706f2543Smrg } 224706f2543Smrg } 225706f2543Smrg} 226706f2543Smrg 227706f2543Smrg 228706f2543Smrg 229706f2543Smrgstatic void 230706f2543SmrgXAAWideSegment ( 231706f2543Smrg GCPtr pGC, 232706f2543Smrg int x1, int y1, int x2, int y2, 233706f2543Smrg Bool projectLeft, Bool projectRight, 234706f2543Smrg LineFacePtr leftFace, LineFacePtr rightFace ) 235706f2543Smrg{ 236706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 237706f2543Smrg double l, L, r; 238706f2543Smrg double xa, ya; 239706f2543Smrg double projectXoff, projectYoff; 240706f2543Smrg double k; 241706f2543Smrg double maxy; 242706f2543Smrg int x, y; 243706f2543Smrg int dx, dy; 244706f2543Smrg int finaly; 245706f2543Smrg PolyEdgePtr left, right; 246706f2543Smrg PolyEdgePtr top, bottom; 247706f2543Smrg int lefty, righty, topy, bottomy; 248706f2543Smrg int signdx; 249706f2543Smrg PolyEdgeRec lefts[2], rights[2]; 250706f2543Smrg LineFacePtr tface; 251706f2543Smrg int lw = pGC->lineWidth; 252706f2543Smrg Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 253706f2543Smrg 254706f2543Smrg /* draw top-to-bottom always */ 255706f2543Smrg if ((y2 < y1) || ((y2 == y1) && (x2 < x1))) { 256706f2543Smrg x = x1; 257706f2543Smrg x1 = x2; 258706f2543Smrg x2 = x; 259706f2543Smrg 260706f2543Smrg y = y1; 261706f2543Smrg y1 = y2; 262706f2543Smrg y2 = y; 263706f2543Smrg 264706f2543Smrg x = projectLeft; 265706f2543Smrg projectLeft = projectRight; 266706f2543Smrg projectRight = x; 267706f2543Smrg 268706f2543Smrg tface = leftFace; 269706f2543Smrg leftFace = rightFace; 270706f2543Smrg rightFace = tface; 271706f2543Smrg } 272706f2543Smrg 273706f2543Smrg dy = y2 - y1; 274706f2543Smrg signdx = 1; 275706f2543Smrg dx = x2 - x1; 276706f2543Smrg if (dx < 0) 277706f2543Smrg signdx = -1; 278706f2543Smrg 279706f2543Smrg leftFace->x = x1; 280706f2543Smrg leftFace->y = y1; 281706f2543Smrg leftFace->dx = dx; 282706f2543Smrg leftFace->dy = dy; 283706f2543Smrg 284706f2543Smrg rightFace->x = x2; 285706f2543Smrg rightFace->y = y2; 286706f2543Smrg rightFace->dx = -dx; 287706f2543Smrg rightFace->dy = -dy; 288706f2543Smrg 289706f2543Smrg if (!dy) { 290706f2543Smrg rightFace->xa = 0; 291706f2543Smrg rightFace->ya = (double) lw / 2.0; 292706f2543Smrg rightFace->k = -(double) (lw * dx) / 2.0; 293706f2543Smrg leftFace->xa = 0; 294706f2543Smrg leftFace->ya = -rightFace->ya; 295706f2543Smrg leftFace->k = rightFace->k; 296706f2543Smrg x = x1; 297706f2543Smrg if (projectLeft) 298706f2543Smrg x -= (lw >> 1); 299706f2543Smrg y = y1 - (lw >> 1); 300706f2543Smrg dx = x2 - x; 301706f2543Smrg if (projectRight) 302706f2543Smrg dx += ((lw + 1) >> 1); 303706f2543Smrg dy = lw; 304706f2543Smrg FILL_RECT(infoRec->pScrn, x, y, dx, dy); 305706f2543Smrg } else if (!dx) { 306706f2543Smrg leftFace->xa = (double) lw / 2.0; 307706f2543Smrg leftFace->ya = 0; 308706f2543Smrg leftFace->k = (double) (lw * dy) / 2.0; 309706f2543Smrg rightFace->xa = -leftFace->xa; 310706f2543Smrg rightFace->ya = 0; 311706f2543Smrg rightFace->k = leftFace->k; 312706f2543Smrg y = y1; 313706f2543Smrg if (projectLeft) 314706f2543Smrg y -= lw >> 1; 315706f2543Smrg x = x1 - (lw >> 1); 316706f2543Smrg dy = y2 - y; 317706f2543Smrg if (projectRight) 318706f2543Smrg dy += ((lw + 1) >> 1); 319706f2543Smrg dx = lw; 320706f2543Smrg FILL_RECT(infoRec->pScrn, x, y, dx, dy); 321706f2543Smrg } else { 322706f2543Smrg l = ((double) lw) / 2.0; 323706f2543Smrg L = sqrt((double)(dx*dx + dy*dy)); 324706f2543Smrg 325706f2543Smrg if (dx < 0) { 326706f2543Smrg right = &rights[1]; 327706f2543Smrg left = &lefts[0]; 328706f2543Smrg top = &rights[0]; 329706f2543Smrg bottom = &lefts[1]; 330706f2543Smrg } else { 331706f2543Smrg right = &rights[0]; 332706f2543Smrg left = &lefts[1]; 333706f2543Smrg top = &lefts[0]; 334706f2543Smrg bottom = &rights[1]; 335706f2543Smrg } 336706f2543Smrg r = l / L; 337706f2543Smrg 338706f2543Smrg /* coord of upper bound at integral y */ 339706f2543Smrg ya = -r * dx; 340706f2543Smrg xa = r * dy; 341706f2543Smrg 342706f2543Smrg projectXoff = -ya; 343706f2543Smrg projectYoff = xa; 344706f2543Smrg 345706f2543Smrg /* xa * dy - ya * dx */ 346706f2543Smrg k = l * L; 347706f2543Smrg 348706f2543Smrg leftFace->xa = xa; 349706f2543Smrg leftFace->ya = ya; 350706f2543Smrg leftFace->k = k; 351706f2543Smrg rightFace->xa = -xa; 352706f2543Smrg rightFace->ya = -ya; 353706f2543Smrg rightFace->k = k; 354706f2543Smrg 355706f2543Smrg if (projectLeft) 356706f2543Smrg righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 357706f2543Smrg k, dx, dy, x1, y1, 0, right); 358706f2543Smrg else 359706f2543Smrg righty = miPolyBuildEdge (xa, ya, 360706f2543Smrg k, dx, dy, x1, y1, 0, right); 361706f2543Smrg 362706f2543Smrg /* coord of lower bound at integral y */ 363706f2543Smrg ya = -ya; 364706f2543Smrg xa = -xa; 365706f2543Smrg 366706f2543Smrg /* xa * dy - ya * dx */ 367706f2543Smrg k = - k; 368706f2543Smrg 369706f2543Smrg if (projectLeft) 370706f2543Smrg lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 371706f2543Smrg k, dx, dy, x1, y1, 1, left); 372706f2543Smrg else 373706f2543Smrg lefty = miPolyBuildEdge (xa, ya, 374706f2543Smrg k, dx, dy, x1, y1, 1, left); 375706f2543Smrg 376706f2543Smrg /* coord of top face at integral y */ 377706f2543Smrg 378706f2543Smrg if (signdx > 0) { 379706f2543Smrg ya = -ya; 380706f2543Smrg xa = -xa; 381706f2543Smrg } 382706f2543Smrg 383706f2543Smrg if (projectLeft) { 384706f2543Smrg double xap = xa - projectXoff; 385706f2543Smrg double yap = ya - projectYoff; 386706f2543Smrg topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 387706f2543Smrg -dy, dx, x1, y1, dx > 0, top); 388706f2543Smrg } 389706f2543Smrg else 390706f2543Smrg topy = miPolyBuildEdge(xa, ya, 0.0, 391706f2543Smrg -dy, dx, x1, y1, dx > 0, top); 392706f2543Smrg 393706f2543Smrg /* coord of bottom face at integral y */ 394706f2543Smrg 395706f2543Smrg if (projectRight) { 396706f2543Smrg double xap = xa + projectXoff; 397706f2543Smrg double yap = ya + projectYoff; 398706f2543Smrg bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 399706f2543Smrg -dy, dx, x2, y2, dx < 0, bottom); 400706f2543Smrg maxy = -ya + projectYoff; 401706f2543Smrg } else { 402706f2543Smrg bottomy = miPolyBuildEdge (xa, ya, 0.0, 403706f2543Smrg -dy, dx, x2, y2, dx < 0, bottom); 404706f2543Smrg maxy = -ya; 405706f2543Smrg } 406706f2543Smrg 407706f2543Smrg finaly = ICEIL (maxy) + y2; 408706f2543Smrg 409706f2543Smrg if (dx < 0) { 410706f2543Smrg left->height = bottomy - lefty; 411706f2543Smrg right->height = finaly - righty; 412706f2543Smrg top->height = righty - topy; 413706f2543Smrg } else { 414706f2543Smrg right->height = bottomy - righty; 415706f2543Smrg left->height = finaly - lefty; 416706f2543Smrg top->height = lefty - topy; 417706f2543Smrg } 418706f2543Smrg bottom->height = finaly - bottomy; 419706f2543Smrg XAAFillPolyHelper (pGC, topy, 420706f2543Smrg bottom->height + bottomy - topy, lefts, rights, 2, 2); 421706f2543Smrg } 422706f2543Smrg} 423706f2543Smrg 424706f2543Smrg 425706f2543Smrgstatic void 426706f2543SmrgXAALineArcI (GCPtr pGC, int xorg, int yorg) 427706f2543Smrg{ 428706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 429706f2543Smrg int x, y, e, ex; 430706f2543Smrg int slw = pGC->lineWidth; 431706f2543Smrg Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 432706f2543Smrg 433706f2543Smrg y = (slw >> 1) + 1; 434706f2543Smrg if (slw & 1) 435706f2543Smrg e = - ((y << 2) + 3); 436706f2543Smrg else 437706f2543Smrg e = - (y << 3); 438706f2543Smrg ex = -4; 439706f2543Smrg x = 0; 440706f2543Smrg while (y) { 441706f2543Smrg e += (y << 3) - 4; 442706f2543Smrg while (e >= 0) { 443706f2543Smrg x++; 444706f2543Smrg e += (ex = -((x << 3) + 4)); 445706f2543Smrg } 446706f2543Smrg y--; 447706f2543Smrg slw = (x << 1) + 1; 448706f2543Smrg if ((e == ex) && (slw > 1)) 449706f2543Smrg slw--; 450706f2543Smrg 451706f2543Smrg FILL_SPAN(infoRec->pScrn, xorg - x, yorg - y, slw); 452706f2543Smrg 453706f2543Smrg if ((y != 0) && ((slw > 1) || (e != ex))) { 454706f2543Smrg FILL_SPAN(infoRec->pScrn, xorg - x, yorg + y, slw); 455706f2543Smrg } 456706f2543Smrg } 457706f2543Smrg} 458706f2543Smrg 459706f2543Smrg 460706f2543Smrgstatic void 461706f2543SmrgXAALineArcD ( 462706f2543Smrg GCPtr pGC, 463706f2543Smrg double xorg, 464706f2543Smrg double yorg, 465706f2543Smrg PolyEdgePtr edge1, 466706f2543Smrg int edgey1, 467706f2543Smrg Bool edgeleft1, 468706f2543Smrg PolyEdgePtr edge2, 469706f2543Smrg int edgey2, 470706f2543Smrg Bool edgeleft2 ) 471706f2543Smrg{ 472706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 473706f2543Smrg double radius, x0, y0, el, er, yk, xlk, xrk, k; 474706f2543Smrg int xbase, ybase, y, boty, xl, xr, xcl, xcr; 475706f2543Smrg int ymin, ymax; 476706f2543Smrg Bool edge1IsMin, edge2IsMin; 477706f2543Smrg int ymin1, ymin2; 478706f2543Smrg Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 479706f2543Smrg 480706f2543Smrg 481706f2543Smrg xbase = floor(xorg); 482706f2543Smrg x0 = xorg - xbase; 483706f2543Smrg ybase = ICEIL (yorg); 484706f2543Smrg y0 = yorg - ybase; 485706f2543Smrg 486706f2543Smrg xlk = x0 + x0 + 1.0; 487706f2543Smrg xrk = x0 + x0 - 1.0; 488706f2543Smrg yk = y0 + y0 - 1.0; 489706f2543Smrg radius = ((double)pGC->lineWidth) / 2.0; 490706f2543Smrg y = floor(radius - y0 + 1.0); 491706f2543Smrg ybase -= y; 492706f2543Smrg ymin = ybase; 493706f2543Smrg ymax = 65536; 494706f2543Smrg edge1IsMin = FALSE; 495706f2543Smrg ymin1 = edgey1; 496706f2543Smrg if (edge1->dy >= 0) { 497706f2543Smrg if (!edge1->dy) { 498706f2543Smrg if (edgeleft1) 499706f2543Smrg edge1IsMin = TRUE; 500706f2543Smrg else 501706f2543Smrg ymax = edgey1; 502706f2543Smrg edgey1 = 65536; 503706f2543Smrg } else if ((edge1->signdx < 0) == edgeleft1) 504706f2543Smrg edge1IsMin = TRUE; 505706f2543Smrg } 506706f2543Smrg edge2IsMin = FALSE; 507706f2543Smrg ymin2 = edgey2; 508706f2543Smrg if (edge2->dy >= 0) { 509706f2543Smrg if (!edge2->dy) { 510706f2543Smrg if (edgeleft2) 511706f2543Smrg edge2IsMin = TRUE; 512706f2543Smrg else 513706f2543Smrg ymax = edgey2; 514706f2543Smrg edgey2 = 65536; 515706f2543Smrg } else if ((edge2->signdx < 0) == edgeleft2) 516706f2543Smrg edge2IsMin = TRUE; 517706f2543Smrg } 518706f2543Smrg if (edge1IsMin) { 519706f2543Smrg ymin = ymin1; 520706f2543Smrg if (edge2IsMin && (ymin1 > ymin2)) 521706f2543Smrg ymin = ymin2; 522706f2543Smrg } else if (edge2IsMin) 523706f2543Smrg ymin = ymin2; 524706f2543Smrg el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0); 525706f2543Smrg er = el + xrk; 526706f2543Smrg xl = 1; 527706f2543Smrg xr = 0; 528706f2543Smrg if (x0 < 0.5) { 529706f2543Smrg xl = 0; 530706f2543Smrg el -= xlk; 531706f2543Smrg } 532706f2543Smrg boty = (y0 < -0.5) ? 1 : 0; 533706f2543Smrg if (ybase + y - boty > ymax) 534706f2543Smrg boty = ymax - ybase - y; 535706f2543Smrg while (y > boty) { 536706f2543Smrg k = (y << 1) + yk; 537706f2543Smrg er += k; 538706f2543Smrg while (er > 0.0) { 539706f2543Smrg xr++; 540706f2543Smrg er += xrk - (xr << 1); 541706f2543Smrg } 542706f2543Smrg el += k; 543706f2543Smrg while (el >= 0.0) { 544706f2543Smrg xl--; 545706f2543Smrg el += (xl << 1) - xlk; 546706f2543Smrg } 547706f2543Smrg y--; 548706f2543Smrg ybase++; 549706f2543Smrg if (ybase < ymin) 550706f2543Smrg continue; 551706f2543Smrg xcl = xl + xbase; 552706f2543Smrg xcr = xr + xbase; 553706f2543Smrg CLIPSTEPEDGE(edgey1, edge1, edgeleft1); 554706f2543Smrg CLIPSTEPEDGE(edgey2, edge2, edgeleft2); 555706f2543Smrg if(xcr >= xcl) { 556706f2543Smrg FILL_SPAN(infoRec->pScrn, xcl, ybase, xcr - xcl + 1); 557706f2543Smrg } 558706f2543Smrg } 559706f2543Smrg er = xrk - (xr << 1) - er; 560706f2543Smrg el = (xl << 1) - xlk - el; 561706f2543Smrg boty = floor(-y0 - radius + 1.0); 562706f2543Smrg if (ybase + y - boty > ymax) 563706f2543Smrg boty = ymax - ybase - y; 564706f2543Smrg while (y > boty) { 565706f2543Smrg k = (y << 1) + yk; 566706f2543Smrg er -= k; 567706f2543Smrg while ((er >= 0.0) && (xr >= 0)) { 568706f2543Smrg xr--; 569706f2543Smrg er += xrk - (xr << 1); 570706f2543Smrg } 571706f2543Smrg el -= k; 572706f2543Smrg while ((el > 0.0) && (xl <= 0)) { 573706f2543Smrg xl++; 574706f2543Smrg el += (xl << 1) - xlk; 575706f2543Smrg } 576706f2543Smrg y--; 577706f2543Smrg ybase++; 578706f2543Smrg if (ybase < ymin) 579706f2543Smrg continue; 580706f2543Smrg xcl = xl + xbase; 581706f2543Smrg xcr = xr + xbase; 582706f2543Smrg CLIPSTEPEDGE(edgey1, edge1, edgeleft1); 583706f2543Smrg CLIPSTEPEDGE(edgey2, edge2, edgeleft2); 584706f2543Smrg if(xcr >= xcl) { 585706f2543Smrg FILL_SPAN(infoRec->pScrn, xcl, ybase, xcr - xcl + 1); 586706f2543Smrg } 587706f2543Smrg } 588706f2543Smrg} 589706f2543Smrg 590706f2543Smrg 591706f2543Smrgstatic void 592706f2543SmrgXAALineArc ( 593706f2543Smrg GCPtr pGC, 594706f2543Smrg LineFacePtr leftFace, 595706f2543Smrg LineFacePtr rightFace, 596706f2543Smrg double xorg, 597706f2543Smrg double yorg, 598706f2543Smrg Bool isInt ) 599706f2543Smrg{ 600706f2543Smrg int xorgi, yorgi; 601706f2543Smrg PolyEdgeRec edge1, edge2; 602706f2543Smrg int edgey1, edgey2; 603706f2543Smrg Bool edgeleft1, edgeleft2; 604706f2543Smrg 605706f2543Smrg if (isInt) { 606706f2543Smrg xorgi = leftFace ? leftFace->x : rightFace->x; 607706f2543Smrg yorgi = leftFace ? leftFace->y : rightFace->y; 608706f2543Smrg } else { /* Muffle compiler */ 609706f2543Smrg xorgi = yorgi = 0; 610706f2543Smrg } 611706f2543Smrg edgey1 = 65536; 612706f2543Smrg edgey2 = 65536; 613706f2543Smrg edge1.x = 0; /* not used, keep memory checkers happy */ 614706f2543Smrg edge1.dy = -1; 615706f2543Smrg edge2.x = 0; /* not used, keep memory checkers happy */ 616706f2543Smrg edge2.dy = -1; 617706f2543Smrg edgeleft1 = FALSE; 618706f2543Smrg edgeleft2 = FALSE; 619706f2543Smrg 620706f2543Smrg if ((pGC->lineWidth > 2) && 621706f2543Smrg ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) || 622706f2543Smrg (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))) { 623706f2543Smrg if (isInt) { 624706f2543Smrg xorg = (double) xorgi; 625706f2543Smrg yorg = (double) yorgi; 626706f2543Smrg } 627706f2543Smrg 628706f2543Smrg if (leftFace && rightFace) 629706f2543Smrg miRoundJoinClip (leftFace, rightFace, &edge1, &edge2, 630706f2543Smrg &edgey1, &edgey2, &edgeleft1, &edgeleft2); 631706f2543Smrg else if (leftFace) 632706f2543Smrg edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1); 633706f2543Smrg else if (rightFace) 634706f2543Smrg edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2); 635706f2543Smrg 636706f2543Smrg isInt = FALSE; 637706f2543Smrg } 638706f2543Smrg 639706f2543Smrg if (isInt) { 640706f2543Smrg if(pGC->lineWidth == 1) { 641706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 642706f2543Smrg Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 643706f2543Smrg DRAW_POINT(infoRec->pScrn, xorgi, yorgi); 644706f2543Smrg } else 645706f2543Smrg XAALineArcI(pGC, xorgi, yorgi); 646706f2543Smrg } else 647706f2543Smrg XAALineArcD(pGC, xorg, yorg, &edge1, edgey1, edgeleft1, 648706f2543Smrg &edge2, edgey2, edgeleft2); 649706f2543Smrg 650706f2543Smrg} 651706f2543Smrg 652706f2543Smrg 653706f2543Smrgstatic void 654706f2543SmrgXAALineJoin ( 655706f2543Smrg GCPtr pGC, 656706f2543Smrg LineFacePtr pLeft, 657706f2543Smrg LineFacePtr pRight ) 658706f2543Smrg{ 659706f2543Smrg double mx = 0, my = 0; 660706f2543Smrg double denom = 0; 661706f2543Smrg PolyVertexRec vertices[4]; 662706f2543Smrg PolySlopeRec slopes[4]; 663706f2543Smrg int edgecount; 664706f2543Smrg PolyEdgeRec left[4], right[4]; 665706f2543Smrg int nleft, nright; 666706f2543Smrg int y, height; 667706f2543Smrg int swapslopes; 668706f2543Smrg int joinStyle = pGC->joinStyle; 669706f2543Smrg int lw = pGC->lineWidth; 670706f2543Smrg 671706f2543Smrg if (lw == 1) { 672706f2543Smrg /* Lines going in the same direction have no join */ 673706f2543Smrg if ((pLeft->dx >= 0) == (pRight->dx <= 0)) 674706f2543Smrg return; 675706f2543Smrg if (joinStyle != JoinRound) { 676706f2543Smrg denom = - pLeft->dx * (double)pRight->dy + pRight->dx * 677706f2543Smrg (double)pLeft->dy; 678706f2543Smrg if (denom == 0.0) 679706f2543Smrg return; /* no join to draw */ 680706f2543Smrg } 681706f2543Smrg if (joinStyle != JoinMiter) { 682706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 683706f2543Smrg Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); 684706f2543Smrg DRAW_POINT(infoRec->pScrn, pLeft->x, pLeft->y); 685706f2543Smrg return; 686706f2543Smrg } 687706f2543Smrg } else { 688706f2543Smrg if (joinStyle == JoinRound) { 689706f2543Smrg XAALineArc(pGC, pLeft, pRight,(double)0.0, (double)0.0, TRUE); 690706f2543Smrg return; 691706f2543Smrg } 692706f2543Smrg denom = - pLeft->dx * (double)pRight->dy + pRight->dx * 693706f2543Smrg (double)pLeft->dy; 694706f2543Smrg if (denom == 0.0) 695706f2543Smrg return; /* no join to draw */ 696706f2543Smrg } 697706f2543Smrg 698706f2543Smrg swapslopes = 0; 699706f2543Smrg if (denom > 0) { 700706f2543Smrg pLeft->xa = -pLeft->xa; 701706f2543Smrg pLeft->ya = -pLeft->ya; 702706f2543Smrg pLeft->dx = -pLeft->dx; 703706f2543Smrg pLeft->dy = -pLeft->dy; 704706f2543Smrg } else { 705706f2543Smrg swapslopes = 1; 706706f2543Smrg pRight->xa = -pRight->xa; 707706f2543Smrg pRight->ya = -pRight->ya; 708706f2543Smrg pRight->dx = -pRight->dx; 709706f2543Smrg pRight->dy = -pRight->dy; 710706f2543Smrg } 711706f2543Smrg 712706f2543Smrg vertices[0].x = pRight->xa; 713706f2543Smrg vertices[0].y = pRight->ya; 714706f2543Smrg slopes[0].dx = -pRight->dy; 715706f2543Smrg slopes[0].dy = pRight->dx; 716706f2543Smrg slopes[0].k = 0; 717706f2543Smrg 718706f2543Smrg vertices[1].x = 0; 719706f2543Smrg vertices[1].y = 0; 720706f2543Smrg slopes[1].dx = pLeft->dy; 721706f2543Smrg slopes[1].dy = -pLeft->dx; 722706f2543Smrg slopes[1].k = 0; 723706f2543Smrg 724706f2543Smrg vertices[2].x = pLeft->xa; 725706f2543Smrg vertices[2].y = pLeft->ya; 726706f2543Smrg 727706f2543Smrg if (joinStyle == JoinMiter) { 728706f2543Smrg my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) - 729706f2543Smrg pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx ))/ 730706f2543Smrg denom; 731706f2543Smrg if (pLeft->dy != 0) 732706f2543Smrg mx = pLeft->xa + (my - pLeft->ya) * 733706f2543Smrg (double) pLeft->dx / (double) pLeft->dy; 734706f2543Smrg else 735706f2543Smrg mx = pRight->xa + (my - pRight->ya) * 736706f2543Smrg (double) pRight->dx / (double) pRight->dy; 737706f2543Smrg 738706f2543Smrg /* check miter limit */ 739706f2543Smrg if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw) 740706f2543Smrg joinStyle = JoinBevel; 741706f2543Smrg } 742706f2543Smrg 743706f2543Smrg if (joinStyle == JoinMiter) { 744706f2543Smrg slopes[2].dx = pLeft->dx; 745706f2543Smrg slopes[2].dy = pLeft->dy; 746706f2543Smrg slopes[2].k = pLeft->k; 747706f2543Smrg if (swapslopes) { 748706f2543Smrg slopes[2].dx = -slopes[2].dx; 749706f2543Smrg slopes[2].dy = -slopes[2].dy; 750706f2543Smrg slopes[2].k = -slopes[2].k; 751706f2543Smrg } 752706f2543Smrg vertices[3].x = mx; 753706f2543Smrg vertices[3].y = my; 754706f2543Smrg slopes[3].dx = pRight->dx; 755706f2543Smrg slopes[3].dy = pRight->dy; 756706f2543Smrg slopes[3].k = pRight->k; 757706f2543Smrg if (swapslopes) { 758706f2543Smrg slopes[3].dx = -slopes[3].dx; 759706f2543Smrg slopes[3].dy = -slopes[3].dy; 760706f2543Smrg slopes[3].k = -slopes[3].k; 761706f2543Smrg } 762706f2543Smrg edgecount = 4; 763706f2543Smrg } else { 764706f2543Smrg double scale, dx, dy, adx, ady; 765706f2543Smrg 766706f2543Smrg adx = dx = pRight->xa - pLeft->xa; 767706f2543Smrg ady = dy = pRight->ya - pLeft->ya; 768706f2543Smrg if (adx < 0) 769706f2543Smrg adx = -adx; 770706f2543Smrg if (ady < 0) 771706f2543Smrg ady = -ady; 772706f2543Smrg scale = ady; 773706f2543Smrg if (adx > ady) 774706f2543Smrg scale = adx; 775706f2543Smrg slopes[2].dx = (dx * 65536) / scale; 776706f2543Smrg slopes[2].dy = (dy * 65536) / scale; 777706f2543Smrg slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy - 778706f2543Smrg (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0; 779706f2543Smrg edgecount = 3; 780706f2543Smrg } 781706f2543Smrg 782706f2543Smrg y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y, 783706f2543Smrg left, right, &nleft, &nright, &height); 784706f2543Smrg XAAFillPolyHelper(pGC, y, height, left, right, nleft, nright); 785706f2543Smrg} 786706f2543Smrg 787706f2543Smrg 788706f2543Smrgvoid 789706f2543SmrgXAAPolylinesWideSolid ( 790706f2543Smrg DrawablePtr pDrawable, 791706f2543Smrg GCPtr pGC, 792706f2543Smrg int mode, 793706f2543Smrg int npt, 794706f2543Smrg DDXPointPtr pPts ) 795706f2543Smrg{ 796706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 797706f2543Smrg int x1, y1, x2, y2; 798706f2543Smrg Bool projectLeft, projectRight; 799706f2543Smrg LineFaceRec leftFace, rightFace, prevRightFace, firstFace; 800706f2543Smrg int first = TRUE; 801706f2543Smrg Bool somethingDrawn = FALSE; 802706f2543Smrg Bool selfJoin = FALSE; 803706f2543Smrg int xorg = pDrawable->x; 804706f2543Smrg int yorg = pDrawable->y; 805706f2543Smrg Bool hardClip = FALSE; 806706f2543Smrg 807706f2543Smrg if(!RegionNumRects(pGC->pCompositeClip)) 808706f2543Smrg return; 809706f2543Smrg 810706f2543Smrg if(RegionNumRects(pGC->pCompositeClip) != 1) { 811706f2543Smrg miWideLine(pDrawable, pGC, mode, npt, pPts); 812706f2543Smrg return; 813706f2543Smrg } 814706f2543Smrg 815706f2543Smrg x2 = pPts->x; 816706f2543Smrg y2 = pPts->y; 817706f2543Smrg if (npt > 1) { 818706f2543Smrg if (mode == CoordModePrevious) { 819706f2543Smrg int nptTmp; 820706f2543Smrg register DDXPointPtr pPtsTmp; 821706f2543Smrg 822706f2543Smrg x1 = x2; 823706f2543Smrg y1 = y2; 824706f2543Smrg nptTmp = npt; 825706f2543Smrg pPtsTmp = pPts + 1; 826706f2543Smrg while (--nptTmp) { 827706f2543Smrg x1 += pPtsTmp->x; 828706f2543Smrg y1 += pPtsTmp->y; 829706f2543Smrg ++pPtsTmp; 830706f2543Smrg } 831706f2543Smrg if ((x2 == x1) && (y2 == y1)) 832706f2543Smrg selfJoin = TRUE; 833706f2543Smrg } else if ((x2 == pPts[npt-1].x) && (y2 == pPts[npt-1].y)) 834706f2543Smrg selfJoin = TRUE; 835706f2543Smrg } 836706f2543Smrg 837706f2543Smrg projectLeft = ((pGC->capStyle == CapProjecting) && !selfJoin); 838706f2543Smrg projectRight = FALSE; 839706f2543Smrg 840706f2543Smrg (*infoRec->SetupForSolidFill)(infoRec->pScrn, pGC->fgPixel, pGC->alu, 841706f2543Smrg pGC->planemask); 842706f2543Smrg 843706f2543Smrg infoRec->ClipBox = &pGC->pCompositeClip->extents; 844706f2543Smrg 845706f2543Smrg if(infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL) { 846706f2543Smrg hardClip = TRUE; 847706f2543Smrg (*infoRec->SetClippingRectangle)(infoRec->pScrn, 848706f2543Smrg infoRec->ClipBox->x1, infoRec->ClipBox->y1, 849706f2543Smrg infoRec->ClipBox->x2 - 1, infoRec->ClipBox->y2 - 1); 850706f2543Smrg } 851706f2543Smrg 852706f2543Smrg x2 += xorg; 853706f2543Smrg y2 += yorg; 854706f2543Smrg while (--npt) { 855706f2543Smrg x1 = x2; 856706f2543Smrg y1 = y2; 857706f2543Smrg ++pPts; 858706f2543Smrg x2 = pPts->x; 859706f2543Smrg y2 = pPts->y; 860706f2543Smrg if (mode == CoordModePrevious) { 861706f2543Smrg x2 += x1; 862706f2543Smrg y2 += y1; 863706f2543Smrg } else { 864706f2543Smrg x2 += xorg; 865706f2543Smrg y2 += yorg; 866706f2543Smrg } 867706f2543Smrg if ((x1 != x2) || (y1 != y2)) { 868706f2543Smrg somethingDrawn = TRUE; 869706f2543Smrg if ((npt == 1) && (pGC->capStyle == CapProjecting) && !selfJoin) 870706f2543Smrg projectRight = TRUE; 871706f2543Smrg XAAWideSegment(pGC, x1, y1, x2, y2, 872706f2543Smrg projectLeft, projectRight, &leftFace, &rightFace); 873706f2543Smrg if (first) { 874706f2543Smrg if (selfJoin) 875706f2543Smrg firstFace = leftFace; 876706f2543Smrg else if (pGC->capStyle == CapRound) { 877706f2543Smrg if (pGC->lineWidth == 1) { 878706f2543Smrg DRAW_POINT(infoRec->pScrn, x1, y1); 879706f2543Smrg } else 880706f2543Smrg XAALineArc(pGC,&leftFace, (LineFacePtr) NULL, 881706f2543Smrg (double)0.0, (double)0.0,TRUE); 882706f2543Smrg } 883706f2543Smrg } else 884706f2543Smrg XAALineJoin (pGC, &leftFace, &prevRightFace); 885706f2543Smrg 886706f2543Smrg prevRightFace = rightFace; 887706f2543Smrg first = FALSE; 888706f2543Smrg projectLeft = FALSE; 889706f2543Smrg } 890706f2543Smrg if (npt == 1 && somethingDrawn) { 891706f2543Smrg if (selfJoin) 892706f2543Smrg XAALineJoin (pGC, &firstFace, &rightFace); 893706f2543Smrg else if (pGC->capStyle == CapRound) { 894706f2543Smrg if (pGC->lineWidth == 1) { 895706f2543Smrg DRAW_POINT(infoRec->pScrn, x2, y2); 896706f2543Smrg } else 897706f2543Smrg XAALineArc (pGC, (LineFacePtr) NULL, &rightFace, 898706f2543Smrg (double)0.0, (double)0.0,TRUE); 899706f2543Smrg } 900706f2543Smrg } 901706f2543Smrg } 902706f2543Smrg /* handle crock where all points are coincedent */ 903706f2543Smrg if (!somethingDrawn) { 904706f2543Smrg projectLeft = (pGC->capStyle == CapProjecting); 905706f2543Smrg XAAWideSegment (pGC, x2, y2, x2, y2, projectLeft, projectLeft, 906706f2543Smrg &leftFace, &rightFace); 907706f2543Smrg if (pGC->capStyle == CapRound) { 908706f2543Smrg XAALineArc (pGC, &leftFace, (LineFacePtr) NULL, 909706f2543Smrg (double)0.0, (double)0.0, TRUE); 910706f2543Smrg rightFace.dx = -1; /* sleezy hack to make it work */ 911706f2543Smrg XAALineArc (pGC, (LineFacePtr) NULL, &rightFace, 912706f2543Smrg (double)0.0, (double)0.0, TRUE); 913706f2543Smrg } 914706f2543Smrg } 915706f2543Smrg 916706f2543Smrg infoRec->ClipBox = NULL; 917706f2543Smrg if(hardClip) 918706f2543Smrg (*infoRec->DisableClipping)(infoRec->pScrn); 919706f2543Smrg 920706f2543Smrg SET_SYNC_FLAG(infoRec); 921706f2543Smrg} 922