1/*
2
3XAAPolylinesWideSolid does not maintain a span list and subsequently does
4not follow the "touch-each-pixel-once" rules for wide lines and arcs.
5This means it can only be used in the case where we have
6miSpansEasyRop(pGC->alu).  Since we clip spans on the fly, we
7limited usage of this function to one rect situations. This
8function is used only for solid lines.
9
10  Adapted from miWideLine by Mark Vojkovich (mvojkovi@ucsd.edu)
11Original mi code written by Keith Packard.
12
13*/
14
15#ifdef HAVE_XORG_CONFIG_H
16#include <xorg-config.h>
17#endif
18
19#include <math.h>
20
21#include "misc.h"
22#include "xf86.h"
23#include "xf86_OSproc.h"
24
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"
34
35#define DRAW_POINT(pScrn, x, y) \
36  if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, 1); \
37  else XAAPointHelper(pScrn, x, y)
38
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)
42
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)
46
47
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	} \
64    }
65
66static void
67XAAPointHelper(ScrnInfoPtr pScrn, int x, int y)
68{
69   XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
70   BoxPtr extents = infoRec->ClipBox;
71
72   if((x >= extents->x1) && (x < extents->x2) &&
73	(y >= extents->y1) && (y < extents->y2))
74	(*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, 1);
75}
76
77static void
78XAAFillRectHelper(ScrnInfoPtr pScrn, int x1, int y1, int dx, int dy)
79{
80   XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
81   BoxPtr extents = infoRec->ClipBox;
82   int x2 = x1 + dx;
83   int y2 = y1 + dy;
84
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;
91
92   (*infoRec->SubsequentSolidFillRect)(pScrn, x1, y1, dx, dy);
93}
94
95
96static void
97XAASpanHelper(ScrnInfoPtr pScrn, int x1, int y, int width)
98{
99   XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
100   BoxPtr extents = infoRec->ClipBox;
101    int x2;
102
103    if((y < extents->y1) || (y >= extents->y2)) return;
104
105    x2 = x1 + width;
106    if(x1 < extents->x1) x1 = extents->x1;
107    if(x2 > extents->x2) x2 = extents->x2;
108    width = x2 - x1;
109
110    if(width > 0)
111 	(*infoRec->SubsequentSolidFillRect)(pScrn, x1, y, width, 1);
112
113}
114
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;				\
124		}					\
125	   } 	 					\
126}
127
128
129static void
130XAAFillPolyHelper (
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 )
136{
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;
144
145    if((y >= extents->y2) || ((y + overall_height) <= extents->y1))
146	return;
147
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;
151
152    left_height = right_height = 0;
153    xorg = 0;
154
155    hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL);
156
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++;
168	}
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++;
179	}
180
181	height = (left_height > right_height) ? right_height : left_height;
182
183	left_height -= height;
184	right_height -= height;
185
186	if(hardClip && infoRec->SubsequentSolidFillTrap && (height > 6)) {
187	    int right_DX, left_DX;
188
189    	    right_DX = (right_dx * right_signdx) + (right_stepx * right_dy);
190	    left_DX = (left_dx * left_signdx) + (left_stepx * left_dy);
191
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);
195
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;
202	}
203
204	while (height--) {
205	    if(right_x > left_x) {
206		FILL_SPAN(infoRec->pScrn, left_x, y, right_x - left_x);
207	    }
208    	    y++;
209
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;
215	    }
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;
221	    }
222
223	}
224    }
225}
226
227
228
229static void
230XAAWideSegment (
231    GCPtr pGC,
232    int  x1, int y1, int x2, int y2,
233    Bool projectLeft, Bool projectRight,
234    LineFacePtr leftFace, LineFacePtr rightFace )
235{
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);
253
254    /* draw top-to-bottom always */
255    if ((y2 < y1) || ((y2 == y1) && (x2 < x1))) {
256	x = x1;
257	x1 = x2;
258	x2 = x;
259
260	y = y1;
261	y1 = y2;
262	y2 = y;
263
264	x = projectLeft;
265	projectLeft = projectRight;
266	projectRight = x;
267
268	tface = leftFace;
269	leftFace = rightFace;
270	rightFace = tface;
271    }
272
273    dy = y2 - y1;
274    signdx = 1;
275    dx = x2 - x1;
276    if (dx < 0)
277	signdx = -1;
278
279    leftFace->x = x1;
280    leftFace->y = y1;
281    leftFace->dx = dx;
282    leftFace->dy = dy;
283
284    rightFace->x = x2;
285    rightFace->y = y2;
286    rightFace->dx = -dx;
287    rightFace->dy = -dy;
288
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));
324
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];
335	}
336	r = l / L;
337
338	/* coord of upper bound at integral y */
339	ya = -r * dx;
340	xa = r * dy;
341
342	projectXoff = -ya;
343	projectYoff = xa;
344
345    	/* xa * dy - ya * dx */
346	k = l * L;
347
348	leftFace->xa = xa;
349	leftFace->ya = ya;
350	leftFace->k = k;
351	rightFace->xa = -xa;
352	rightFace->ya = -ya;
353	rightFace->k = k;
354
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);
361
362	/* coord of lower bound at integral y */
363	ya = -ya;
364	xa = -xa;
365
366	/* xa * dy - ya * dx */
367	k = - k;
368
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);
375
376	/* coord of top face at integral y */
377
378	if (signdx > 0) {
379	    ya = -ya;
380	    xa = -xa;
381	}
382
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);
388	}
389	else
390	    topy = miPolyBuildEdge(xa, ya, 0.0,
391					-dy, dx, x1, y1, dx > 0, top);
392
393		/* coord of bottom face at integral y */
394
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;
405	}
406
407	finaly = ICEIL (maxy) + y2;
408
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;
417	}
418	bottom->height = finaly - bottomy;
419	XAAFillPolyHelper (pGC, topy,
420		bottom->height + bottomy - topy, lefts, rights, 2, 2);
421    }
422}
423
424
425static void
426XAALineArcI (GCPtr pGC, int xorg, int yorg)
427{
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);
432
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));
445	}
446	y--;
447	slw = (x << 1) + 1;
448	if ((e == ex) && (slw > 1))
449	    slw--;
450
451	FILL_SPAN(infoRec->pScrn, xorg - x, yorg - y, slw);
452
453	if ((y != 0) && ((slw > 1) || (e != ex))) {
454	    FILL_SPAN(infoRec->pScrn, xorg - x, yorg + y, slw);
455	}
456    }
457}
458
459
460static void
461XAALineArcD (
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 )
471{
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);
479
480
481    xbase = floor(xorg);
482    x0 = xorg - xbase;
483    ybase = ICEIL (yorg);
484    y0 = yorg - ybase;
485
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;
505    }
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;
517    }
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;
531    }
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);
541	}
542	el += k;
543	while (el >= 0.0) {
544	    xl--;
545	    el += (xl << 1) - xlk;
546	}
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);
557	}
558    }
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);
570	}
571	el -= k;
572	while ((el > 0.0) && (xl <= 0)) {
573	    xl++;
574	    el += (xl << 1) - xlk;
575	}
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);
586	}
587    }
588}
589
590
591static void
592XAALineArc (
593    GCPtr  pGC,
594    LineFacePtr leftFace,
595    LineFacePtr rightFace,
596    double	xorg,
597    double	yorg,
598    Bool	isInt )
599{
600    int xorgi, yorgi;
601    PolyEdgeRec	edge1, edge2;
602    int		edgey1, edgey2;
603    Bool	edgeleft1, edgeleft2;
604
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;
610    }
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;
619
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;
626	}
627
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);
635
636	isInt = FALSE;
637    }
638
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);
649
650}
651
652
653static void
654XAALineJoin (
655    GCPtr	    pGC,
656    LineFacePtr     pLeft,
657    LineFacePtr     pRight )
658{
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;
670
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 */
680	}
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;
686	}
687    } else {
688    	if (joinStyle == JoinRound) {
689	    XAALineArc(pGC, pLeft, pRight,(double)0.0, (double)0.0, TRUE);
690	    return;
691    	}
692    	denom = - pLeft->dx * (double)pRight->dy + pRight->dx *
693				(double)pLeft->dy;
694    	if (denom == 0.0)
695	    return;	/* no join to draw */
696    }
697
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;
710    }
711
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;
717
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;
723
724    vertices[2].x = pLeft->xa;
725    vertices[2].y = pLeft->ya;
726
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;
737
738	/* check miter limit */
739	if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw)
740	    joinStyle = JoinBevel;
741    }
742
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;
751	}
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;
761	}
762	edgecount = 4;
763    } else {
764	double	scale, dx, dy, adx, ady;
765
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;
780    }
781
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);
785}
786
787
788void
789XAAPolylinesWideSolid (
790   DrawablePtr  pDrawable,
791   GCPtr        pGC,
792   int          mode,
793   int          npt,
794   DDXPointPtr  pPts )
795{
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;
806
807    if(!RegionNumRects(pGC->pCompositeClip))
808	return;
809
810    if(RegionNumRects(pGC->pCompositeClip) != 1) {
811	miWideLine(pDrawable, pGC, mode, npt, pPts);
812	return;
813    }
814
815    x2 = pPts->x;
816    y2 = pPts->y;
817    if (npt > 1) {
818    	if (mode == CoordModePrevious) {
819	    int nptTmp;
820	    register DDXPointPtr pPtsTmp;
821
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;
830	    }
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;
835    }
836
837    projectLeft = ((pGC->capStyle == CapProjecting) && !selfJoin);
838    projectRight = FALSE;
839
840    (*infoRec->SetupForSolidFill)(infoRec->pScrn, pGC->fgPixel, pGC->alu,
841						pGC->planemask);
842
843    infoRec->ClipBox = &pGC->pCompositeClip->extents;
844
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);
850    }
851
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;
866	}
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);
882		}
883	    } else
884	    	XAALineJoin (pGC, &leftFace, &prevRightFace);
885
886	    prevRightFace = rightFace;
887	    first = FALSE;
888	    projectLeft = FALSE;
889	}
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);
899	    }
900	}
901    }
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);
913	}
914   }
915
916   infoRec->ClipBox = NULL;
917   if(hardClip)
918	(*infoRec->DisableClipping)(infoRec->pScrn);
919
920   SET_SYNC_FLAG(infoRec);
921}
922