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>
23 #include "xf86_OSproc.h"
26 #include "windowstr.h"
28 #include "regionstr.h"
29 #include "miwideline.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) { \
58 edge->x += edge->stepx; \
59 edge->e += edge->dx; \
61 edge->x += edge->signdx; \
62 edge->e -= edge->dy; \
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);
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
;
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
);
97 XAASpanHelper(ScrnInfoPtr pScrn
, int x1
, int y
, int width
)
99 XAAInfoRecPtr infoRec
= GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn
);
100 BoxPtr extents
= infoRec
->ClipBox
;
103 if((y
< extents
->y1
) || (y
>= extents
->y2
)) return;
106 if(x1
< extents
->x1
) x1
= extents
->x1
;
107 if(x2
> extents
->x2
) x2
= extents
->x2
;
111 (*infoRec
->SubsequentSolidFillRect
)(pScrn
, x1
, y
, width
, 1);
115 #define FixError(x, dx, dy, e, sign, step, h) { \
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
;
145 if((y
>= extents
->y2
) || ((y
+ overall_height
) <= extents
->y1
))
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;
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
;
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
;
175 right_dy
= right
->dy
;
176 right_dx
= right
->dx
;
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
,
198 FixError(right_x
, right_dx
, right_dy
, right_e
, right_signdx
,
199 right_stepx
, height
);
205 if(right_x
> left_x
) {
206 FILL_SPAN(infoRec
->pScrn
, left_x
, y
, right_x
- left_x
);
210 left_x
+= left_stepx
;
213 left_x
+= left_signdx
;
216 right_x
+= right_stepx
;
219 right_x
+= right_signdx
;
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
);
239 double projectXoff
, projectYoff
;
245 PolyEdgePtr left
, right
;
246 PolyEdgePtr top
, bottom
;
247 int lefty
, righty
, topy
, bottomy
;
249 PolyEdgeRec lefts
[2], rights
[2];
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
))) {
265 projectLeft
= projectRight
;
269 leftFace
= rightFace
;
291 rightFace
->ya
= (double) lw
/ 2.0;
292 rightFace
->k
= -(double) (lw
* dx
) / 2.0;
294 leftFace
->ya
= -rightFace
->ya
;
295 leftFace
->k
= rightFace
->k
;
302 dx
+= ((lw
+ 1) >> 1);
304 FILL_RECT(infoRec
->pScrn
, x
, y
, dx
, dy
);
306 leftFace
->xa
= (double) lw
/ 2.0;
308 leftFace
->k
= (double) (lw
* dy
) / 2.0;
309 rightFace
->xa
= -leftFace
->xa
;
311 rightFace
->k
= leftFace
->k
;
318 dy
+= ((lw
+ 1) >> 1);
320 FILL_RECT(infoRec
->pScrn
, x
, y
, dx
, dy
);
322 l
= ((double) lw
) / 2.0;
323 L
= sqrt((double)(dx
*dx
+ dy
*dy
));
338 /* coord of upper bound at integral y */
345 /* xa * dy - ya * dx */
356 righty
= miPolyBuildEdge (xa
- projectXoff
, ya
- projectYoff
,
357 k
, dx
, dy
, x1
, y1
, 0, right
);
359 righty
= miPolyBuildEdge (xa
, ya
,
360 k
, dx
, dy
, x1
, y1
, 0, right
);
362 /* coord of lower bound at integral y */
366 /* xa * dy - ya * dx */
370 lefty
= miPolyBuildEdge (xa
- projectXoff
, ya
- projectYoff
,
371 k
, dx
, dy
, x1
, y1
, 1, left
);
373 lefty
= miPolyBuildEdge (xa
, ya
,
374 k
, dx
, dy
, x1
, y1
, 1, left
);
376 /* coord of top face at integral y */
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
);
390 topy
= miPolyBuildEdge(xa
, ya
, 0.0,
391 -dy
, dx
, x1
, y1
, dx
> 0, top
);
393 /* coord of bottom face at integral y */
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
;
402 bottomy
= miPolyBuildEdge (xa
, ya
, 0.0,
403 -dy
, dx
, x2
, y2
, dx
< 0, bottom
);
407 finaly
= ICEIL (maxy
) + y2
;
410 left
->height
= bottomy
- lefty
;
411 right
->height
= finaly
- righty
;
412 top
->height
= righty
- topy
;
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);
426 XAALineArcI (GCPtr pGC
, int xorg
, int yorg
)
428 XAAInfoRecPtr infoRec
= GET_XAAINFORECPTR_FROM_GC(pGC
);
430 int slw
= pGC
->lineWidth
;
431 Bool hardClip
= (infoRec
->ClippingFlags
& HARDWARE_CLIP_SOLID_FILL
);
435 e
= - ((y
<< 2) + 3);
444 e
+= (ex
= -((x
<< 3) + 4));
448 if ((e
== ex
) && (slw
> 1))
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
);
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
;
476 Bool edge1IsMin
, edge2IsMin
;
478 Bool hardClip
= (infoRec
->ClippingFlags
& HARDWARE_CLIP_SOLID_FILL
);
483 ybase
= ICEIL (yorg
);
489 radius
= ((double)pGC
->lineWidth
) / 2.0;
490 y
= floor(radius
- y0
+ 1.0);
496 if (edge1
->dy
>= 0) {
503 } else if ((edge1
->signdx
< 0) == edgeleft1
)
508 if (edge2
->dy
>= 0) {
515 } else if ((edge2
->signdx
< 0) == edgeleft2
)
520 if (edge2IsMin
&& (ymin1
> ymin2
))
522 } else if (edge2IsMin
)
524 el
= radius
* radius
- ((y
+ y0
) * (y
+ y0
)) - (x0
* x0
);
532 boty
= (y0
< -0.5) ? 1 : 0;
533 if (ybase
+ y
- boty
> ymax
)
534 boty
= ymax
- ybase
- y
;
540 er
+= xrk
- (xr
<< 1);
545 el
+= (xl
<< 1) - xlk
;
553 CLIPSTEPEDGE(edgey1
, edge1
, edgeleft1
);
554 CLIPSTEPEDGE(edgey2
, edge2
, edgeleft2
);
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
;
567 while ((er
>= 0.0) && (xr
>= 0)) {
569 er
+= xrk
- (xr
<< 1);
572 while ((el
> 0.0) && (xl
<= 0)) {
574 el
+= (xl
<< 1) - xlk
;
582 CLIPSTEPEDGE(edgey1
, edge1
, edgeleft1
);
583 CLIPSTEPEDGE(edgey2
, edge2
, edgeleft2
);
585 FILL_SPAN(infoRec
->pScrn
, xcl
, ybase
, xcr
- xcl
+ 1);
594 LineFacePtr leftFace
,
595 LineFacePtr rightFace
,
601 PolyEdgeRec edge1
, edge2
;
603 Bool edgeleft1
, edgeleft2
;
606 xorgi
= leftFace
? leftFace
->x
: rightFace
->x
;
607 yorgi
= leftFace
? leftFace
->y
: rightFace
->y
;
608 } else { /* Muffle compiler */
613 edge1
.x
= 0; /* not used, keep memory checkers happy */
615 edge2
.x
= 0; /* not used, keep memory checkers happy */
620 if ((pGC
->lineWidth
> 2) &&
621 ((pGC
->capStyle
== CapRound
&& pGC
->joinStyle
!= JoinRound
) ||
622 (pGC
->joinStyle
== JoinRound
&& pGC
->capStyle
== CapButt
))) {
624 xorg
= (double) xorgi
;
625 yorg
= (double) yorgi
;
628 if (leftFace
&& rightFace
)
629 miRoundJoinClip (leftFace
, rightFace
, &edge1
, &edge2
,
630 &edgey1
, &edgey2
, &edgeleft1
, &edgeleft2
);
632 edgey1
= miRoundCapClip (leftFace
, isInt
, &edge1
, &edgeleft1
);
634 edgey2
= miRoundCapClip (rightFace
, isInt
, &edge2
, &edgeleft2
);
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
);
645 XAALineArcI(pGC
, xorgi
, yorgi
);
647 XAALineArcD(pGC
, xorg
, yorg
, &edge1
, edgey1
, edgeleft1
,
648 &edge2
, edgey2
, edgeleft2
);
659 double mx
= 0, my
= 0;
661 PolyVertexRec vertices
[4];
662 PolySlopeRec slopes
[4];
664 PolyEdgeRec left
[4], right
[4];
668 int joinStyle
= pGC
->joinStyle
;
669 int lw
= pGC
->lineWidth
;
672 /* Lines going in the same direction have no join */
673 if ((pLeft
->dx
>= 0) == (pRight
->dx
<= 0))
675 if (joinStyle
!= JoinRound
) {
676 denom
= - pLeft
->dx
* (double)pRight
->dy
+ pRight
->dx
*
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
);
688 if (joinStyle
== JoinRound
) {
689 XAALineArc(pGC
, pLeft
, pRight
,(double)0.0, (double)0.0, TRUE
);
692 denom
= - pLeft
->dx
* (double)pRight
->dy
+ pRight
->dx
*
695 return; /* no join to draw */
700 pLeft
->xa
= -pLeft
->xa
;
701 pLeft
->ya
= -pLeft
->ya
;
702 pLeft
->dx
= -pLeft
->dx
;
703 pLeft
->dy
= -pLeft
->dy
;
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
;
720 slopes
[1].dx
= pLeft
->dy
;
721 slopes
[1].dy
= -pLeft
->dx
;
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
))/
732 mx
= pLeft
->xa
+ (my
- pLeft
->ya
) *
733 (double) pLeft
->dx
/ (double) pLeft
->dy
;
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
;
748 slopes
[2].dx
= -slopes
[2].dx
;
749 slopes
[2].dy
= -slopes
[2].dy
;
750 slopes
[2].k
= -slopes
[2].k
;
754 slopes
[3].dx
= pRight
->dx
;
755 slopes
[3].dy
= pRight
->dy
;
756 slopes
[3].k
= pRight
->k
;
758 slopes
[3].dx
= -slopes
[3].dx
;
759 slopes
[3].dy
= -slopes
[3].dy
;
760 slopes
[3].k
= -slopes
[3].k
;
764 double scale
, dx
, dy
, adx
, ady
;
766 adx
= dx
= pRight
->xa
- pLeft
->xa
;
767 ady
= dy
= pRight
->ya
- pLeft
->ya
;
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;
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
);
789 XAAPolylinesWideSolid (
790 DrawablePtr pDrawable
,
796 XAAInfoRecPtr infoRec
= GET_XAAINFORECPTR_FROM_GC(pGC
);
798 Bool projectLeft
, projectRight
;
799 LineFaceRec leftFace
, rightFace
, prevRightFace
, firstFace
;
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
))
810 if(REGION_NUM_RECTS(pGC
->pCompositeClip
) != 1) {
811 miWideLine(pDrawable
, pGC
, mode
, npt
, pPts
);
818 if (mode
== CoordModePrevious
) {
820 register DDXPointPtr pPtsTmp
;
831 if ((x2
== x1
) && (y2
== y1
))
833 } else if ((x2
== pPts
[npt
-1].x
) && (y2
== pPts
[npt
-1].y
))
837 projectLeft
= ((pGC
->capStyle
== CapProjecting
) && !selfJoin
);
838 projectRight
= FALSE
;
840 (*infoRec
->SetupForSolidFill
)(infoRec
->pScrn
, pGC
->fgPixel
, pGC
->alu
,
843 infoRec
->ClipBox
= &pGC
->pCompositeClip
->extents
;
845 if(infoRec
->ClippingFlags
& HARDWARE_CLIP_SOLID_FILL
) {
847 (*infoRec
->SetClippingRectangle
)(infoRec
->pScrn
,
848 infoRec
->ClipBox
->x1
, infoRec
->ClipBox
->y1
,
849 infoRec
->ClipBox
->x2
- 1, infoRec
->ClipBox
->y2
- 1);
860 if (mode
== CoordModePrevious
) {
867 if ((x1
!= x2
) || (y1
!= y2
)) {
868 somethingDrawn
= TRUE
;
869 if ((npt
== 1) && (pGC
->capStyle
== CapProjecting
) && !selfJoin
)
871 XAAWideSegment(pGC
, x1
, y1
, x2
, y2
,
872 projectLeft
, projectRight
, &leftFace
, &rightFace
);
875 firstFace
= leftFace
;
876 else if (pGC
->capStyle
== CapRound
) {
877 if (pGC
->lineWidth
== 1) {
878 DRAW_POINT(infoRec
->pScrn
, x1
, y1
);
880 XAALineArc(pGC
,&leftFace
, (LineFacePtr
) NULL
,
881 (double)0.0, (double)0.0,TRUE
);
884 XAALineJoin (pGC
, &leftFace
, &prevRightFace
);
886 prevRightFace
= rightFace
;
890 if (npt
== 1 && somethingDrawn
) {
892 XAALineJoin (pGC
, &firstFace
, &rightFace
);
893 else if (pGC
->capStyle
== CapRound
) {
894 if (pGC
->lineWidth
== 1) {
895 DRAW_POINT(infoRec
->pScrn
, x2
, y2
);
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
;
918 (*infoRec
->DisableClipping
)(infoRec
->pScrn
);
920 SET_SYNC_FLAG(infoRec
);