First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / xaa / xaaWideLine.c
bloba684d667624efb0c7863fa0e0f2c6ad26ad6e974
1 /*
3 XAAPolylinesWideSolid does not maintain a span list and subsequently does
4 not follow the "touch-each-pixel-once" rules for wide lines and arcs.
5 This means it can only be used in the case where we have
6 miSpansEasyRop(pGC->alu). Since we clip spans on the fly, we
7 limited usage of this function to one rect situations. This
8 function is used only for solid lines.
10 Adapted from miWideLine by Mark Vojkovich (mvojkovi@ucsd.edu)
11 Original mi code written by Keith Packard.
15 #ifdef HAVE_XORG_CONFIG_H
16 #include <xorg-config.h>
17 #endif
19 #include <math.h>
21 #include "misc.h"
22 #include "xf86.h"
23 #include "xf86_OSproc.h"
25 #include <X11/X.h>
26 #include "windowstr.h"
27 #include "gcstruct.h"
28 #include "regionstr.h"
29 #include "miwideline.h"
30 #include "mi.h"
31 #include "xf86str.h"
32 #include "xaa.h"
33 #include "xaalocal.h"
35 #define DRAW_POINT(pScrn, x, y) \
36 if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, 1); \
37 else XAAPointHelper(pScrn, x, y)
39 #define FILL_RECT(pScrn, x, y, w, h) \
40 if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); \
41 else XAAFillRectHelper(pScrn, x, y, w, h)
43 #define FILL_SPAN(pScrn, x, y, w) \
44 if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, 1); \
45 else XAASpanHelper(pScrn, x, y, w)
48 #define CLIPSTEPEDGE(edgey,edge,edgeleft) \
49 if (ybase == edgey) { \
50 if (edgeleft) { \
51 if (edge->x > xcl) \
52 xcl = edge->x; \
53 } else { \
54 if (edge->x < xcr) \
55 xcr = edge->x; \
56 } \
57 edgey++; \
58 edge->x += edge->stepx; \
59 edge->e += edge->dx; \
60 if (edge->e > 0) { \
61 edge->x += edge->signdx; \
62 edge->e -= edge->dy; \
63 } \
66 static void
67 XAAPointHelper(ScrnInfoPtr pScrn, int x, int y)
69 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
70 BoxPtr extents = infoRec->ClipBox;
72 if((x >= extents->x1) && (x < extents->x2) &&
73 (y >= extents->y1) && (y < extents->y2))
74 (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, 1);
77 static void
78 XAAFillRectHelper(ScrnInfoPtr pScrn, int x1, int y1, int dx, int dy)
80 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
81 BoxPtr extents = infoRec->ClipBox;
82 int x2 = x1 + dx;
83 int y2 = y1 + dy;
85 if(x1 < extents->x1) x1 = extents->x1;
86 if(x2 >= extents->x2) x2 = extents->x2;
87 if((dx = x2 - x1)<1) return;
88 if(y1 < extents->y1) y1 = extents->y1;
89 if(y2 >= extents->y2) y2 = extents->y2;
90 if((dy = y2 - y1)<1) return;
92 (*infoRec->SubsequentSolidFillRect)(pScrn, x1, y1, dx, dy);
96 static void
97 XAASpanHelper(ScrnInfoPtr pScrn, int x1, int y, int width)
99 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
100 BoxPtr extents = infoRec->ClipBox;
101 int x2;
103 if((y < extents->y1) || (y >= extents->y2)) return;
105 x2 = x1 + width;
106 if(x1 < extents->x1) x1 = extents->x1;
107 if(x2 > extents->x2) x2 = extents->x2;
108 width = x2 - x1;
110 if(width > 0)
111 (*infoRec->SubsequentSolidFillRect)(pScrn, x1, y, width, 1);
115 #define FixError(x, dx, dy, e, sign, step, h) { \
116 e += (h) * dx; \
117 x += (h) * step; \
118 if(e > 0) { \
119 x += e * sign/dy; \
120 e %= dy; \
121 if(e) { \
122 x += sign; \
123 e -= dy; \
129 static void
130 XAAFillPolyHelper (
131 GCPtr pGC,
132 int y, /* start y coordinate */
133 int overall_height, /* height of entire segment */
134 PolyEdgePtr left, PolyEdgePtr right,
135 int left_count, int right_count )
137 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
138 BoxPtr extents = infoRec->ClipBox;
139 int left_x, left_e, left_stepx, left_signdx, left_dy, left_dx;
140 int right_x, right_e, right_stepx, right_signdx, right_dy, right_dx;
141 int height, left_height, right_height;
142 int xorg;
143 Bool hardClip;
145 if((y >= extents->y2) || ((y + overall_height) <= extents->y1))
146 return;
148 /* Muffle compiler */
149 left_x = left_e = left_stepx = left_signdx = left_dy = left_dx = 0;
150 right_x = right_e = right_stepx = right_signdx = right_dy = right_dx = 0;
152 left_height = right_height = 0;
153 xorg = 0;
155 hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
157 while ((left_count || left_height) && (right_count || right_height)) {
158 if (!left_height && left_count) {
159 left_height = left->height;
160 left_x = left->x + xorg;
161 left_stepx = left->stepx;
162 left_signdx = left->signdx;
163 left_e = left->e;
164 left_dy = left->dy;
165 left_dx = left->dx;
166 left_count--;
167 left++;
169 if (!right_height && right_count) {
170 right_height = right->height;
171 right_x = right->x + xorg + 1;
172 right_stepx = right->stepx;
173 right_signdx = right->signdx;
174 right_e = right->e;
175 right_dy = right->dy;
176 right_dx = right->dx;
177 right_count--;
178 right++;
181 height = (left_height > right_height) ? right_height : left_height;
183 left_height -= height;
184 right_height -= height;
186 if(hardClip && infoRec->SubsequentSolidFillTrap && (height > 6)) {
187 int right_DX, left_DX;
189 right_DX = (right_dx * right_signdx) + (right_stepx * right_dy);
190 left_DX = (left_dx * left_signdx) + (left_stepx * left_dy);
192 (*infoRec->SubsequentSolidFillTrap)(infoRec->pScrn, y, height,
193 left_x, left_DX, left_dy, left_e,
194 right_x - 1, right_DX, right_dy, right_e);
196 FixError(left_x, left_dx, left_dy, left_e, left_signdx,
197 left_stepx, height);
198 FixError(right_x, right_dx, right_dy, right_e, right_signdx,
199 right_stepx, height);
200 y += height;
201 continue;
204 while (height--) {
205 if(right_x > left_x) {
206 FILL_SPAN(infoRec->pScrn, left_x, y, right_x - left_x);
208 y++;
210 left_x += left_stepx;
211 left_e += left_dx;
212 if (left_e > 0) {
213 left_x += left_signdx;
214 left_e -= left_dy;
216 right_x += right_stepx;
217 right_e += right_dx;
218 if (right_e > 0) {
219 right_x += right_signdx;
220 right_e -= right_dy;
229 static void
230 XAAWideSegment (
231 GCPtr pGC,
232 int x1, int y1, int x2, int y2,
233 Bool projectLeft, Bool projectRight,
234 LineFacePtr leftFace, LineFacePtr rightFace )
236 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
237 double l, L, r;
238 double xa, ya;
239 double projectXoff, projectYoff;
240 double k;
241 double maxy;
242 int x, y;
243 int dx, dy;
244 int finaly;
245 PolyEdgePtr left, right;
246 PolyEdgePtr top, bottom;
247 int lefty, righty, topy, bottomy;
248 int signdx;
249 PolyEdgeRec lefts[2], rights[2];
250 LineFacePtr tface;
251 int lw = pGC->lineWidth;
252 Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
254 /* draw top-to-bottom always */
255 if ((y2 < y1) || ((y2 == y1) && (x2 < x1))) {
256 x = x1;
257 x1 = x2;
258 x2 = x;
260 y = y1;
261 y1 = y2;
262 y2 = y;
264 x = projectLeft;
265 projectLeft = projectRight;
266 projectRight = x;
268 tface = leftFace;
269 leftFace = rightFace;
270 rightFace = tface;
273 dy = y2 - y1;
274 signdx = 1;
275 dx = x2 - x1;
276 if (dx < 0)
277 signdx = -1;
279 leftFace->x = x1;
280 leftFace->y = y1;
281 leftFace->dx = dx;
282 leftFace->dy = dy;
284 rightFace->x = x2;
285 rightFace->y = y2;
286 rightFace->dx = -dx;
287 rightFace->dy = -dy;
289 if (!dy) {
290 rightFace->xa = 0;
291 rightFace->ya = (double) lw / 2.0;
292 rightFace->k = -(double) (lw * dx) / 2.0;
293 leftFace->xa = 0;
294 leftFace->ya = -rightFace->ya;
295 leftFace->k = rightFace->k;
296 x = x1;
297 if (projectLeft)
298 x -= (lw >> 1);
299 y = y1 - (lw >> 1);
300 dx = x2 - x;
301 if (projectRight)
302 dx += ((lw + 1) >> 1);
303 dy = lw;
304 FILL_RECT(infoRec->pScrn, x, y, dx, dy);
305 } else if (!dx) {
306 leftFace->xa = (double) lw / 2.0;
307 leftFace->ya = 0;
308 leftFace->k = (double) (lw * dy) / 2.0;
309 rightFace->xa = -leftFace->xa;
310 rightFace->ya = 0;
311 rightFace->k = leftFace->k;
312 y = y1;
313 if (projectLeft)
314 y -= lw >> 1;
315 x = x1 - (lw >> 1);
316 dy = y2 - y;
317 if (projectRight)
318 dy += ((lw + 1) >> 1);
319 dx = lw;
320 FILL_RECT(infoRec->pScrn, x, y, dx, dy);
321 } else {
322 l = ((double) lw) / 2.0;
323 L = sqrt((double)(dx*dx + dy*dy));
325 if (dx < 0) {
326 right = &rights[1];
327 left = &lefts[0];
328 top = &rights[0];
329 bottom = &lefts[1];
330 } else {
331 right = &rights[0];
332 left = &lefts[1];
333 top = &lefts[0];
334 bottom = &rights[1];
336 r = l / L;
338 /* coord of upper bound at integral y */
339 ya = -r * dx;
340 xa = r * dy;
342 projectXoff = -ya;
343 projectYoff = xa;
345 /* xa * dy - ya * dx */
346 k = l * L;
348 leftFace->xa = xa;
349 leftFace->ya = ya;
350 leftFace->k = k;
351 rightFace->xa = -xa;
352 rightFace->ya = -ya;
353 rightFace->k = k;
355 if (projectLeft)
356 righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
357 k, dx, dy, x1, y1, 0, right);
358 else
359 righty = miPolyBuildEdge (xa, ya,
360 k, dx, dy, x1, y1, 0, right);
362 /* coord of lower bound at integral y */
363 ya = -ya;
364 xa = -xa;
366 /* xa * dy - ya * dx */
367 k = - k;
369 if (projectLeft)
370 lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
371 k, dx, dy, x1, y1, 1, left);
372 else
373 lefty = miPolyBuildEdge (xa, ya,
374 k, dx, dy, x1, y1, 1, left);
376 /* coord of top face at integral y */
378 if (signdx > 0) {
379 ya = -ya;
380 xa = -xa;
383 if (projectLeft) {
384 double xap = xa - projectXoff;
385 double yap = ya - projectYoff;
386 topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
387 -dy, dx, x1, y1, dx > 0, top);
389 else
390 topy = miPolyBuildEdge(xa, ya, 0.0,
391 -dy, dx, x1, y1, dx > 0, top);
393 /* coord of bottom face at integral y */
395 if (projectRight) {
396 double xap = xa + projectXoff;
397 double yap = ya + projectYoff;
398 bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
399 -dy, dx, x2, y2, dx < 0, bottom);
400 maxy = -ya + projectYoff;
401 } else {
402 bottomy = miPolyBuildEdge (xa, ya, 0.0,
403 -dy, dx, x2, y2, dx < 0, bottom);
404 maxy = -ya;
407 finaly = ICEIL (maxy) + y2;
409 if (dx < 0) {
410 left->height = bottomy - lefty;
411 right->height = finaly - righty;
412 top->height = righty - topy;
413 } else {
414 right->height = bottomy - righty;
415 left->height = finaly - lefty;
416 top->height = lefty - topy;
418 bottom->height = finaly - bottomy;
419 XAAFillPolyHelper (pGC, topy,
420 bottom->height + bottomy - topy, lefts, rights, 2, 2);
425 static void
426 XAALineArcI (GCPtr pGC, int xorg, int yorg)
428 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
429 int x, y, e, ex;
430 int slw = pGC->lineWidth;
431 Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
433 y = (slw >> 1) + 1;
434 if (slw & 1)
435 e = - ((y << 2) + 3);
436 else
437 e = - (y << 3);
438 ex = -4;
439 x = 0;
440 while (y) {
441 e += (y << 3) - 4;
442 while (e >= 0) {
443 x++;
444 e += (ex = -((x << 3) + 4));
446 y--;
447 slw = (x << 1) + 1;
448 if ((e == ex) && (slw > 1))
449 slw--;
451 FILL_SPAN(infoRec->pScrn, xorg - x, yorg - y, slw);
453 if ((y != 0) && ((slw > 1) || (e != ex))) {
454 FILL_SPAN(infoRec->pScrn, xorg - x, yorg + y, slw);
460 static void
461 XAALineArcD (
462 GCPtr pGC,
463 double xorg,
464 double yorg,
465 PolyEdgePtr edge1,
466 int edgey1,
467 Bool edgeleft1,
468 PolyEdgePtr edge2,
469 int edgey2,
470 Bool edgeleft2 )
472 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
473 double radius, x0, y0, el, er, yk, xlk, xrk, k;
474 int xbase, ybase, y, boty, xl, xr, xcl, xcr;
475 int ymin, ymax;
476 Bool edge1IsMin, edge2IsMin;
477 int ymin1, ymin2;
478 Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
481 xbase = floor(xorg);
482 x0 = xorg - xbase;
483 ybase = ICEIL (yorg);
484 y0 = yorg - ybase;
486 xlk = x0 + x0 + 1.0;
487 xrk = x0 + x0 - 1.0;
488 yk = y0 + y0 - 1.0;
489 radius = ((double)pGC->lineWidth) / 2.0;
490 y = floor(radius - y0 + 1.0);
491 ybase -= y;
492 ymin = ybase;
493 ymax = 65536;
494 edge1IsMin = FALSE;
495 ymin1 = edgey1;
496 if (edge1->dy >= 0) {
497 if (!edge1->dy) {
498 if (edgeleft1)
499 edge1IsMin = TRUE;
500 else
501 ymax = edgey1;
502 edgey1 = 65536;
503 } else if ((edge1->signdx < 0) == edgeleft1)
504 edge1IsMin = TRUE;
506 edge2IsMin = FALSE;
507 ymin2 = edgey2;
508 if (edge2->dy >= 0) {
509 if (!edge2->dy) {
510 if (edgeleft2)
511 edge2IsMin = TRUE;
512 else
513 ymax = edgey2;
514 edgey2 = 65536;
515 } else if ((edge2->signdx < 0) == edgeleft2)
516 edge2IsMin = TRUE;
518 if (edge1IsMin) {
519 ymin = ymin1;
520 if (edge2IsMin && (ymin1 > ymin2))
521 ymin = ymin2;
522 } else if (edge2IsMin)
523 ymin = ymin2;
524 el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0);
525 er = el + xrk;
526 xl = 1;
527 xr = 0;
528 if (x0 < 0.5) {
529 xl = 0;
530 el -= xlk;
532 boty = (y0 < -0.5) ? 1 : 0;
533 if (ybase + y - boty > ymax)
534 boty = ymax - ybase - y;
535 while (y > boty) {
536 k = (y << 1) + yk;
537 er += k;
538 while (er > 0.0) {
539 xr++;
540 er += xrk - (xr << 1);
542 el += k;
543 while (el >= 0.0) {
544 xl--;
545 el += (xl << 1) - xlk;
547 y--;
548 ybase++;
549 if (ybase < ymin)
550 continue;
551 xcl = xl + xbase;
552 xcr = xr + xbase;
553 CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
554 CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
555 if(xcr >= xcl) {
556 FILL_SPAN(infoRec->pScrn, xcl, ybase, xcr - xcl + 1);
559 er = xrk - (xr << 1) - er;
560 el = (xl << 1) - xlk - el;
561 boty = floor(-y0 - radius + 1.0);
562 if (ybase + y - boty > ymax)
563 boty = ymax - ybase - y;
564 while (y > boty) {
565 k = (y << 1) + yk;
566 er -= k;
567 while ((er >= 0.0) && (xr >= 0)) {
568 xr--;
569 er += xrk - (xr << 1);
571 el -= k;
572 while ((el > 0.0) && (xl <= 0)) {
573 xl++;
574 el += (xl << 1) - xlk;
576 y--;
577 ybase++;
578 if (ybase < ymin)
579 continue;
580 xcl = xl + xbase;
581 xcr = xr + xbase;
582 CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
583 CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
584 if(xcr >= xcl) {
585 FILL_SPAN(infoRec->pScrn, xcl, ybase, xcr - xcl + 1);
591 static void
592 XAALineArc (
593 GCPtr pGC,
594 LineFacePtr leftFace,
595 LineFacePtr rightFace,
596 double xorg,
597 double yorg,
598 Bool isInt )
600 int xorgi, yorgi;
601 PolyEdgeRec edge1, edge2;
602 int edgey1, edgey2;
603 Bool edgeleft1, edgeleft2;
605 if (isInt) {
606 xorgi = leftFace ? leftFace->x : rightFace->x;
607 yorgi = leftFace ? leftFace->y : rightFace->y;
608 } else { /* Muffle compiler */
609 xorgi = yorgi = 0;
611 edgey1 = 65536;
612 edgey2 = 65536;
613 edge1.x = 0; /* not used, keep memory checkers happy */
614 edge1.dy = -1;
615 edge2.x = 0; /* not used, keep memory checkers happy */
616 edge2.dy = -1;
617 edgeleft1 = FALSE;
618 edgeleft2 = FALSE;
620 if ((pGC->lineWidth > 2) &&
621 ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) ||
622 (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))) {
623 if (isInt) {
624 xorg = (double) xorgi;
625 yorg = (double) yorgi;
628 if (leftFace && rightFace)
629 miRoundJoinClip (leftFace, rightFace, &edge1, &edge2,
630 &edgey1, &edgey2, &edgeleft1, &edgeleft2);
631 else if (leftFace)
632 edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1);
633 else if (rightFace)
634 edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2);
636 isInt = FALSE;
639 if (isInt) {
640 if(pGC->lineWidth == 1) {
641 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
642 Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
643 DRAW_POINT(infoRec->pScrn, xorgi, yorgi);
644 } else
645 XAALineArcI(pGC, xorgi, yorgi);
646 } else
647 XAALineArcD(pGC, xorg, yorg, &edge1, edgey1, edgeleft1,
648 &edge2, edgey2, edgeleft2);
653 static void
654 XAALineJoin (
655 GCPtr pGC,
656 LineFacePtr pLeft,
657 LineFacePtr pRight )
659 double mx = 0, my = 0;
660 double denom = 0;
661 PolyVertexRec vertices[4];
662 PolySlopeRec slopes[4];
663 int edgecount;
664 PolyEdgeRec left[4], right[4];
665 int nleft, nright;
666 int y, height;
667 int swapslopes;
668 int joinStyle = pGC->joinStyle;
669 int lw = pGC->lineWidth;
671 if (lw == 1) {
672 /* Lines going in the same direction have no join */
673 if ((pLeft->dx >= 0) == (pRight->dx <= 0))
674 return;
675 if (joinStyle != JoinRound) {
676 denom = - pLeft->dx * (double)pRight->dy + pRight->dx *
677 (double)pLeft->dy;
678 if (denom == 0.0)
679 return; /* no join to draw */
681 if (joinStyle != JoinMiter) {
682 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
683 Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
684 DRAW_POINT(infoRec->pScrn, pLeft->x, pLeft->y);
685 return;
687 } else {
688 if (joinStyle == JoinRound) {
689 XAALineArc(pGC, pLeft, pRight,(double)0.0, (double)0.0, TRUE);
690 return;
692 denom = - pLeft->dx * (double)pRight->dy + pRight->dx *
693 (double)pLeft->dy;
694 if (denom == 0.0)
695 return; /* no join to draw */
698 swapslopes = 0;
699 if (denom > 0) {
700 pLeft->xa = -pLeft->xa;
701 pLeft->ya = -pLeft->ya;
702 pLeft->dx = -pLeft->dx;
703 pLeft->dy = -pLeft->dy;
704 } else {
705 swapslopes = 1;
706 pRight->xa = -pRight->xa;
707 pRight->ya = -pRight->ya;
708 pRight->dx = -pRight->dx;
709 pRight->dy = -pRight->dy;
712 vertices[0].x = pRight->xa;
713 vertices[0].y = pRight->ya;
714 slopes[0].dx = -pRight->dy;
715 slopes[0].dy = pRight->dx;
716 slopes[0].k = 0;
718 vertices[1].x = 0;
719 vertices[1].y = 0;
720 slopes[1].dx = pLeft->dy;
721 slopes[1].dy = -pLeft->dx;
722 slopes[1].k = 0;
724 vertices[2].x = pLeft->xa;
725 vertices[2].y = pLeft->ya;
727 if (joinStyle == JoinMiter) {
728 my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) -
729 pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx ))/
730 denom;
731 if (pLeft->dy != 0)
732 mx = pLeft->xa + (my - pLeft->ya) *
733 (double) pLeft->dx / (double) pLeft->dy;
734 else
735 mx = pRight->xa + (my - pRight->ya) *
736 (double) pRight->dx / (double) pRight->dy;
738 /* check miter limit */
739 if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw)
740 joinStyle = JoinBevel;
743 if (joinStyle == JoinMiter) {
744 slopes[2].dx = pLeft->dx;
745 slopes[2].dy = pLeft->dy;
746 slopes[2].k = pLeft->k;
747 if (swapslopes) {
748 slopes[2].dx = -slopes[2].dx;
749 slopes[2].dy = -slopes[2].dy;
750 slopes[2].k = -slopes[2].k;
752 vertices[3].x = mx;
753 vertices[3].y = my;
754 slopes[3].dx = pRight->dx;
755 slopes[3].dy = pRight->dy;
756 slopes[3].k = pRight->k;
757 if (swapslopes) {
758 slopes[3].dx = -slopes[3].dx;
759 slopes[3].dy = -slopes[3].dy;
760 slopes[3].k = -slopes[3].k;
762 edgecount = 4;
763 } else {
764 double scale, dx, dy, adx, ady;
766 adx = dx = pRight->xa - pLeft->xa;
767 ady = dy = pRight->ya - pLeft->ya;
768 if (adx < 0)
769 adx = -adx;
770 if (ady < 0)
771 ady = -ady;
772 scale = ady;
773 if (adx > ady)
774 scale = adx;
775 slopes[2].dx = (dx * 65536) / scale;
776 slopes[2].dy = (dy * 65536) / scale;
777 slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy -
778 (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0;
779 edgecount = 3;
782 y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y,
783 left, right, &nleft, &nright, &height);
784 XAAFillPolyHelper(pGC, y, height, left, right, nleft, nright);
788 void
789 XAAPolylinesWideSolid (
790 DrawablePtr pDrawable,
791 GCPtr pGC,
792 int mode,
793 int npt,
794 DDXPointPtr pPts )
796 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
797 int x1, y1, x2, y2;
798 Bool projectLeft, projectRight;
799 LineFaceRec leftFace, rightFace, prevRightFace, firstFace;
800 int first = TRUE;
801 Bool somethingDrawn = FALSE;
802 Bool selfJoin = FALSE;
803 int xorg = pDrawable->x;
804 int yorg = pDrawable->y;
805 Bool hardClip = FALSE;
807 if(!REGION_NUM_RECTS(pGC->pCompositeClip))
808 return;
810 if(REGION_NUM_RECTS(pGC->pCompositeClip) != 1) {
811 miWideLine(pDrawable, pGC, mode, npt, pPts);
812 return;
815 x2 = pPts->x;
816 y2 = pPts->y;
817 if (npt > 1) {
818 if (mode == CoordModePrevious) {
819 int nptTmp;
820 register DDXPointPtr pPtsTmp;
822 x1 = x2;
823 y1 = y2;
824 nptTmp = npt;
825 pPtsTmp = pPts + 1;
826 while (--nptTmp) {
827 x1 += pPtsTmp->x;
828 y1 += pPtsTmp->y;
829 ++pPtsTmp;
831 if ((x2 == x1) && (y2 == y1))
832 selfJoin = TRUE;
833 } else if ((x2 == pPts[npt-1].x) && (y2 == pPts[npt-1].y))
834 selfJoin = TRUE;
837 projectLeft = ((pGC->capStyle == CapProjecting) && !selfJoin);
838 projectRight = FALSE;
840 (*infoRec->SetupForSolidFill)(infoRec->pScrn, pGC->fgPixel, pGC->alu,
841 pGC->planemask);
843 infoRec->ClipBox = &pGC->pCompositeClip->extents;
845 if(infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL) {
846 hardClip = TRUE;
847 (*infoRec->SetClippingRectangle)(infoRec->pScrn,
848 infoRec->ClipBox->x1, infoRec->ClipBox->y1,
849 infoRec->ClipBox->x2 - 1, infoRec->ClipBox->y2 - 1);
852 x2 += xorg;
853 y2 += yorg;
854 while (--npt) {
855 x1 = x2;
856 y1 = y2;
857 ++pPts;
858 x2 = pPts->x;
859 y2 = pPts->y;
860 if (mode == CoordModePrevious) {
861 x2 += x1;
862 y2 += y1;
863 } else {
864 x2 += xorg;
865 y2 += yorg;
867 if ((x1 != x2) || (y1 != y2)) {
868 somethingDrawn = TRUE;
869 if ((npt == 1) && (pGC->capStyle == CapProjecting) && !selfJoin)
870 projectRight = TRUE;
871 XAAWideSegment(pGC, x1, y1, x2, y2,
872 projectLeft, projectRight, &leftFace, &rightFace);
873 if (first) {
874 if (selfJoin)
875 firstFace = leftFace;
876 else if (pGC->capStyle == CapRound) {
877 if (pGC->lineWidth == 1) {
878 DRAW_POINT(infoRec->pScrn, x1, y1);
879 } else
880 XAALineArc(pGC,&leftFace, (LineFacePtr) NULL,
881 (double)0.0, (double)0.0,TRUE);
883 } else
884 XAALineJoin (pGC, &leftFace, &prevRightFace);
886 prevRightFace = rightFace;
887 first = FALSE;
888 projectLeft = FALSE;
890 if (npt == 1 && somethingDrawn) {
891 if (selfJoin)
892 XAALineJoin (pGC, &firstFace, &rightFace);
893 else if (pGC->capStyle == CapRound) {
894 if (pGC->lineWidth == 1) {
895 DRAW_POINT(infoRec->pScrn, x2, y2);
896 } else
897 XAALineArc (pGC, (LineFacePtr) NULL, &rightFace,
898 (double)0.0, (double)0.0,TRUE);
902 /* handle crock where all points are coincedent */
903 if (!somethingDrawn) {
904 projectLeft = (pGC->capStyle == CapProjecting);
905 XAAWideSegment (pGC, x2, y2, x2, y2, projectLeft, projectLeft,
906 &leftFace, &rightFace);
907 if (pGC->capStyle == CapRound) {
908 XAALineArc (pGC, &leftFace, (LineFacePtr) NULL,
909 (double)0.0, (double)0.0, TRUE);
910 rightFace.dx = -1; /* sleezy hack to make it work */
911 XAALineArc (pGC, (LineFacePtr) NULL, &rightFace,
912 (double)0.0, (double)0.0, TRUE);
916 infoRec->ClipBox = NULL;
917 if(hardClip)
918 (*infoRec->DisableClipping)(infoRec->pScrn);
920 SET_SYNC_FLAG(infoRec);