]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/mi/miwideline.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / mi / miwideline.c
1 /* $XConsortium: miwideline.c /main/58 1996/08/12 21:51:21 dpw $ */
2 /*
3
4 Copyright (c) 1988  X Consortium
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24
25 Except as contained in this notice, the name of the X Consortium shall
26 not be used in advertising or otherwise to promote the sale, use or
27 other dealings in this Software without prior written authorization
28 from the X Consortium.
29
30 */
31 /* $XFree86: xc/programs/Xserver/mi/miwideline.c,v 1.1.1.3.2.2 1998/02/01 22:08:22 robin Exp $ */
32
33 /* Author:  Keith Packard, MIT X Consortium */
34
35 /*
36  * Mostly integer wideline code.  Uses a technique similar to
37  * bresenham zero-width lines, except walks an X edge
38  */
39
40 #include <stdio.h>
41 #ifdef _XOPEN_SOURCE
42 #include <math.h>
43 #else
44 #define _XOPEN_SOURCE   /* to get prototype for hypot on some systems */
45 #include <math.h>
46 #undef _XOPEN_SOURCE
47 #endif
48 #include "X.h"
49 #include "windowstr.h"
50 #include "gcstruct.h"
51 #include "miscstruct.h"
52 #include "miwideline.h"
53 #include "mi.h"
54
55 #ifdef ICEILTEMPDECL
56 ICEILTEMPDECL
57 #endif
58
59 static void miLineArc();
60
61 /*
62  * spans-based polygon filler
63  */
64
65 void
66 miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, overall_height,
67                   left, right, left_count, right_count)
68     DrawablePtr pDrawable;
69     GCPtr       pGC;
70     unsigned long   pixel;
71     SpanDataPtr spanData;
72     int         y;                      /* start y coordinate */
73     int         overall_height;         /* height of entire segment */
74     PolyEdgePtr left, right;
75     int         left_count, right_count;
76 {
77     register int left_x, left_e;
78     int left_stepx;
79     int left_signdx;
80     int left_dy, left_dx;
81
82     register int right_x, right_e;
83     int right_stepx;
84     int right_signdx;
85     int right_dy, right_dx;
86
87     int height;
88     int left_height, right_height;
89
90     register DDXPointPtr ppt;
91     DDXPointPtr pptInit;
92     register int *pwidth;
93     int *pwidthInit;
94     XID         oldPixel;
95     int         xorg;
96     Spans       spanRec;
97
98     left_height = 0;
99     right_height = 0;
100     
101     if (!spanData)
102     {
103         pptInit = (DDXPointPtr) ALLOCATE_LOCAL (overall_height * sizeof(*ppt));
104         if (!pptInit)
105             return;
106         pwidthInit = (int *) ALLOCATE_LOCAL (overall_height * sizeof(*pwidth));
107         if (!pwidthInit)
108         {
109             DEALLOCATE_LOCAL (pptInit);
110             return;
111         }
112         ppt = pptInit;
113         pwidth = pwidthInit;
114         oldPixel = pGC->fgPixel;
115         if (pixel != oldPixel)
116         {
117             DoChangeGC (pGC, GCForeground, (XID *)&pixel, FALSE);
118             ValidateGC (pDrawable, pGC);
119         }
120     }
121     else
122     {
123         spanRec.points = (DDXPointPtr) xalloc (overall_height * sizeof (*ppt));
124         if (!spanRec.points)
125             return;
126         spanRec.widths = (int *) xalloc (overall_height * sizeof (int));
127         if (!spanRec.widths)
128         {
129             xfree (spanRec.points);
130             return;
131         }
132         ppt = spanRec.points;
133         pwidth = spanRec.widths;
134     }
135
136     xorg = 0;
137     if (pGC->miTranslate)
138     {
139         y += pDrawable->y;
140         xorg = pDrawable->x;
141     }
142     while ((left_count || left_height) &&
143            (right_count || right_height))
144     {
145         MIPOLYRELOADLEFT
146         MIPOLYRELOADRIGHT
147
148         height = left_height;
149         if (height > right_height)
150             height = right_height;
151
152         left_height -= height;
153         right_height -= height;
154
155         while (--height >= 0)
156         {
157             if (right_x >= left_x)
158             {
159                 ppt->y = y;
160                 ppt->x = left_x + xorg;
161                 ppt++;
162                 *pwidth++ = right_x - left_x + 1;
163             }
164             y++;
165         
166             MIPOLYSTEPLEFT
167
168             MIPOLYSTEPRIGHT
169         }
170     }
171     if (!spanData)
172     {
173         (*pGC->ops->FillSpans) (pDrawable, pGC, ppt - pptInit, pptInit, pwidthInit, TRUE);
174         DEALLOCATE_LOCAL (pwidthInit);
175         DEALLOCATE_LOCAL (pptInit);
176         if (pixel != oldPixel)
177         {
178             DoChangeGC (pGC, GCForeground, &oldPixel, FALSE);
179             ValidateGC (pDrawable, pGC);
180         }
181     }
182     else
183     {
184         spanRec.count = ppt - spanRec.points;
185         AppendSpanGroup (pGC, pixel, &spanRec, spanData)
186     }
187 }
188
189 static void
190 miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, x, y, w, h)
191     DrawablePtr pDrawable;
192     GCPtr       pGC;
193     unsigned long   pixel;
194     SpanDataPtr spanData;
195     int         x, y, w, h;
196 {
197     register DDXPointPtr ppt;
198     register int *pwidth;
199     XID         oldPixel;
200     Spans       spanRec;
201     xRectangle  rect;
202
203     if (!spanData)
204     {
205         rect.x = x;
206         rect.y = y;
207         rect.width = w;
208         rect.height = h;
209         oldPixel = pGC->fgPixel;
210         if (pixel != oldPixel)
211         {
212             DoChangeGC (pGC, GCForeground, (XID *)&pixel, FALSE);
213             ValidateGC (pDrawable, pGC);
214         }
215         (*pGC->ops->PolyFillRect) (pDrawable, pGC, 1, &rect);
216         if (pixel != oldPixel)
217         {
218             DoChangeGC (pGC, GCForeground, &oldPixel, FALSE);
219             ValidateGC (pDrawable, pGC);
220         }
221     }
222     else
223     {
224         spanRec.points = (DDXPointPtr) xalloc (h * sizeof (*ppt));
225         if (!spanRec.points)
226             return;
227         spanRec.widths = (int *) xalloc (h * sizeof (int));
228         if (!spanRec.widths)
229         {
230             xfree (spanRec.points);
231             return;
232         }
233         ppt = spanRec.points;
234         pwidth = spanRec.widths;
235
236         if (pGC->miTranslate)
237         {
238             y += pDrawable->y;
239             x += pDrawable->x;
240         }
241         while (h--)
242         {
243             ppt->x = x;
244             ppt->y = y;
245             ppt++;
246             *pwidth++ = w;
247             y++;
248         }
249         spanRec.count = ppt - spanRec.points;
250         AppendSpanGroup (pGC, pixel, &spanRec, spanData)
251     }
252 }
253
254 int
255 miPolyBuildEdge (x0, y0, k, dx, dy, xi, yi, left, edge)
256     double      x0, y0;
257     double      k;  /* x0 * dy - y0 * dx */
258     register int dx, dy;
259     int         xi, yi;
260     int         left;
261     register PolyEdgePtr edge;
262 {
263     int     x, y, e;
264     int     xady;
265
266     if (dy < 0)
267     {
268         dy = -dy;
269         dx = -dx;
270         k = -k;
271     }
272
273 #ifdef NOTDEF
274     {
275         double  realk, kerror;
276         realk = x0 * dy - y0 * dx;
277         kerror = Fabs (realk - k);
278         if (kerror > .1)
279             printf ("realk: %g k: %g\n", realk, k);
280     }
281 #endif
282     y = ICEIL (y0);
283     xady = ICEIL (k) + y * dx;
284
285     if (xady <= 0)
286         x = - (-xady / dy) - 1;
287     else
288         x = (xady - 1) / dy;
289
290     e = xady - x * dy;
291
292     if (dx >= 0)
293     {
294         edge->signdx = 1;
295         edge->stepx = dx / dy;
296         edge->dx = dx % dy;
297     }
298     else
299     {
300         edge->signdx = -1;
301         edge->stepx = - (-dx / dy);
302         edge->dx = -dx % dy;
303         e = dy - e + 1;
304     }
305     edge->dy = dy;
306     edge->x = x + left + xi;
307     edge->e = e - dy;   /* bias to compare against 0 instead of dy */
308     return y + yi;
309 }
310
311 #define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr)))
312
313 int
314 miPolyBuildPoly (vertices, slopes, count, xi, yi, left, right, pnleft, pnright, h)
315     register PolyVertexPtr vertices;
316     register PolySlopePtr  slopes;
317     int             count;
318     int             xi, yi;
319     PolyEdgePtr     left, right;
320     int             *pnleft, *pnright;
321     int             *h;
322 {
323     int     top, bottom;
324     double  miny, maxy;
325     register int i;
326     int     j;
327     int     clockwise;
328     int     slopeoff;
329     register int s;
330     register int nright, nleft;
331     int     y, lasty, bottomy, topy;
332
333     /* find the top of the polygon */
334     maxy = miny = vertices[0].y;
335     bottom = top = 0;
336     for (i = 1; i < count; i++)
337     {
338         if (vertices[i].y < miny)
339         {
340             top = i;
341             miny = vertices[i].y;
342         }
343         if (vertices[i].y >= maxy)
344         {
345             bottom = i;
346             maxy = vertices[i].y;
347         }
348     }
349     clockwise = 1;
350     slopeoff = 0;
351
352     i = top;
353     j = StepAround (top, -1, count);
354
355     if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx)
356     {
357         clockwise = -1;
358         slopeoff = -1;
359     }
360
361     bottomy = ICEIL (maxy) + yi;
362
363     nright = 0;
364
365     s = StepAround (top, slopeoff, count);
366     i = top;
367     while (i != bottom)
368     {
369         if (slopes[s].dy != 0)
370         {
371             y = miPolyBuildEdge (vertices[i].x, vertices[i].y,
372                         slopes[s].k,
373                         slopes[s].dx, slopes[s].dy,
374                         xi, yi, 0,
375                         &right[nright]);
376             if (nright != 0)
377                 right[nright-1].height = y - lasty;
378             else
379                 topy = y;
380             nright++;
381             lasty = y;
382         }
383
384         i = StepAround (i, clockwise, count);
385         s = StepAround (s, clockwise, count);
386     }
387     if (nright != 0)
388         right[nright-1].height = bottomy - lasty;
389
390     if (slopeoff == 0)
391         slopeoff = -1;
392     else
393         slopeoff = 0;
394
395     nleft = 0;
396     s = StepAround (top, slopeoff, count);
397     i = top;
398     while (i != bottom)
399     {
400         if (slopes[s].dy != 0)
401         {
402             y = miPolyBuildEdge (vertices[i].x, vertices[i].y,
403                            slopes[s].k,
404                            slopes[s].dx,  slopes[s].dy, xi, yi, 1,
405                            &left[nleft]);
406     
407             if (nleft != 0)
408                 left[nleft-1].height = y - lasty;
409             nleft++;
410             lasty = y;
411         }
412         i = StepAround (i, -clockwise, count);
413         s = StepAround (s, -clockwise, count);
414     }
415     if (nleft != 0)
416         left[nleft-1].height = bottomy - lasty;
417     *pnleft = nleft;
418     *pnright = nright;
419     *h = bottomy - topy;
420     return topy;
421 }
422
423 static void
424 miLineOnePoint (pDrawable, pGC, pixel, spanData, x, y)
425     DrawablePtr     pDrawable;
426     GCPtr           pGC;
427     unsigned long   pixel;
428     SpanDataPtr     spanData;
429     int             x, y;
430 {
431     DDXPointRec pt;
432     int     wid;
433     unsigned long       oldPixel;
434
435     MILINESETPIXEL (pDrawable, pGC, pixel, oldPixel);
436     if (pGC->fillStyle == FillSolid)
437     {
438         pt.x = x;
439         pt.y = y;
440         (*pGC->ops->PolyPoint) (pDrawable, pGC, CoordModeOrigin, 1, &pt);
441     }
442     else
443     {
444         wid = 1;
445         if (pGC->miTranslate) 
446         {
447             x += pDrawable->x;
448             y += pDrawable->y;
449         }
450         pt.x = x;
451         pt.y = y;
452         (*pGC->ops->FillSpans) (pDrawable, pGC, 1, &pt, &wid, TRUE);
453     }
454     MILINERESETPIXEL (pDrawable, pGC, pixel, oldPixel);
455 }
456
457 static void
458 miLineJoin (pDrawable, pGC, pixel, spanData, pLeft, pRight)
459     DrawablePtr     pDrawable;
460     GCPtr           pGC;
461     unsigned long   pixel;
462     SpanDataPtr     spanData;
463     register LineFacePtr pLeft, pRight;
464 {
465     double          mx, my;
466     double          denom;
467     PolyVertexRec   vertices[4];
468     PolySlopeRec    slopes[4];
469     int             edgecount;
470     PolyEdgeRec     left[4], right[4];
471     int             nleft, nright;
472     int             y, height;
473     int             swapslopes;
474     int             joinStyle = pGC->joinStyle;
475     int             lw = pGC->lineWidth;
476
477     if (lw == 1 && !spanData) {
478         /* Lines going in the same direction have no join */
479         if (pLeft->dx >= 0 == pRight->dx <= 0)
480             return;
481         if (joinStyle != JoinRound) {
482             denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
483             if (denom == 0)
484                 return; /* no join to draw */
485         }
486         if (joinStyle != JoinMiter) {
487             miLineOnePoint (pDrawable, pGC, pixel, spanData, pLeft->x, pLeft->y);
488             return;
489         }
490     } else {
491         if (joinStyle == JoinRound)
492         {
493             miLineArc(pDrawable, pGC, pixel, spanData,
494                       pLeft, pRight,
495                       (double)0.0, (double)0.0, TRUE);
496             return;
497         }
498         denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
499         if (denom == 0.0)
500             return;     /* no join to draw */
501     }
502
503     swapslopes = 0;
504     if (denom > 0)
505     {
506         pLeft->xa = -pLeft->xa;
507         pLeft->ya = -pLeft->ya;
508         pLeft->dx = -pLeft->dx;
509         pLeft->dy = -pLeft->dy;
510     }
511     else
512     {
513         swapslopes = 1;
514         pRight->xa = -pRight->xa;
515         pRight->ya = -pRight->ya;
516         pRight->dx = -pRight->dx;
517         pRight->dy = -pRight->dy;
518     }
519
520     vertices[0].x = pRight->xa;
521     vertices[0].y = pRight->ya;
522     slopes[0].dx = -pRight->dy;
523     slopes[0].dy =  pRight->dx;
524     slopes[0].k = 0;
525
526     vertices[1].x = 0;
527     vertices[1].y = 0;
528     slopes[1].dx =  pLeft->dy;
529     slopes[1].dy = -pLeft->dx;
530     slopes[1].k = 0;
531
532     vertices[2].x = pLeft->xa;
533     vertices[2].y = pLeft->ya;
534
535     if (joinStyle == JoinMiter)
536     {
537         my = (pLeft->dy  * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) -
538               pRight->dy * (pLeft->xa  * pLeft->dy  - pLeft->ya  * pLeft->dx )) /
539               denom;
540         if (pLeft->dy != 0)
541         {
542             mx = pLeft->xa + (my - pLeft->ya) *
543                             (double) pLeft->dx / (double) pLeft->dy;
544         }
545         else
546         {
547             mx = pRight->xa + (my - pRight->ya) *
548                             (double) pRight->dx / (double) pRight->dy;
549         }
550         /* check miter limit */
551         if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw)
552             joinStyle = JoinBevel;
553     }
554
555     if (joinStyle == JoinMiter)
556     {
557         slopes[2].dx = pLeft->dx;
558         slopes[2].dy = pLeft->dy;
559         slopes[2].k =  pLeft->k;
560         if (swapslopes)
561         {
562             slopes[2].dx = -slopes[2].dx;
563             slopes[2].dy = -slopes[2].dy;
564             slopes[2].k  = -slopes[2].k;
565         }
566         vertices[3].x = mx;
567         vertices[3].y = my;
568         slopes[3].dx = pRight->dx;
569         slopes[3].dy = pRight->dy;
570         slopes[3].k  = pRight->k;
571         if (swapslopes)
572         {
573             slopes[3].dx = -slopes[3].dx;
574             slopes[3].dy = -slopes[3].dy;
575             slopes[3].k  = -slopes[3].k;
576         }
577         edgecount = 4;
578     }
579     else
580     {
581         double  scale, dx, dy, adx, ady;
582
583         adx = dx = pRight->xa - pLeft->xa;
584         ady = dy = pRight->ya - pLeft->ya;
585         if (adx < 0)
586             adx = -adx;
587         if (ady < 0)
588             ady = -ady;
589         scale = ady;
590         if (adx > ady)
591             scale = adx;
592         slopes[2].dx = (dx * 65536) / scale;
593         slopes[2].dy = (dy * 65536) / scale;
594         slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy -
595                        (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0;
596         edgecount = 3;
597     }
598
599     y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y,
600                    left, right, &nleft, &nright, &height);
601     miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, height, left, right, nleft, nright);
602 }
603
604 static int
605 miLineArcI (pDraw, pGC, xorg, yorg, points, widths)
606     DrawablePtr     pDraw;
607     GCPtr           pGC;
608     int             xorg, yorg;
609     DDXPointPtr     points;
610     int             *widths;
611 {
612     register DDXPointPtr tpts, bpts;
613     register int *twids, *bwids;
614     register int x, y, e, ex, slw;
615
616     tpts = points;
617     twids = widths;
618     if (pGC->miTranslate)
619     {
620         xorg += pDraw->x;
621         yorg += pDraw->y;
622     }
623     slw = pGC->lineWidth;
624     if (slw == 1)
625     {
626         tpts->x = xorg;
627         tpts->y = yorg;
628         *twids = 1;
629         return 1;
630     }
631     bpts = tpts + slw;
632     bwids = twids + slw;
633     y = (slw >> 1) + 1;
634     if (slw & 1)
635         e = - ((y << 2) + 3);
636     else
637         e = - (y << 3);
638     ex = -4;
639     x = 0;
640     while (y)
641     {
642         e += (y << 3) - 4;
643         while (e >= 0)
644         {
645             x++;
646             e += (ex = -((x << 3) + 4));
647         }
648         y--;
649         slw = (x << 1) + 1;
650         if ((e == ex) && (slw > 1))
651             slw--;
652         tpts->x = xorg - x;
653         tpts->y = yorg - y;
654         tpts++;
655         *twids++ = slw;
656         if ((y != 0) && ((slw > 1) || (e != ex)))
657         {
658             bpts--;
659             bpts->x = xorg - x;
660             bpts->y = yorg + y;
661             *--bwids = slw;
662         }
663     }
664     return (pGC->lineWidth);
665 }
666
667 #define CLIPSTEPEDGE(edgey,edge,edgeleft) \
668     if (ybase == edgey) \
669     { \
670         if (edgeleft) \
671         { \
672             if (edge->x > xcl) \
673                 xcl = edge->x; \
674         } \
675         else \
676         { \
677             if (edge->x < xcr) \
678                 xcr = edge->x; \
679         } \
680         edgey++; \
681         edge->x += edge->stepx; \
682         edge->e += edge->dx; \
683         if (edge->e > 0) \
684         { \
685             edge->x += edge->signdx; \
686             edge->e -= edge->dy; \
687         } \
688     }
689
690 static int
691 miLineArcD (pDraw, pGC, xorg, yorg, points, widths,
692             edge1, edgey1, edgeleft1, edge2, edgey2, edgeleft2)
693     DrawablePtr     pDraw;
694     GCPtr           pGC;
695     double          xorg, yorg;
696     DDXPointPtr     points;
697     int             *widths;
698     PolyEdgePtr     edge1, edge2;
699     int             edgey1, edgey2;
700     Bool            edgeleft1, edgeleft2;
701 {
702     register DDXPointPtr pts;
703     register int *wids;
704     double radius, x0, y0, el, er, yk, xlk, xrk, k;
705     int xbase, ybase, y, boty, xl, xr, xcl, xcr;
706     int ymin, ymax;
707     Bool edge1IsMin, edge2IsMin;
708     int ymin1, ymin2;
709
710     pts = points;
711     wids = widths;
712     xbase = floor(xorg);
713     x0 = xorg - xbase;
714     ybase = ICEIL (yorg);
715     y0 = yorg - ybase;
716     if (pGC->miTranslate)
717     {
718         xbase += pDraw->x;
719         ybase += pDraw->y;
720         edge1->x += pDraw->x;
721         edge2->x += pDraw->x;
722         edgey1 += pDraw->y;
723         edgey2 += pDraw->y;
724     }
725     xlk = x0 + x0 + 1.0;
726     xrk = x0 + x0 - 1.0;
727     yk = y0 + y0 - 1.0;
728     radius = ((double)pGC->lineWidth) / 2.0;
729     y = floor(radius - y0 + 1.0);
730     ybase -= y;
731     ymin = ybase;
732     ymax = 65536;
733     edge1IsMin = FALSE;
734     ymin1 = edgey1;
735     if (edge1->dy >= 0)
736     {
737         if (!edge1->dy)
738         {
739             if (edgeleft1)
740                 edge1IsMin = TRUE;
741             else
742                 ymax = edgey1;
743             edgey1 = 65536;
744         }
745         else
746         {
747             if ((edge1->signdx < 0) == edgeleft1)
748                 edge1IsMin = TRUE;
749         }
750     }
751     edge2IsMin = FALSE;
752     ymin2 = edgey2;
753     if (edge2->dy >= 0)
754     {
755         if (!edge2->dy)
756         {
757             if (edgeleft2)
758                 edge2IsMin = TRUE;
759             else
760                 ymax = edgey2;
761             edgey2 = 65536;
762         }
763         else
764         {
765             if ((edge2->signdx < 0) == edgeleft2)
766                 edge2IsMin = TRUE;
767         }
768     }
769     if (edge1IsMin)
770     {
771         ymin = ymin1;
772         if (edge2IsMin && ymin1 > ymin2)
773             ymin = ymin2;
774     } else if (edge2IsMin)
775         ymin = ymin2;
776     el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0);
777     er = el + xrk;
778     xl = 1;
779     xr = 0;
780     if (x0 < 0.5)
781     {
782         xl = 0;
783         el -= xlk;
784     }
785     boty = (y0 < -0.5) ? 1 : 0;
786     if (ybase + y - boty > ymax)
787         boty = ymax - ybase - y;
788     while (y > boty)
789     {
790         k = (y << 1) + yk;
791         er += k;
792         while (er > 0.0)
793         {
794             xr++;
795             er += xrk - (xr << 1);
796         }
797         el += k;
798         while (el >= 0.0)
799         {
800             xl--;
801             el += (xl << 1) - xlk;
802         }
803         y--;
804         ybase++;
805         if (ybase < ymin)
806             continue;
807         xcl = xl + xbase;
808         xcr = xr + xbase;
809         CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
810         CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
811         if (xcr >= xcl)
812         {
813             pts->x = xcl;
814             pts->y = ybase;
815             pts++;
816             *wids++ = xcr - xcl + 1;
817         }
818     }
819     er = xrk - (xr << 1) - er;
820     el = (xl << 1) - xlk - el;
821     boty = floor(-y0 - radius + 1.0);
822     if (ybase + y - boty > ymax)
823         boty = ymax - ybase - y;
824     while (y > boty)
825     {
826         k = (y << 1) + yk;
827         er -= k;
828         while ((er >= 0.0) && (xr >= 0))
829         {
830             xr--;
831             er += xrk - (xr << 1);
832         }
833         el -= k;
834         while ((el > 0.0) && (xl <= 0))
835         {
836             xl++;
837             el += (xl << 1) - xlk;
838         }
839         y--;
840         ybase++;
841         if (ybase < ymin)
842             continue;
843         xcl = xl + xbase;
844         xcr = xr + xbase;
845         CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
846         CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
847         if (xcr >= xcl)
848         {
849             pts->x = xcl;
850             pts->y = ybase;
851             pts++;
852             *wids++ = xcr - xcl + 1;
853         }
854     }
855     return (pts - points);
856 }
857
858 int
859 miRoundJoinFace (face, edge, leftEdge)
860     register LineFacePtr face;
861     register PolyEdgePtr edge;
862     Bool        *leftEdge;
863 {
864     int     y;
865     int     dx, dy;
866     double  xa, ya;
867     Bool        left;
868
869     dx = -face->dy;
870     dy = face->dx;
871     xa = face->xa;
872     ya = face->ya;
873     left = 1;
874     if (ya > 0)
875     {
876         ya = 0.0;
877         xa = 0.0;
878     }
879     if (dy < 0 || dy == 0 && dx > 0)
880     {
881         dx = -dx;
882         dy = -dy;
883         left = !left;
884     }
885     if (dx == 0 && dy == 0)
886         dy = 1;
887     if (dy == 0)
888     {
889         y = ICEIL (face->ya) + face->y;
890         edge->x = -32767;
891         edge->stepx = 0;
892         edge->signdx = 0;
893         edge->e = -1;
894         edge->dy = 0;
895         edge->dx = 0;
896         edge->height = 0;
897     }
898     else
899     {
900         y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge);
901         edge->height = 32767;
902     }
903     *leftEdge = !left;
904     return y;
905 }
906
907 void
908 miRoundJoinClip (pLeft, pRight, edge1, edge2, y1, y2, left1, left2)
909     register LineFacePtr pLeft, pRight;
910     PolyEdgePtr edge1, edge2;
911     int         *y1, *y2;
912     Bool        *left1, *left2;
913 {
914     double      denom;
915
916     denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
917
918     if (denom >= 0)
919     {
920         pLeft->xa = -pLeft->xa;
921         pLeft->ya = -pLeft->ya;
922     }
923     else
924     {
925         pRight->xa = -pRight->xa;
926         pRight->ya = -pRight->ya;
927     }
928     *y1 = miRoundJoinFace (pLeft, edge1, left1);
929     *y2 = miRoundJoinFace (pRight, edge2, left2);
930 }
931
932 int
933 miRoundCapClip (face, isInt, edge, leftEdge)
934     register LineFacePtr face;
935     Bool        isInt;
936     register PolyEdgePtr edge;
937     Bool        *leftEdge;
938 {
939     int     y;
940     register int dx, dy;
941     double  xa, ya, k;
942     Bool        left;
943
944     dx = -face->dy;
945     dy = face->dx;
946     xa = face->xa;
947     ya = face->ya;
948     k = 0.0;
949     if (!isInt)
950         k = face->k;
951     left = 1;
952     if (dy < 0 || dy == 0 && dx > 0)
953     {
954         dx = -dx;
955         dy = -dy;
956         xa = -xa;
957         ya = -ya;
958         left = !left;
959     }
960     if (dx == 0 && dy == 0)
961         dy = 1;
962     if (dy == 0)
963     {
964         y = ICEIL (face->ya) + face->y;
965         edge->x = -32767;
966         edge->stepx = 0;
967         edge->signdx = 0;
968         edge->e = -1;
969         edge->dy = 0;
970         edge->dx = 0;
971         edge->height = 0;
972     }
973     else
974     {
975         y = miPolyBuildEdge (xa, ya, k, dx, dy, face->x, face->y, !left, edge);
976         edge->height = 32767;
977     }
978     *leftEdge = !left;
979     return y;
980 }
981
982 static void
983 miLineArc (pDraw, pGC, pixel, spanData, leftFace, rightFace, xorg, yorg, isInt)
984     DrawablePtr     pDraw;
985     register GCPtr  pGC;
986     unsigned long   pixel;
987     SpanDataPtr     spanData;
988     register LineFacePtr leftFace, rightFace;
989     double          xorg, yorg;
990     Bool            isInt;
991 {
992     DDXPointPtr points;
993     int *widths;
994     int xorgi, yorgi;
995     XID         oldPixel;
996     Spans spanRec;
997     int n;
998     PolyEdgeRec edge1, edge2;
999     int         edgey1, edgey2;
1000     Bool        edgeleft1, edgeleft2;
1001
1002     if (isInt)
1003     {
1004         xorgi = leftFace ? leftFace->x : rightFace->x;
1005         yorgi = leftFace ? leftFace->y : rightFace->y;
1006     }
1007     edgey1 = 65536;
1008     edgey2 = 65536;
1009     edge1.x = 0; /* not used, keep memory checkers happy */
1010     edge1.dy = -1;
1011     edge2.x = 0; /* not used, keep memory checkers happy */
1012     edge2.dy = -1;
1013     edgeleft1 = FALSE;
1014     edgeleft2 = FALSE;
1015     if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) &&
1016         (pGC->capStyle == CapRound && pGC->joinStyle != JoinRound ||
1017          pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))
1018     {
1019         if (isInt)
1020         {
1021             xorg = (double) xorgi;
1022             yorg = (double) yorgi;
1023         }
1024         if (leftFace && rightFace)
1025         {
1026             miRoundJoinClip (leftFace, rightFace, &edge1, &edge2,
1027                              &edgey1, &edgey2, &edgeleft1, &edgeleft2);
1028         }
1029         else if (leftFace)
1030         {
1031             edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1);
1032         }
1033         else if (rightFace)
1034         {
1035             edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2);
1036         }
1037         isInt = FALSE;
1038     }
1039     if (!spanData)
1040     {
1041         points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * pGC->lineWidth);
1042         if (!points)
1043             return;
1044         widths = (int *)ALLOCATE_LOCAL(sizeof(int) * pGC->lineWidth);
1045         if (!widths)
1046         {
1047             DEALLOCATE_LOCAL(points);
1048             return;
1049         }
1050         oldPixel = pGC->fgPixel;
1051         if (pixel != oldPixel)
1052         {
1053             DoChangeGC(pGC, GCForeground, (XID *)&pixel, FALSE);
1054             ValidateGC (pDraw, pGC);
1055         }
1056     }
1057     else
1058     {
1059         points = (DDXPointPtr) xalloc (pGC->lineWidth * sizeof (DDXPointRec));
1060         if (!points)
1061             return;
1062         widths = (int *) xalloc (pGC->lineWidth * sizeof (int));
1063         if (!widths)
1064         {
1065             xfree (points);
1066             return;
1067         }
1068         spanRec.points = points;
1069         spanRec.widths = widths;
1070     }
1071     if (isInt)
1072         n = miLineArcI(pDraw, pGC, xorgi, yorgi, points, widths);
1073     else
1074         n = miLineArcD(pDraw, pGC, xorg, yorg, points, widths,
1075                        &edge1, edgey1, edgeleft1,
1076                        &edge2, edgey2, edgeleft2);
1077
1078     if (!spanData)
1079     {
1080         (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, TRUE);
1081         DEALLOCATE_LOCAL(widths);
1082         DEALLOCATE_LOCAL(points);
1083         if (pixel != oldPixel)
1084         {
1085             DoChangeGC(pGC, GCForeground, &oldPixel, FALSE);
1086             ValidateGC (pDraw, pGC);
1087         }
1088     }
1089     else
1090     {
1091         spanRec.count = n;
1092         AppendSpanGroup (pGC, pixel, &spanRec, spanData)
1093     }
1094 }
1095
1096 void
1097 miLineProjectingCap (pDrawable, pGC, pixel, spanData, face, isLeft, xorg, yorg, isInt)
1098     DrawablePtr     pDrawable;
1099     register GCPtr  pGC;
1100     unsigned long   pixel;
1101     SpanDataPtr     spanData;
1102     register LineFacePtr face;
1103     Bool            isLeft;
1104     double          xorg, yorg;
1105     Bool            isInt;
1106 {
1107     int xorgi, yorgi;
1108     int lw;
1109     PolyEdgeRec lefts[2], rights[2];
1110     int         lefty, righty, topy, bottomy;
1111     PolyEdgePtr left, right;
1112     PolyEdgePtr top, bottom;
1113     double      xa,ya;
1114     double      k;
1115     double      xap, yap;
1116     int         dx, dy;
1117     double      projectXoff, projectYoff;
1118     double      maxy;
1119     int         finaly;
1120     
1121     if (isInt)
1122     {
1123         xorgi = face->x;
1124         yorgi = face->y;
1125     }
1126     lw = pGC->lineWidth;
1127     dx = face->dx;
1128     dy = face->dy;
1129     k = face->k;
1130     if (dy == 0)
1131     {
1132         lefts[0].height = lw;
1133         lefts[0].x = xorgi;
1134         if (isLeft)
1135             lefts[0].x -= (lw >> 1);
1136         lefts[0].stepx = 0;
1137         lefts[0].signdx = 1;
1138         lefts[0].e = -lw;
1139         lefts[0].dx = 0;
1140         lefts[0].dy = lw;
1141         rights[0].height = lw;
1142         rights[0].x = xorgi;
1143         if (!isLeft)
1144             rights[0].x += (lw + 1 >> 1);
1145         rights[0].stepx = 0;
1146         rights[0].signdx = 1;
1147         rights[0].e = -lw;
1148         rights[0].dx = 0;
1149         rights[0].dy = lw;
1150         miFillPolyHelper (pDrawable, pGC, pixel, spanData, yorgi - (lw >> 1), lw,
1151                      lefts, rights, 1, 1);
1152     }
1153     else if (dx == 0)
1154     {
1155         topy = yorgi;
1156         bottomy = yorgi + dy;
1157         if (isLeft)
1158             topy -= (lw >> 1);
1159         else
1160             bottomy += (lw >> 1);
1161         lefts[0].height = bottomy - topy;
1162         lefts[0].x = xorgi - (lw >> 1);
1163         lefts[0].stepx = 0;
1164         lefts[0].signdx = 1;
1165         lefts[0].e = -dy;
1166         lefts[0].dx = dx;
1167         lefts[0].dy = dy;
1168
1169         rights[0].height = bottomy - topy;
1170         rights[0].x = lefts[0].x + (lw-1);
1171         rights[0].stepx = 0;
1172         rights[0].signdx = 1;
1173         rights[0].e = -dy;
1174         rights[0].dx = dx;
1175         rights[0].dy = dy;
1176         miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, bottomy - topy, lefts, rights, 1, 1);
1177     }
1178     else
1179     {
1180         xa = face->xa;
1181         ya = face->ya;
1182         projectXoff = -ya;
1183         projectYoff = xa;
1184         if (dx < 0)
1185         {
1186             right = &rights[1];
1187             left = &lefts[0];
1188             top = &rights[0];
1189             bottom = &lefts[1];
1190         }
1191         else
1192         {
1193             right = &rights[0];
1194             left = &lefts[1];
1195             top = &lefts[0];
1196             bottom = &rights[1];
1197         }
1198         if (isLeft)
1199         {
1200             righty = miPolyBuildEdge (xa, ya,
1201                      k, dx, dy, xorgi, yorgi, 0, right);
1202             
1203             xa = -xa;
1204             ya = -ya;
1205             k = -k;
1206             lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
1207                                      k, dx, dy, xorgi, yorgi, 1, left);
1208             if (dx > 0)
1209             {
1210                 ya = -ya;
1211                 xa = -xa;
1212             }
1213             xap = xa - projectXoff;
1214             yap = ya - projectYoff;
1215             topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
1216                                     -dy, dx, xorgi, yorgi, dx > 0, top);
1217             bottomy = miPolyBuildEdge (xa, ya,
1218                                        0.0, -dy, dx, xorgi, yorgi, dx < 0, bottom);
1219             maxy = -ya;
1220         }
1221         else
1222         {
1223             righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
1224                      k, dx, dy, xorgi, yorgi, 0, right);
1225             
1226             xa = -xa;
1227             ya = -ya;
1228             k = -k;
1229             lefty = miPolyBuildEdge (xa, ya,
1230                     k, dx, dy, xorgi, yorgi, 1, left);
1231             if (dx > 0)
1232             {
1233                 ya = -ya;
1234                 xa = -xa;
1235             }
1236             xap = xa - projectXoff;
1237             yap = ya - projectYoff;
1238             topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0, top);
1239             bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
1240                                        -dy, dx, xorgi, xorgi, dx < 0, bottom);
1241             maxy = -ya + projectYoff;
1242         }
1243         finaly = ICEIL(maxy) + yorgi;
1244         if (dx < 0)
1245         {
1246             left->height = bottomy - lefty;
1247             right->height = finaly - righty;
1248             top->height = righty - topy;
1249         }
1250         else
1251         {
1252             right->height =  bottomy - righty;
1253             left->height = finaly - lefty;
1254             top->height = lefty - topy;
1255         }
1256         bottom->height = finaly - bottomy;
1257         miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy,
1258                      bottom->height + bottomy - topy, lefts, rights, 2, 2);
1259     }
1260 }
1261
1262 static void
1263 miWideSegment (pDrawable, pGC, pixel, spanData,
1264                x1, y1, x2, y2, projectLeft, projectRight, leftFace, rightFace)
1265     DrawablePtr     pDrawable;
1266     GCPtr           pGC;
1267     unsigned long   pixel;
1268     SpanDataPtr     spanData;
1269     register int    x1, y1, x2, y2;
1270     Bool            projectLeft, projectRight;
1271     register LineFacePtr leftFace, rightFace;
1272 {
1273     double      l, L, r;
1274     double      xa, ya;
1275     double      projectXoff, projectYoff;
1276     double      k;
1277     double      maxy;
1278     int         x, y;
1279     int         dx, dy;
1280     int         finaly;
1281     PolyEdgePtr left, right;
1282     PolyEdgePtr top, bottom;
1283     int         lefty, righty, topy, bottomy;
1284     int         signdx;
1285     PolyEdgeRec lefts[2], rights[2];
1286     LineFacePtr tface;
1287     int         lw = pGC->lineWidth;
1288
1289     /* draw top-to-bottom always */
1290     if (y2 < y1 || y2 == y1 && x2 < x1)
1291     {
1292         x = x1;
1293         x1 = x2;
1294         x2 = x;
1295
1296         y = y1;
1297         y1 = y2;
1298         y2 = y;
1299
1300         x = projectLeft;
1301         projectLeft = projectRight;
1302         projectRight = x;
1303
1304         tface = leftFace;
1305         leftFace = rightFace;
1306         rightFace = tface;
1307     }
1308
1309     dy = y2 - y1;
1310     signdx = 1;
1311     dx = x2 - x1;
1312     if (dx < 0)
1313         signdx = -1;
1314
1315     leftFace->x = x1;
1316     leftFace->y = y1;
1317     leftFace->dx = dx;
1318     leftFace->dy = dy;
1319
1320     rightFace->x = x2;
1321     rightFace->y = y2;
1322     rightFace->dx = -dx;
1323     rightFace->dy = -dy;
1324
1325     if (dy == 0)
1326     {
1327         rightFace->xa = 0;
1328         rightFace->ya = (double) lw / 2.0;
1329         rightFace->k = -(double) (lw * dx) / 2.0;
1330         leftFace->xa = 0;
1331         leftFace->ya = -rightFace->ya;
1332         leftFace->k = rightFace->k;
1333         x = x1;
1334         if (projectLeft)
1335             x -= (lw >> 1);
1336         y = y1 - (lw >> 1);
1337         dx = x2 - x;
1338         if (projectRight)
1339             dx += (lw + 1 >> 1);
1340         dy = lw;
1341         miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
1342                               x, y, dx, dy);
1343     }
1344     else if (dx == 0)
1345     {
1346         leftFace->xa =  (double) lw / 2.0;
1347         leftFace->ya = 0;
1348         leftFace->k = (double) (lw * dy) / 2.0;
1349         rightFace->xa = -leftFace->xa;
1350         rightFace->ya = 0;
1351         rightFace->k = leftFace->k;
1352         y = y1;
1353         if (projectLeft)
1354             y -= lw >> 1;
1355         x = x1 - (lw >> 1);
1356         dy = y2 - y;
1357         if (projectRight)
1358             dy += (lw + 1 >> 1);
1359         dx = lw;
1360         miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
1361                               x, y, dx, dy);
1362     }
1363     else
1364     {
1365         l = ((double) lw) / 2.0;
1366         L = hypot ((double) dx, (double) dy);
1367
1368         if (dx < 0)
1369         {
1370             right = &rights[1];
1371             left = &lefts[0];
1372             top = &rights[0];
1373             bottom = &lefts[1];
1374         }
1375         else
1376         {
1377             right = &rights[0];
1378             left = &lefts[1];
1379             top = &lefts[0];
1380             bottom = &rights[1];
1381         }
1382         r = l / L;
1383
1384         /* coord of upper bound at integral y */
1385         ya = -r * dx;
1386         xa = r * dy;
1387
1388         if (projectLeft | projectRight)
1389         {
1390             projectXoff = -ya;
1391             projectYoff = xa;
1392         }
1393
1394         /* xa * dy - ya * dx */
1395         k = l * L;
1396
1397         leftFace->xa = xa;
1398         leftFace->ya = ya;
1399         leftFace->k = k;
1400         rightFace->xa = -xa;
1401         rightFace->ya = -ya;
1402         rightFace->k = k;
1403
1404         if (projectLeft)
1405             righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
1406                                       k, dx, dy, x1, y1, 0, right);
1407         else
1408             righty = miPolyBuildEdge (xa, ya,
1409                                       k, dx, dy, x1, y1, 0, right);
1410
1411         /* coord of lower bound at integral y */
1412         ya = -ya;
1413         xa = -xa;
1414
1415         /* xa * dy - ya * dx */
1416         k = - k;
1417
1418         if (projectLeft)
1419             lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
1420                                      k, dx, dy, x1, y1, 1, left);
1421         else
1422             lefty = miPolyBuildEdge (xa, ya,
1423                                      k, dx, dy, x1, y1, 1, left);
1424
1425         /* coord of top face at integral y */
1426
1427         if (signdx > 0)
1428         {
1429             ya = -ya;
1430             xa = -xa;
1431         }
1432
1433         if (projectLeft)
1434         {
1435             double xap = xa - projectXoff;
1436             double yap = ya - projectYoff;
1437             topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
1438                                     -dy, dx, x1, y1, dx > 0, top);
1439         }
1440         else
1441             topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top);
1442
1443         /* coord of bottom face at integral y */
1444
1445         if (projectRight)
1446         {
1447             double xap = xa + projectXoff;
1448             double yap = ya + projectYoff;
1449             bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
1450                                        -dy, dx, x2, y2, dx < 0, bottom);
1451             maxy = -ya + projectYoff;
1452         }
1453         else
1454         {
1455             bottomy = miPolyBuildEdge (xa, ya,
1456                                        0.0, -dy, dx, x2, y2, dx < 0, bottom);
1457             maxy = -ya;
1458         }
1459
1460         finaly = ICEIL (maxy) + y2;
1461
1462         if (dx < 0)
1463         {
1464             left->height = bottomy - lefty;
1465             right->height = finaly - righty;
1466             top->height = righty - topy;
1467         }
1468         else
1469         {
1470             right->height =  bottomy - righty;
1471             left->height = finaly - lefty;
1472             top->height = lefty - topy;
1473         }
1474         bottom->height = finaly - bottomy;
1475         miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy,
1476                      bottom->height + bottomy - topy, lefts, rights, 2, 2);
1477     }
1478 }
1479
1480 SpanDataPtr
1481 miSetupSpanData (pGC, spanData, npt)
1482     register GCPtr pGC;
1483     SpanDataPtr spanData;
1484     int         npt;
1485 {
1486     if (npt < 3 && pGC->capStyle != CapRound || miSpansEasyRop(pGC->alu))
1487         return (SpanDataPtr) NULL;
1488     if (pGC->lineStyle == LineDoubleDash)
1489         miInitSpanGroup (&spanData->bgGroup);
1490     miInitSpanGroup (&spanData->fgGroup);
1491     return spanData;
1492 }
1493
1494 void
1495 miCleanupSpanData (pDrawable, pGC, spanData)
1496     DrawablePtr pDrawable;
1497     GCPtr       pGC;
1498     SpanDataPtr spanData;
1499 {
1500     if (pGC->lineStyle == LineDoubleDash)
1501     {
1502         XID oldPixel, pixel;
1503         
1504         pixel = pGC->bgPixel;
1505         oldPixel = pGC->fgPixel;
1506         if (pixel != oldPixel)
1507         {
1508             DoChangeGC (pGC, GCForeground, &pixel, FALSE);
1509             ValidateGC (pDrawable, pGC);
1510         }
1511         miFillUniqueSpanGroup (pDrawable, pGC, &spanData->bgGroup);
1512         miFreeSpanGroup (&spanData->bgGroup);
1513         if (pixel != oldPixel)
1514         {
1515             DoChangeGC (pGC, GCForeground, &oldPixel, FALSE);
1516             ValidateGC (pDrawable, pGC);
1517         }
1518     }
1519     miFillUniqueSpanGroup (pDrawable, pGC, &spanData->fgGroup);
1520     miFreeSpanGroup (&spanData->fgGroup);
1521 }
1522
1523 void
1524 miWideLine (pDrawable, pGC, mode, npt, pPts)
1525     DrawablePtr pDrawable;
1526     register GCPtr pGC;
1527     int         mode;
1528     register int npt;
1529     register DDXPointPtr pPts;
1530 {
1531     int             x1, y1, x2, y2;
1532     SpanDataRec     spanDataRec;
1533     SpanDataPtr     spanData;
1534     unsigned long   pixel;
1535     Bool            projectLeft, projectRight;
1536     LineFaceRec     leftFace, rightFace, prevRightFace;
1537     LineFaceRec     firstFace;
1538     register int    first;
1539     Bool            somethingDrawn = FALSE;
1540     Bool            selfJoin;
1541
1542     spanData = miSetupSpanData (pGC, &spanDataRec, npt);
1543     pixel = pGC->fgPixel;
1544     x2 = pPts->x;
1545     y2 = pPts->y;
1546     first = TRUE;
1547     selfJoin = FALSE;
1548     if (npt > 1)
1549     {
1550         if (mode == CoordModePrevious)
1551         {
1552             int nptTmp;
1553             DDXPointPtr pPtsTmp;
1554     
1555             x1 = x2;
1556             y1 = y2;
1557             nptTmp = npt;
1558             pPtsTmp = pPts + 1;
1559             while (--nptTmp)
1560             {
1561                 x1 += pPtsTmp->x;
1562                 y1 += pPtsTmp->y;
1563                 ++pPtsTmp;
1564             }
1565             if (x2 == x1 && y2 == y1)
1566                 selfJoin = TRUE;
1567         }
1568         else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y)
1569         {
1570             selfJoin = TRUE;
1571         }
1572     }
1573     projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
1574     projectRight = FALSE;
1575     while (--npt)
1576     {
1577         x1 = x2;
1578         y1 = y2;
1579         ++pPts;
1580         x2 = pPts->x;
1581         y2 = pPts->y;
1582         if (mode == CoordModePrevious)
1583         {
1584             x2 += x1;
1585             y2 += y1;
1586         }
1587         if (x1 != x2 || y1 != y2)
1588         {
1589             somethingDrawn = TRUE;
1590             if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin)
1591                 projectRight = TRUE;
1592             miWideSegment (pDrawable, pGC, pixel, spanData, x1, y1, x2, y2,
1593                            projectLeft, projectRight, &leftFace, &rightFace);
1594             if (first)
1595             {
1596                 if (selfJoin)
1597                     firstFace = leftFace;
1598                 else if (pGC->capStyle == CapRound)
1599                 {
1600                     if (pGC->lineWidth == 1 && !spanData)
1601                         miLineOnePoint (pDrawable, pGC, pixel, spanData, x1, y1);
1602                     else
1603                         miLineArc (pDrawable, pGC, pixel, spanData,
1604                                    &leftFace, (LineFacePtr) NULL,
1605                                    (double)0.0, (double)0.0,
1606                                    TRUE);
1607                 }
1608             }
1609             else
1610             {
1611                 miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace,
1612                             &prevRightFace);
1613             }
1614             prevRightFace = rightFace;
1615             first = FALSE;
1616             projectLeft = FALSE;
1617         }
1618         if (npt == 1 && somethingDrawn)
1619         {
1620             if (selfJoin)
1621                 miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace,
1622                             &rightFace);
1623             else if (pGC->capStyle == CapRound)
1624             {
1625                 if (pGC->lineWidth == 1 && !spanData)
1626                     miLineOnePoint (pDrawable, pGC, pixel, spanData, x2, y2);
1627                 else
1628                     miLineArc (pDrawable, pGC, pixel, spanData,
1629                                (LineFacePtr) NULL, &rightFace,
1630                                (double)0.0, (double)0.0,
1631                                TRUE);
1632             }
1633         }
1634     }
1635     /* handle crock where all points are coincedent */
1636     if (!somethingDrawn)
1637     {
1638         projectLeft = pGC->capStyle == CapProjecting;
1639         miWideSegment (pDrawable, pGC, pixel, spanData,
1640                        x2, y2, x2, y2, projectLeft, projectLeft,
1641                        &leftFace, &rightFace);
1642         if (pGC->capStyle == CapRound)
1643         {
1644             miLineArc (pDrawable, pGC, pixel, spanData,
1645                        &leftFace, (LineFacePtr) NULL,
1646                        (double)0.0, (double)0.0,
1647                        TRUE);
1648             rightFace.dx = -1;  /* sleezy hack to make it work */
1649             miLineArc (pDrawable, pGC, pixel, spanData,
1650                        (LineFacePtr) NULL, &rightFace,
1651                        (double)0.0, (double)0.0,
1652                        TRUE);
1653         }
1654     }
1655     if (spanData)
1656         miCleanupSpanData (pDrawable, pGC, spanData);
1657 }
1658
1659 #define V_TOP       0
1660 #define V_RIGHT     1
1661 #define V_BOTTOM    2
1662 #define V_LEFT      3
1663
1664 static void
1665 miWideDashSegment (pDrawable, pGC, spanData, pDashOffset, pDashIndex,
1666            x1, y1, x2, y2, projectLeft, projectRight, leftFace, rightFace)
1667     DrawablePtr     pDrawable;
1668     register GCPtr  pGC;
1669     int             *pDashOffset, *pDashIndex;
1670     SpanDataPtr     spanData;
1671     int             x1, y1, x2, y2;
1672     Bool            projectLeft, projectRight;
1673     LineFacePtr     leftFace, rightFace;
1674 {
1675     int             dashIndex, dashRemain;
1676     unsigned char   *pDash;
1677     double          L, l;
1678     double          k;
1679     PolyVertexRec   vertices[4];
1680     PolyVertexRec   saveRight, saveBottom;
1681     PolySlopeRec    slopes[4];
1682     PolyEdgeRec     left[2], right[2];
1683     LineFaceRec     lcapFace, rcapFace;
1684     int             nleft, nright;
1685     int             h;
1686     int             y;
1687     int             dy, dx;
1688     unsigned long   pixel;
1689     double          LRemain;
1690     double          r;
1691     double          rdx, rdy;
1692     double          dashDx, dashDy;
1693     double          saveK;
1694     Bool            first = TRUE;
1695     double          lcenterx, lcentery, rcenterx, rcentery;
1696     unsigned long   fgPixel, bgPixel;
1697     
1698     dx = x2 - x1;
1699     dy = y2 - y1;
1700     dashIndex = *pDashIndex;
1701     pDash = pGC->dash;
1702     dashRemain = pDash[dashIndex] - *pDashOffset;
1703     fgPixel = pGC->fgPixel;
1704     bgPixel = pGC->bgPixel;
1705     if (pGC->fillStyle == FillOpaqueStippled ||
1706         pGC->fillStyle == FillTiled)
1707     {
1708         bgPixel = fgPixel;
1709     }
1710
1711     l = ((double) pGC->lineWidth) / 2.0;
1712     if (dx == 0)
1713     {
1714         L = dy;
1715         rdx = 0;
1716         rdy = l;
1717         if (dy < 0)
1718         {
1719             L = -dy;
1720             rdy = -l;
1721         }
1722     }
1723     else if (dy == 0)
1724     {
1725         L = dx;
1726         rdx = l;
1727         rdy = 0;
1728         if (dx < 0)
1729         {
1730             L = -dx;
1731             rdx = -l;
1732         }
1733     }
1734     else
1735     {
1736         L = hypot ((double) dx, (double) dy);
1737         r = l / L;
1738
1739         rdx = r * dx;
1740         rdy = r * dy;
1741     }
1742     k = l * L;
1743     LRemain = L;
1744     /* All position comments are relative to a line with dx and dy > 0,
1745      * but the code does not depend on this */
1746     /* top */
1747     slopes[V_TOP].dx = dx;
1748     slopes[V_TOP].dy = dy;
1749     slopes[V_TOP].k = k;
1750     /* right */
1751     slopes[V_RIGHT].dx = -dy;
1752     slopes[V_RIGHT].dy = dx;
1753     slopes[V_RIGHT].k = 0;
1754     /* bottom */
1755     slopes[V_BOTTOM].dx = -dx;
1756     slopes[V_BOTTOM].dy = -dy;
1757     slopes[V_BOTTOM].k = k;
1758     /* left */
1759     slopes[V_LEFT].dx = dy;
1760     slopes[V_LEFT].dy = -dx;
1761     slopes[V_LEFT].k = 0;
1762
1763     /* preload the start coordinates */
1764     vertices[V_RIGHT].x = vertices[V_TOP].x = rdy;
1765     vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx;
1766
1767     vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy;
1768     vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx;
1769
1770     if (projectLeft)
1771     {
1772         vertices[V_TOP].x -= rdx;
1773         vertices[V_TOP].y -= rdy;
1774
1775         vertices[V_LEFT].x -= rdx;
1776         vertices[V_LEFT].y -= rdy;
1777
1778         slopes[V_LEFT].k = rdx * dx + rdy * dy;
1779     }
1780
1781     lcenterx = x1;
1782     lcentery = y1;
1783
1784     if (pGC->capStyle == CapRound)
1785     {
1786         lcapFace.dx = dx;
1787         lcapFace.dy = dy;
1788         lcapFace.x = x1;
1789         lcapFace.y = y1;
1790
1791         rcapFace.dx = -dx;
1792         rcapFace.dy = -dy;
1793         rcapFace.x = x1;
1794         rcapFace.y = y1;
1795     }
1796     while (LRemain > dashRemain)
1797     {
1798         dashDx = (dashRemain * dx) / L;
1799         dashDy = (dashRemain * dy) / L;
1800
1801         rcenterx = lcenterx + dashDx;
1802         rcentery = lcentery + dashDy;
1803
1804         vertices[V_RIGHT].x += dashDx;
1805         vertices[V_RIGHT].y += dashDy;
1806
1807         vertices[V_BOTTOM].x += dashDx;
1808         vertices[V_BOTTOM].y += dashDy;
1809
1810         slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy;
1811
1812         if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))
1813         {
1814             if (pGC->lineStyle == LineOnOffDash &&
1815                 pGC->capStyle == CapProjecting)
1816             {
1817                 saveRight = vertices[V_RIGHT];
1818                 saveBottom = vertices[V_BOTTOM];
1819                 saveK = slopes[V_RIGHT].k;
1820                 
1821                 if (!first)
1822                 {
1823                     vertices[V_TOP].x -= rdx;
1824                     vertices[V_TOP].y -= rdy;
1825     
1826                     vertices[V_LEFT].x -= rdx;
1827                     vertices[V_LEFT].y -= rdy;
1828
1829                     slopes[V_LEFT].k = vertices[V_LEFT].x *
1830                                        slopes[V_LEFT].dy -
1831                                        vertices[V_LEFT].y *
1832                                        slopes[V_LEFT].dx;
1833                 }
1834                 
1835                 vertices[V_RIGHT].x += rdx;
1836                 vertices[V_RIGHT].y += rdy;
1837
1838                 vertices[V_BOTTOM].x += rdx;
1839                 vertices[V_BOTTOM].y += rdy;
1840
1841                 slopes[V_RIGHT].k = vertices[V_RIGHT].x *
1842                                    slopes[V_RIGHT].dy -
1843                                    vertices[V_RIGHT].y *
1844                                    slopes[V_RIGHT].dx;
1845             }
1846             y = miPolyBuildPoly (vertices, slopes, 4, x1, y1,
1847                                  left, right, &nleft, &nright, &h);
1848             pixel = (dashIndex & 1) ? bgPixel : fgPixel;
1849             miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright);
1850
1851             if (pGC->lineStyle == LineOnOffDash)
1852             {
1853                 switch (pGC->capStyle)
1854                 {
1855                 case CapProjecting:
1856                     vertices[V_BOTTOM] = saveBottom;
1857                     vertices[V_RIGHT] = saveRight;
1858                     slopes[V_RIGHT].k = saveK;
1859                     break;
1860                 case CapRound:
1861                     if (!first)
1862                     {
1863                         if (dx < 0)
1864                         {
1865                             lcapFace.xa = -vertices[V_LEFT].x;
1866                             lcapFace.ya = -vertices[V_LEFT].y;
1867                             lcapFace.k = slopes[V_LEFT].k;
1868                         }
1869                         else
1870                         {
1871                             lcapFace.xa = vertices[V_TOP].x;
1872                             lcapFace.ya = vertices[V_TOP].y;
1873                             lcapFace.k = -slopes[V_LEFT].k;
1874                         }
1875                         miLineArc (pDrawable, pGC, pixel, spanData,
1876                                    &lcapFace, (LineFacePtr) NULL,
1877                                    lcenterx, lcentery, FALSE);
1878                     }
1879                     if (dx < 0)
1880                     {
1881                         rcapFace.xa = vertices[V_BOTTOM].x;
1882                         rcapFace.ya = vertices[V_BOTTOM].y;
1883                         rcapFace.k = slopes[V_RIGHT].k;
1884                     }
1885                     else
1886                     {
1887                         rcapFace.xa = -vertices[V_RIGHT].x;
1888                         rcapFace.ya = -vertices[V_RIGHT].y;
1889                         rcapFace.k = -slopes[V_RIGHT].k;
1890                     }
1891                     miLineArc (pDrawable, pGC, pixel, spanData,
1892                                (LineFacePtr) NULL, &rcapFace,
1893                                rcenterx, rcentery, FALSE);
1894                     break;
1895                 }
1896             }
1897         }
1898         LRemain -= dashRemain;
1899         ++dashIndex;
1900         if (dashIndex == pGC->numInDashList)
1901             dashIndex = 0;
1902         dashRemain = pDash[dashIndex];
1903
1904         lcenterx = rcenterx;
1905         lcentery = rcentery;
1906
1907         vertices[V_TOP] = vertices[V_RIGHT];
1908         vertices[V_LEFT] = vertices[V_BOTTOM];
1909         slopes[V_LEFT].k = -slopes[V_RIGHT].k;
1910         first = FALSE;
1911     }
1912
1913     if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))
1914     {
1915         vertices[V_TOP].x -= dx;
1916         vertices[V_TOP].y -= dy;
1917
1918         vertices[V_LEFT].x -= dx;
1919         vertices[V_LEFT].y -= dy;
1920
1921         vertices[V_RIGHT].x = rdy;
1922         vertices[V_RIGHT].y = -rdx;
1923
1924         vertices[V_BOTTOM].x = -rdy;
1925         vertices[V_BOTTOM].y = rdx;
1926
1927         
1928         if (projectRight)
1929         {
1930             vertices[V_RIGHT].x += rdx;
1931             vertices[V_RIGHT].y += rdy;
1932     
1933             vertices[V_BOTTOM].x += rdx;
1934             vertices[V_BOTTOM].y += rdy;
1935             slopes[V_RIGHT].k = vertices[V_RIGHT].x *
1936                                 slopes[V_RIGHT].dy -
1937                                 vertices[V_RIGHT].y *
1938                                 slopes[V_RIGHT].dx;
1939         }
1940         else
1941             slopes[V_RIGHT].k = 0;
1942
1943         if (!first && pGC->lineStyle == LineOnOffDash &&
1944             pGC->capStyle == CapProjecting)
1945         {
1946             vertices[V_TOP].x -= rdx;
1947             vertices[V_TOP].y -= rdy;
1948
1949             vertices[V_LEFT].x -= rdx;
1950             vertices[V_LEFT].y -= rdy;
1951             slopes[V_LEFT].k = vertices[V_LEFT].x *
1952                                slopes[V_LEFT].dy -
1953                                vertices[V_LEFT].y *
1954                                slopes[V_LEFT].dx;
1955         }
1956         else
1957             slopes[V_LEFT].k += dx * dx + dy * dy;
1958
1959
1960         y = miPolyBuildPoly (vertices, slopes, 4, x2, y2,
1961                              left, right, &nleft, &nright, &h);
1962
1963         pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel;
1964         miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright);
1965         if (!first && pGC->lineStyle == LineOnOffDash &&
1966             pGC->capStyle == CapRound)
1967         {
1968             lcapFace.x = x2;
1969             lcapFace.y = y2;
1970             if (dx < 0)
1971             {
1972                 lcapFace.xa = -vertices[V_LEFT].x;
1973                 lcapFace.ya = -vertices[V_LEFT].y;
1974                 lcapFace.k = slopes[V_LEFT].k;
1975             }
1976             else
1977             {
1978                 lcapFace.xa = vertices[V_TOP].x;
1979                 lcapFace.ya = vertices[V_TOP].y;
1980                 lcapFace.k = -slopes[V_LEFT].k;
1981             }
1982             miLineArc (pDrawable, pGC, pixel, spanData,
1983                        &lcapFace, (LineFacePtr) NULL,
1984                        rcenterx, rcentery, FALSE);
1985         }
1986     }
1987     dashRemain = ((double) dashRemain) - LRemain;
1988     if (dashRemain == 0)
1989     {
1990         dashIndex++;
1991         if (dashIndex == pGC->numInDashList)
1992             dashIndex = 0;
1993         dashRemain = pDash[dashIndex];
1994     }
1995
1996     leftFace->x = x1;
1997     leftFace->y = y1;
1998     leftFace->dx = dx;
1999     leftFace->dy = dy;
2000     leftFace->xa = rdy;
2001     leftFace->ya = -rdx;
2002     leftFace->k = k;
2003
2004     rightFace->x = x2;
2005     rightFace->y = y2;
2006     rightFace->dx = -dx;
2007     rightFace->dy = -dy;
2008     rightFace->xa = -rdy;
2009     rightFace->ya = rdx;
2010     rightFace->k = k;
2011
2012     *pDashIndex = dashIndex;
2013     *pDashOffset = pDash[dashIndex] - dashRemain;
2014 }
2015
2016 void
2017 miWideDash (pDrawable, pGC, mode, npt, pPts)
2018     DrawablePtr pDrawable;
2019     register GCPtr pGC;
2020     int         mode;
2021     register int npt;
2022     register DDXPointPtr pPts;
2023 {
2024     int             x1, y1, x2, y2;
2025     unsigned long   pixel;
2026     Bool            projectLeft, projectRight;
2027     LineFaceRec     leftFace, rightFace, prevRightFace;
2028     LineFaceRec     firstFace;
2029     int             first;
2030     int             dashIndex, dashOffset;
2031     register int    prevDashIndex;
2032     SpanDataRec     spanDataRec;
2033     SpanDataPtr     spanData;
2034     Bool            somethingDrawn = FALSE;
2035     Bool            selfJoin;
2036     Bool            endIsFg, startIsFg, firstIsFg = FALSE, prevIsFg;
2037
2038     /* XXX backward compatibility */
2039     if (pGC->lineWidth == 0)
2040     {
2041         miZeroDashLine (pDrawable, pGC, mode, npt, pPts);
2042         return;
2043     }
2044     if (pGC->lineStyle == LineDoubleDash && 
2045         (pGC->fillStyle == FillOpaqueStippled || pGC->fillStyle == FillTiled))
2046     {
2047         miWideLine (pDrawable, pGC, mode, npt, pPts);
2048         return;
2049     }
2050     if (npt == 0)
2051         return;
2052     spanData = miSetupSpanData (pGC, &spanDataRec, npt);
2053     x2 = pPts->x;
2054     y2 = pPts->y;
2055     first = TRUE;
2056     selfJoin = FALSE;
2057     if (mode == CoordModePrevious)
2058     {
2059         int nptTmp;
2060         DDXPointPtr pPtsTmp;
2061
2062         x1 = x2;
2063         y1 = y2;
2064         nptTmp = npt;
2065         pPtsTmp = pPts + 1;
2066         while (--nptTmp)
2067         {
2068             x1 += pPtsTmp->x;
2069             y1 += pPtsTmp->y;
2070             ++pPtsTmp;
2071         }
2072         if (x2 == x1 && y2 == y1)
2073             selfJoin = TRUE;
2074     }
2075     else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y)
2076     {
2077         selfJoin = TRUE;
2078     }
2079     projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
2080     projectRight = FALSE;
2081     dashIndex = 0;
2082     dashOffset = 0;
2083     miStepDash ((int)pGC->dashOffset, &dashIndex,
2084                 pGC->dash, (int)pGC->numInDashList, &dashOffset);
2085     while (--npt)
2086     {
2087         x1 = x2;
2088         y1 = y2;
2089         ++pPts;
2090         x2 = pPts->x;
2091         y2 = pPts->y;
2092         if (mode == CoordModePrevious)
2093         {
2094             x2 += x1;
2095             y2 += y1;
2096         }
2097         if (x1 != x2 || y1 != y2)
2098         {
2099             somethingDrawn = TRUE;
2100             if (npt == 1 && pGC->capStyle == CapProjecting && 
2101                 (!selfJoin || !firstIsFg))
2102                 projectRight = TRUE;
2103             prevDashIndex = dashIndex;
2104             miWideDashSegment (pDrawable, pGC, spanData, &dashOffset, &dashIndex,
2105                                 x1, y1, x2, y2,
2106                                 projectLeft, projectRight, &leftFace, &rightFace);
2107             startIsFg = !(prevDashIndex & 1);
2108             endIsFg = (dashIndex & 1) ^ (dashOffset != 0);
2109             if (pGC->lineStyle == LineDoubleDash || startIsFg)
2110             {
2111                 pixel = startIsFg ? pGC->fgPixel : pGC->bgPixel;
2112                 if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg))
2113                 {
2114                     if (first && selfJoin)
2115                     {
2116                         firstFace = leftFace;
2117                         firstIsFg = startIsFg;
2118                     }
2119                     else if (pGC->capStyle == CapRound)
2120                         miLineArc (pDrawable, pGC, pixel, spanData,
2121                                    &leftFace, (LineFacePtr) NULL,
2122                                    (double)0.0, (double)0.0, TRUE);
2123                 }
2124                 else
2125                 {
2126                     miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace,
2127                                 &prevRightFace);
2128                 }
2129             }
2130             prevRightFace = rightFace;
2131             prevIsFg = endIsFg;
2132             first = FALSE;
2133             projectLeft = FALSE;
2134         }
2135         if (npt == 1 && somethingDrawn)
2136         {
2137             if (pGC->lineStyle == LineDoubleDash || endIsFg)
2138             {
2139                 pixel = endIsFg ? pGC->fgPixel : pGC->bgPixel;
2140                 if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg))
2141                 {
2142                     miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace,
2143                                 &rightFace);
2144                 }
2145                 else 
2146                 {
2147                     if (pGC->capStyle == CapRound)
2148                         miLineArc (pDrawable, pGC, pixel, spanData,
2149                                     (LineFacePtr) NULL, &rightFace,
2150                                     (double)0.0, (double)0.0, TRUE);
2151                 }
2152             }
2153             else
2154             {
2155                 /* glue a cap to the start of the line if
2156                  * we're OnOffDash and ended on odd dash
2157                  */
2158                 if (selfJoin && firstIsFg)
2159                 {
2160                     pixel = pGC->fgPixel;
2161                     if (pGC->capStyle == CapProjecting)
2162                         miLineProjectingCap (pDrawable, pGC, pixel, spanData,
2163                                     &firstFace, TRUE,
2164                                     (double)0.0, (double)0.0, TRUE);
2165                     else if (pGC->capStyle == CapRound)
2166                         miLineArc (pDrawable, pGC, pixel, spanData,
2167                                     &firstFace, (LineFacePtr) NULL,
2168                                     (double)0.0, (double)0.0, TRUE);
2169                 }
2170             }
2171         }
2172     }
2173     /* handle crock where all points are coincident */
2174     if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)))
2175     {
2176         /* not the same as endIsFg computation above */
2177         pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel;
2178         switch (pGC->capStyle) {
2179         case CapRound:
2180             miLineArc (pDrawable, pGC, pixel, spanData,
2181                        (LineFacePtr) NULL, (LineFacePtr) NULL,
2182                        (double)x2, (double)y2,
2183                        FALSE);
2184             break;
2185         case CapProjecting:
2186             x1 = pGC->lineWidth;
2187             miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
2188                                   x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1);
2189             break;
2190         }
2191     }
2192     if (spanData)
2193         miCleanupSpanData (pDrawable, pGC, spanData);
2194 }
2195
2196 /* these are stubs to allow old ddx ValidateGCs to work without change */
2197
2198 void
2199 miMiter()
2200 {
2201 }
2202
2203 void
2204 miNotMiter()
2205 {
2206 }