miwideline.c revision 4642e01f
105b261ecSmrg/* 205b261ecSmrg 305b261ecSmrgCopyright 1988, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included 1205b261ecSmrgin all copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1505b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1605b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 1705b261ecSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 1805b261ecSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1905b261ecSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2005b261ecSmrgOTHER DEALINGS IN THE SOFTWARE. 2105b261ecSmrg 2205b261ecSmrgExcept as contained in this notice, the name of The Open Group shall 2305b261ecSmrgnot be used in advertising or otherwise to promote the sale, use or 2405b261ecSmrgother dealings in this Software without prior written authorization 2505b261ecSmrgfrom The Open Group. 2605b261ecSmrg 2705b261ecSmrg*/ 2805b261ecSmrg 2905b261ecSmrg/* Author: Keith Packard, MIT X Consortium */ 3005b261ecSmrg 3105b261ecSmrg/* 3205b261ecSmrg * Mostly integer wideline code. Uses a technique similar to 3305b261ecSmrg * bresenham zero-width lines, except walks an X edge 3405b261ecSmrg */ 3505b261ecSmrg 3605b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3705b261ecSmrg#include <dix-config.h> 3805b261ecSmrg#endif 3905b261ecSmrg 4005b261ecSmrg#include <stdio.h> 4105b261ecSmrg#ifdef _XOPEN_SOURCE 4205b261ecSmrg#include <math.h> 4305b261ecSmrg#else 4405b261ecSmrg#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */ 4505b261ecSmrg#include <math.h> 4605b261ecSmrg#undef _XOPEN_SOURCE 4705b261ecSmrg#endif 4805b261ecSmrg#include <X11/X.h> 4905b261ecSmrg#include "windowstr.h" 5005b261ecSmrg#include "gcstruct.h" 5105b261ecSmrg#include "regionstr.h" 5205b261ecSmrg#include "miwideline.h" 5305b261ecSmrg#include "mi.h" 5405b261ecSmrg 5505b261ecSmrgstatic void miLineArc(DrawablePtr pDraw, GCPtr pGC, 5605b261ecSmrg unsigned long pixel, SpanDataPtr spanData, 5705b261ecSmrg LineFacePtr leftFace, 5805b261ecSmrg LineFacePtr rightFace, 5905b261ecSmrg double xorg, double yorg, Bool isInt); 6005b261ecSmrg 6105b261ecSmrg 6205b261ecSmrg/* 6305b261ecSmrg * spans-based polygon filler 6405b261ecSmrg */ 6505b261ecSmrg 6605b261ecSmrgstatic void 6705b261ecSmrgmiFillPolyHelper (DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel, 6805b261ecSmrg SpanDataPtr spanData, int y, int overall_height, 6905b261ecSmrg PolyEdgePtr left, PolyEdgePtr right, 7005b261ecSmrg int left_count, int right_count) 7105b261ecSmrg{ 7205b261ecSmrg int left_x = 0, left_e = 0; 7305b261ecSmrg int left_stepx = 0; 7405b261ecSmrg int left_signdx = 0; 7505b261ecSmrg int left_dy = 0, left_dx = 0; 7605b261ecSmrg 7705b261ecSmrg int right_x = 0, right_e = 0; 7805b261ecSmrg int right_stepx = 0; 7905b261ecSmrg int right_signdx = 0; 8005b261ecSmrg int right_dy = 0, right_dx = 0; 8105b261ecSmrg 8205b261ecSmrg int height = 0; 8305b261ecSmrg int left_height = 0, right_height = 0; 8405b261ecSmrg 8505b261ecSmrg DDXPointPtr ppt; 8605b261ecSmrg DDXPointPtr pptInit = NULL; 8705b261ecSmrg int *pwidth; 8805b261ecSmrg int *pwidthInit = NULL; 8905b261ecSmrg XID oldPixel; 9005b261ecSmrg int xorg; 9105b261ecSmrg Spans spanRec; 9205b261ecSmrg 9305b261ecSmrg left_height = 0; 9405b261ecSmrg right_height = 0; 9505b261ecSmrg 9605b261ecSmrg if (!spanData) 9705b261ecSmrg { 984642e01fSmrg pptInit = (DDXPointPtr) xalloc (overall_height * sizeof(*ppt)); 9905b261ecSmrg if (!pptInit) 10005b261ecSmrg return; 1014642e01fSmrg pwidthInit = (int *) xalloc (overall_height * sizeof(*pwidth)); 10205b261ecSmrg if (!pwidthInit) 10305b261ecSmrg { 1044642e01fSmrg xfree (pptInit); 10505b261ecSmrg return; 10605b261ecSmrg } 10705b261ecSmrg ppt = pptInit; 10805b261ecSmrg pwidth = pwidthInit; 10905b261ecSmrg oldPixel = pGC->fgPixel; 11005b261ecSmrg if (pixel != oldPixel) 11105b261ecSmrg { 11205b261ecSmrg XID tmpPixel = (XID)pixel; 11305b261ecSmrg DoChangeGC (pGC, GCForeground, &tmpPixel, FALSE); 11405b261ecSmrg ValidateGC (pDrawable, pGC); 11505b261ecSmrg } 11605b261ecSmrg } 11705b261ecSmrg else 11805b261ecSmrg { 11905b261ecSmrg spanRec.points = (DDXPointPtr) xalloc (overall_height * sizeof (*ppt)); 12005b261ecSmrg if (!spanRec.points) 12105b261ecSmrg return; 12205b261ecSmrg spanRec.widths = (int *) xalloc (overall_height * sizeof (int)); 12305b261ecSmrg if (!spanRec.widths) 12405b261ecSmrg { 12505b261ecSmrg xfree (spanRec.points); 12605b261ecSmrg return; 12705b261ecSmrg } 12805b261ecSmrg ppt = spanRec.points; 12905b261ecSmrg pwidth = spanRec.widths; 13005b261ecSmrg } 13105b261ecSmrg 13205b261ecSmrg xorg = 0; 13305b261ecSmrg if (pGC->miTranslate) 13405b261ecSmrg { 13505b261ecSmrg y += pDrawable->y; 13605b261ecSmrg xorg = pDrawable->x; 13705b261ecSmrg } 13805b261ecSmrg while ((left_count || left_height) && 13905b261ecSmrg (right_count || right_height)) 14005b261ecSmrg { 14105b261ecSmrg MIPOLYRELOADLEFT 14205b261ecSmrg MIPOLYRELOADRIGHT 14305b261ecSmrg 14405b261ecSmrg height = left_height; 14505b261ecSmrg if (height > right_height) 14605b261ecSmrg height = right_height; 14705b261ecSmrg 14805b261ecSmrg left_height -= height; 14905b261ecSmrg right_height -= height; 15005b261ecSmrg 15105b261ecSmrg while (--height >= 0) 15205b261ecSmrg { 15305b261ecSmrg if (right_x >= left_x) 15405b261ecSmrg { 15505b261ecSmrg ppt->y = y; 15605b261ecSmrg ppt->x = left_x + xorg; 15705b261ecSmrg ppt++; 15805b261ecSmrg *pwidth++ = right_x - left_x + 1; 15905b261ecSmrg } 16005b261ecSmrg y++; 16105b261ecSmrg 16205b261ecSmrg MIPOLYSTEPLEFT 16305b261ecSmrg 16405b261ecSmrg MIPOLYSTEPRIGHT 16505b261ecSmrg } 16605b261ecSmrg } 16705b261ecSmrg if (!spanData) 16805b261ecSmrg { 16905b261ecSmrg (*pGC->ops->FillSpans) (pDrawable, pGC, ppt - pptInit, pptInit, pwidthInit, TRUE); 1704642e01fSmrg xfree (pwidthInit); 1714642e01fSmrg xfree (pptInit); 17205b261ecSmrg if (pixel != oldPixel) 17305b261ecSmrg { 17405b261ecSmrg DoChangeGC (pGC, GCForeground, &oldPixel, FALSE); 17505b261ecSmrg ValidateGC (pDrawable, pGC); 17605b261ecSmrg } 17705b261ecSmrg } 17805b261ecSmrg else 17905b261ecSmrg { 18005b261ecSmrg spanRec.count = ppt - spanRec.points; 18105b261ecSmrg AppendSpanGroup (pGC, pixel, &spanRec, spanData) 18205b261ecSmrg } 18305b261ecSmrg} 18405b261ecSmrg 18505b261ecSmrgstatic void 18605b261ecSmrgmiFillRectPolyHelper ( 18705b261ecSmrg DrawablePtr pDrawable, 18805b261ecSmrg GCPtr pGC, 18905b261ecSmrg unsigned long pixel, 19005b261ecSmrg SpanDataPtr spanData, 19105b261ecSmrg int x, 19205b261ecSmrg int y, 19305b261ecSmrg int w, 19405b261ecSmrg int h) 19505b261ecSmrg{ 19605b261ecSmrg DDXPointPtr ppt; 19705b261ecSmrg int *pwidth; 19805b261ecSmrg XID oldPixel; 19905b261ecSmrg Spans spanRec; 20005b261ecSmrg xRectangle rect; 20105b261ecSmrg 20205b261ecSmrg if (!spanData) 20305b261ecSmrg { 20405b261ecSmrg rect.x = x; 20505b261ecSmrg rect.y = y; 20605b261ecSmrg rect.width = w; 20705b261ecSmrg rect.height = h; 20805b261ecSmrg oldPixel = pGC->fgPixel; 20905b261ecSmrg if (pixel != oldPixel) 21005b261ecSmrg { 21105b261ecSmrg XID tmpPixel = (XID)pixel; 21205b261ecSmrg DoChangeGC (pGC, GCForeground, &tmpPixel, FALSE); 21305b261ecSmrg ValidateGC (pDrawable, pGC); 21405b261ecSmrg } 21505b261ecSmrg (*pGC->ops->PolyFillRect) (pDrawable, pGC, 1, &rect); 21605b261ecSmrg if (pixel != oldPixel) 21705b261ecSmrg { 21805b261ecSmrg DoChangeGC (pGC, GCForeground, &oldPixel, FALSE); 21905b261ecSmrg ValidateGC (pDrawable, pGC); 22005b261ecSmrg } 22105b261ecSmrg } 22205b261ecSmrg else 22305b261ecSmrg { 22405b261ecSmrg spanRec.points = (DDXPointPtr) xalloc (h * sizeof (*ppt)); 22505b261ecSmrg if (!spanRec.points) 22605b261ecSmrg return; 22705b261ecSmrg spanRec.widths = (int *) xalloc (h * sizeof (int)); 22805b261ecSmrg if (!spanRec.widths) 22905b261ecSmrg { 23005b261ecSmrg xfree (spanRec.points); 23105b261ecSmrg return; 23205b261ecSmrg } 23305b261ecSmrg ppt = spanRec.points; 23405b261ecSmrg pwidth = spanRec.widths; 23505b261ecSmrg 23605b261ecSmrg if (pGC->miTranslate) 23705b261ecSmrg { 23805b261ecSmrg y += pDrawable->y; 23905b261ecSmrg x += pDrawable->x; 24005b261ecSmrg } 24105b261ecSmrg while (h--) 24205b261ecSmrg { 24305b261ecSmrg ppt->x = x; 24405b261ecSmrg ppt->y = y; 24505b261ecSmrg ppt++; 24605b261ecSmrg *pwidth++ = w; 24705b261ecSmrg y++; 24805b261ecSmrg } 24905b261ecSmrg spanRec.count = ppt - spanRec.points; 25005b261ecSmrg AppendSpanGroup (pGC, pixel, &spanRec, spanData) 25105b261ecSmrg } 25205b261ecSmrg} 25305b261ecSmrg 25405b261ecSmrg_X_EXPORT /* static */ int 2554642e01fSmrgmiPolyBuildEdge ( 2564642e01fSmrg double x0, 2574642e01fSmrg double y0, 2584642e01fSmrg double k, /* x0 * dy - y0 * dx */ 2594642e01fSmrg int dx, 2604642e01fSmrg int dy, 2614642e01fSmrg int xi, 2624642e01fSmrg int yi, 2634642e01fSmrg int left, 2644642e01fSmrg PolyEdgePtr edge) 26505b261ecSmrg{ 26605b261ecSmrg int x, y, e; 26705b261ecSmrg int xady; 26805b261ecSmrg 26905b261ecSmrg if (dy < 0) 27005b261ecSmrg { 27105b261ecSmrg dy = -dy; 27205b261ecSmrg dx = -dx; 27305b261ecSmrg k = -k; 27405b261ecSmrg } 27505b261ecSmrg 27605b261ecSmrg#ifdef NOTDEF 27705b261ecSmrg { 27805b261ecSmrg double realk, kerror; 27905b261ecSmrg realk = x0 * dy - y0 * dx; 28005b261ecSmrg kerror = Fabs (realk - k); 28105b261ecSmrg if (kerror > .1) 28205b261ecSmrg printf ("realk: %g k: %g\n", realk, k); 28305b261ecSmrg } 28405b261ecSmrg#endif 28505b261ecSmrg y = ICEIL (y0); 28605b261ecSmrg xady = ICEIL (k) + y * dx; 28705b261ecSmrg 28805b261ecSmrg if (xady <= 0) 28905b261ecSmrg x = - (-xady / dy) - 1; 29005b261ecSmrg else 29105b261ecSmrg x = (xady - 1) / dy; 29205b261ecSmrg 29305b261ecSmrg e = xady - x * dy; 29405b261ecSmrg 29505b261ecSmrg if (dx >= 0) 29605b261ecSmrg { 29705b261ecSmrg edge->signdx = 1; 29805b261ecSmrg edge->stepx = dx / dy; 29905b261ecSmrg edge->dx = dx % dy; 30005b261ecSmrg } 30105b261ecSmrg else 30205b261ecSmrg { 30305b261ecSmrg edge->signdx = -1; 30405b261ecSmrg edge->stepx = - (-dx / dy); 30505b261ecSmrg edge->dx = -dx % dy; 30605b261ecSmrg e = dy - e + 1; 30705b261ecSmrg } 30805b261ecSmrg edge->dy = dy; 30905b261ecSmrg edge->x = x + left + xi; 31005b261ecSmrg edge->e = e - dy; /* bias to compare against 0 instead of dy */ 31105b261ecSmrg return y + yi; 31205b261ecSmrg} 31305b261ecSmrg 31405b261ecSmrg#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr))) 31505b261ecSmrg 31605b261ecSmrg_X_EXPORT /* static */ int 3174642e01fSmrgmiPolyBuildPoly ( 3184642e01fSmrg PolyVertexPtr vertices, 3194642e01fSmrg PolySlopePtr slopes, 3204642e01fSmrg int count, 3214642e01fSmrg int xi, 3224642e01fSmrg int yi, 3234642e01fSmrg PolyEdgePtr left, 3244642e01fSmrg PolyEdgePtr right, 3254642e01fSmrg int *pnleft, 3264642e01fSmrg int *pnright, 3274642e01fSmrg int *h) 32805b261ecSmrg{ 32905b261ecSmrg int top, bottom; 33005b261ecSmrg double miny, maxy; 33105b261ecSmrg int i; 33205b261ecSmrg int j; 33305b261ecSmrg int clockwise; 33405b261ecSmrg int slopeoff; 33505b261ecSmrg int s; 33605b261ecSmrg int nright, nleft; 33705b261ecSmrg int y, lasty = 0, bottomy, topy = 0; 33805b261ecSmrg 33905b261ecSmrg /* find the top of the polygon */ 34005b261ecSmrg maxy = miny = vertices[0].y; 34105b261ecSmrg bottom = top = 0; 34205b261ecSmrg for (i = 1; i < count; i++) 34305b261ecSmrg { 34405b261ecSmrg if (vertices[i].y < miny) 34505b261ecSmrg { 34605b261ecSmrg top = i; 34705b261ecSmrg miny = vertices[i].y; 34805b261ecSmrg } 34905b261ecSmrg if (vertices[i].y >= maxy) 35005b261ecSmrg { 35105b261ecSmrg bottom = i; 35205b261ecSmrg maxy = vertices[i].y; 35305b261ecSmrg } 35405b261ecSmrg } 35505b261ecSmrg clockwise = 1; 35605b261ecSmrg slopeoff = 0; 35705b261ecSmrg 35805b261ecSmrg i = top; 35905b261ecSmrg j = StepAround (top, -1, count); 36005b261ecSmrg 36105b261ecSmrg if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx) 36205b261ecSmrg { 36305b261ecSmrg clockwise = -1; 36405b261ecSmrg slopeoff = -1; 36505b261ecSmrg } 36605b261ecSmrg 36705b261ecSmrg bottomy = ICEIL (maxy) + yi; 36805b261ecSmrg 36905b261ecSmrg nright = 0; 37005b261ecSmrg 37105b261ecSmrg s = StepAround (top, slopeoff, count); 37205b261ecSmrg i = top; 37305b261ecSmrg while (i != bottom) 37405b261ecSmrg { 37505b261ecSmrg if (slopes[s].dy != 0) 37605b261ecSmrg { 37705b261ecSmrg y = miPolyBuildEdge (vertices[i].x, vertices[i].y, 37805b261ecSmrg slopes[s].k, 37905b261ecSmrg slopes[s].dx, slopes[s].dy, 38005b261ecSmrg xi, yi, 0, 38105b261ecSmrg &right[nright]); 38205b261ecSmrg if (nright != 0) 38305b261ecSmrg right[nright-1].height = y - lasty; 38405b261ecSmrg else 38505b261ecSmrg topy = y; 38605b261ecSmrg nright++; 38705b261ecSmrg lasty = y; 38805b261ecSmrg } 38905b261ecSmrg 39005b261ecSmrg i = StepAround (i, clockwise, count); 39105b261ecSmrg s = StepAround (s, clockwise, count); 39205b261ecSmrg } 39305b261ecSmrg if (nright != 0) 39405b261ecSmrg right[nright-1].height = bottomy - lasty; 39505b261ecSmrg 39605b261ecSmrg if (slopeoff == 0) 39705b261ecSmrg slopeoff = -1; 39805b261ecSmrg else 39905b261ecSmrg slopeoff = 0; 40005b261ecSmrg 40105b261ecSmrg nleft = 0; 40205b261ecSmrg s = StepAround (top, slopeoff, count); 40305b261ecSmrg i = top; 40405b261ecSmrg while (i != bottom) 40505b261ecSmrg { 40605b261ecSmrg if (slopes[s].dy != 0) 40705b261ecSmrg { 40805b261ecSmrg y = miPolyBuildEdge (vertices[i].x, vertices[i].y, 40905b261ecSmrg slopes[s].k, 41005b261ecSmrg slopes[s].dx, slopes[s].dy, xi, yi, 1, 41105b261ecSmrg &left[nleft]); 41205b261ecSmrg 41305b261ecSmrg if (nleft != 0) 41405b261ecSmrg left[nleft-1].height = y - lasty; 41505b261ecSmrg nleft++; 41605b261ecSmrg lasty = y; 41705b261ecSmrg } 41805b261ecSmrg i = StepAround (i, -clockwise, count); 41905b261ecSmrg s = StepAround (s, -clockwise, count); 42005b261ecSmrg } 42105b261ecSmrg if (nleft != 0) 42205b261ecSmrg left[nleft-1].height = bottomy - lasty; 42305b261ecSmrg *pnleft = nleft; 42405b261ecSmrg *pnright = nright; 42505b261ecSmrg *h = bottomy - topy; 42605b261ecSmrg return topy; 42705b261ecSmrg} 42805b261ecSmrg 42905b261ecSmrgstatic void 43005b261ecSmrgmiLineOnePoint ( 43105b261ecSmrg DrawablePtr pDrawable, 43205b261ecSmrg GCPtr pGC, 43305b261ecSmrg unsigned long pixel, 43405b261ecSmrg SpanDataPtr spanData, 43505b261ecSmrg int x, 43605b261ecSmrg int y) 43705b261ecSmrg{ 43805b261ecSmrg DDXPointRec pt; 43905b261ecSmrg int wid; 44005b261ecSmrg unsigned long oldPixel; 44105b261ecSmrg 44205b261ecSmrg MILINESETPIXEL (pDrawable, pGC, pixel, oldPixel); 44305b261ecSmrg if (pGC->fillStyle == FillSolid) 44405b261ecSmrg { 44505b261ecSmrg pt.x = x; 44605b261ecSmrg pt.y = y; 44705b261ecSmrg (*pGC->ops->PolyPoint) (pDrawable, pGC, CoordModeOrigin, 1, &pt); 44805b261ecSmrg } 44905b261ecSmrg else 45005b261ecSmrg { 45105b261ecSmrg wid = 1; 45205b261ecSmrg if (pGC->miTranslate) 45305b261ecSmrg { 45405b261ecSmrg x += pDrawable->x; 45505b261ecSmrg y += pDrawable->y; 45605b261ecSmrg } 45705b261ecSmrg pt.x = x; 45805b261ecSmrg pt.y = y; 45905b261ecSmrg (*pGC->ops->FillSpans) (pDrawable, pGC, 1, &pt, &wid, TRUE); 46005b261ecSmrg } 46105b261ecSmrg MILINERESETPIXEL (pDrawable, pGC, pixel, oldPixel); 46205b261ecSmrg} 46305b261ecSmrg 46405b261ecSmrgstatic void 46505b261ecSmrgmiLineJoin ( 46605b261ecSmrg DrawablePtr pDrawable, 46705b261ecSmrg GCPtr pGC, 46805b261ecSmrg unsigned long pixel, 46905b261ecSmrg SpanDataPtr spanData, 47005b261ecSmrg LineFacePtr pLeft, 47105b261ecSmrg LineFacePtr pRight) 47205b261ecSmrg{ 47305b261ecSmrg double mx = 0, my = 0; 47405b261ecSmrg double denom = 0.0; 47505b261ecSmrg PolyVertexRec vertices[4]; 47605b261ecSmrg PolySlopeRec slopes[4]; 47705b261ecSmrg int edgecount; 47805b261ecSmrg PolyEdgeRec left[4], right[4]; 47905b261ecSmrg int nleft, nright; 48005b261ecSmrg int y, height; 48105b261ecSmrg int swapslopes; 48205b261ecSmrg int joinStyle = pGC->joinStyle; 48305b261ecSmrg int lw = pGC->lineWidth; 48405b261ecSmrg 48505b261ecSmrg if (lw == 1 && !spanData) { 48605b261ecSmrg /* See if one of the lines will draw the joining pixel */ 48705b261ecSmrg if (pLeft->dx > 0 || (pLeft->dx == 0 && pLeft->dy > 0)) 48805b261ecSmrg return; 48905b261ecSmrg if (pRight->dx > 0 || (pRight->dx == 0 && pRight->dy > 0)) 49005b261ecSmrg return; 49105b261ecSmrg if (joinStyle != JoinRound) { 49205b261ecSmrg denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; 49305b261ecSmrg if (denom == 0) 49405b261ecSmrg return; /* no join to draw */ 49505b261ecSmrg } 49605b261ecSmrg if (joinStyle != JoinMiter) { 49705b261ecSmrg miLineOnePoint (pDrawable, pGC, pixel, spanData, pLeft->x, pLeft->y); 49805b261ecSmrg return; 49905b261ecSmrg } 50005b261ecSmrg } else { 50105b261ecSmrg if (joinStyle == JoinRound) 50205b261ecSmrg { 50305b261ecSmrg miLineArc(pDrawable, pGC, pixel, spanData, 50405b261ecSmrg pLeft, pRight, 50505b261ecSmrg (double)0.0, (double)0.0, TRUE); 50605b261ecSmrg return; 50705b261ecSmrg } 50805b261ecSmrg denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; 50905b261ecSmrg if (denom == 0.0) 51005b261ecSmrg return; /* no join to draw */ 51105b261ecSmrg } 51205b261ecSmrg 51305b261ecSmrg swapslopes = 0; 51405b261ecSmrg if (denom > 0) 51505b261ecSmrg { 51605b261ecSmrg pLeft->xa = -pLeft->xa; 51705b261ecSmrg pLeft->ya = -pLeft->ya; 51805b261ecSmrg pLeft->dx = -pLeft->dx; 51905b261ecSmrg pLeft->dy = -pLeft->dy; 52005b261ecSmrg } 52105b261ecSmrg else 52205b261ecSmrg { 52305b261ecSmrg swapslopes = 1; 52405b261ecSmrg pRight->xa = -pRight->xa; 52505b261ecSmrg pRight->ya = -pRight->ya; 52605b261ecSmrg pRight->dx = -pRight->dx; 52705b261ecSmrg pRight->dy = -pRight->dy; 52805b261ecSmrg } 52905b261ecSmrg 53005b261ecSmrg vertices[0].x = pRight->xa; 53105b261ecSmrg vertices[0].y = pRight->ya; 53205b261ecSmrg slopes[0].dx = -pRight->dy; 53305b261ecSmrg slopes[0].dy = pRight->dx; 53405b261ecSmrg slopes[0].k = 0; 53505b261ecSmrg 53605b261ecSmrg vertices[1].x = 0; 53705b261ecSmrg vertices[1].y = 0; 53805b261ecSmrg slopes[1].dx = pLeft->dy; 53905b261ecSmrg slopes[1].dy = -pLeft->dx; 54005b261ecSmrg slopes[1].k = 0; 54105b261ecSmrg 54205b261ecSmrg vertices[2].x = pLeft->xa; 54305b261ecSmrg vertices[2].y = pLeft->ya; 54405b261ecSmrg 54505b261ecSmrg if (joinStyle == JoinMiter) 54605b261ecSmrg { 54705b261ecSmrg my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) - 54805b261ecSmrg pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx )) / 54905b261ecSmrg denom; 55005b261ecSmrg if (pLeft->dy != 0) 55105b261ecSmrg { 55205b261ecSmrg mx = pLeft->xa + (my - pLeft->ya) * 55305b261ecSmrg (double) pLeft->dx / (double) pLeft->dy; 55405b261ecSmrg } 55505b261ecSmrg else 55605b261ecSmrg { 55705b261ecSmrg mx = pRight->xa + (my - pRight->ya) * 55805b261ecSmrg (double) pRight->dx / (double) pRight->dy; 55905b261ecSmrg } 56005b261ecSmrg /* check miter limit */ 56105b261ecSmrg if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw) 56205b261ecSmrg joinStyle = JoinBevel; 56305b261ecSmrg } 56405b261ecSmrg 56505b261ecSmrg if (joinStyle == JoinMiter) 56605b261ecSmrg { 56705b261ecSmrg slopes[2].dx = pLeft->dx; 56805b261ecSmrg slopes[2].dy = pLeft->dy; 56905b261ecSmrg slopes[2].k = pLeft->k; 57005b261ecSmrg if (swapslopes) 57105b261ecSmrg { 57205b261ecSmrg slopes[2].dx = -slopes[2].dx; 57305b261ecSmrg slopes[2].dy = -slopes[2].dy; 57405b261ecSmrg slopes[2].k = -slopes[2].k; 57505b261ecSmrg } 57605b261ecSmrg vertices[3].x = mx; 57705b261ecSmrg vertices[3].y = my; 57805b261ecSmrg slopes[3].dx = pRight->dx; 57905b261ecSmrg slopes[3].dy = pRight->dy; 58005b261ecSmrg slopes[3].k = pRight->k; 58105b261ecSmrg if (swapslopes) 58205b261ecSmrg { 58305b261ecSmrg slopes[3].dx = -slopes[3].dx; 58405b261ecSmrg slopes[3].dy = -slopes[3].dy; 58505b261ecSmrg slopes[3].k = -slopes[3].k; 58605b261ecSmrg } 58705b261ecSmrg edgecount = 4; 58805b261ecSmrg } 58905b261ecSmrg else 59005b261ecSmrg { 59105b261ecSmrg double scale, dx, dy, adx, ady; 59205b261ecSmrg 59305b261ecSmrg adx = dx = pRight->xa - pLeft->xa; 59405b261ecSmrg ady = dy = pRight->ya - pLeft->ya; 59505b261ecSmrg if (adx < 0) 59605b261ecSmrg adx = -adx; 59705b261ecSmrg if (ady < 0) 59805b261ecSmrg ady = -ady; 59905b261ecSmrg scale = ady; 60005b261ecSmrg if (adx > ady) 60105b261ecSmrg scale = adx; 60205b261ecSmrg slopes[2].dx = (dx * 65536) / scale; 60305b261ecSmrg slopes[2].dy = (dy * 65536) / scale; 60405b261ecSmrg slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy - 60505b261ecSmrg (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0; 60605b261ecSmrg edgecount = 3; 60705b261ecSmrg } 60805b261ecSmrg 60905b261ecSmrg y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y, 61005b261ecSmrg left, right, &nleft, &nright, &height); 61105b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, height, left, right, nleft, nright); 61205b261ecSmrg} 61305b261ecSmrg 61405b261ecSmrgstatic int 61505b261ecSmrgmiLineArcI ( 61605b261ecSmrg DrawablePtr pDraw, 61705b261ecSmrg GCPtr pGC, 61805b261ecSmrg int xorg, 61905b261ecSmrg int yorg, 62005b261ecSmrg DDXPointPtr points, 62105b261ecSmrg int *widths) 62205b261ecSmrg{ 62305b261ecSmrg DDXPointPtr tpts, bpts; 62405b261ecSmrg int *twids, *bwids; 62505b261ecSmrg int x, y, e, ex, slw; 62605b261ecSmrg 62705b261ecSmrg tpts = points; 62805b261ecSmrg twids = widths; 62905b261ecSmrg if (pGC->miTranslate) 63005b261ecSmrg { 63105b261ecSmrg xorg += pDraw->x; 63205b261ecSmrg yorg += pDraw->y; 63305b261ecSmrg } 63405b261ecSmrg slw = pGC->lineWidth; 63505b261ecSmrg if (slw == 1) 63605b261ecSmrg { 63705b261ecSmrg tpts->x = xorg; 63805b261ecSmrg tpts->y = yorg; 63905b261ecSmrg *twids = 1; 64005b261ecSmrg return 1; 64105b261ecSmrg } 64205b261ecSmrg bpts = tpts + slw; 64305b261ecSmrg bwids = twids + slw; 64405b261ecSmrg y = (slw >> 1) + 1; 64505b261ecSmrg if (slw & 1) 64605b261ecSmrg e = - ((y << 2) + 3); 64705b261ecSmrg else 64805b261ecSmrg e = - (y << 3); 64905b261ecSmrg ex = -4; 65005b261ecSmrg x = 0; 65105b261ecSmrg while (y) 65205b261ecSmrg { 65305b261ecSmrg e += (y << 3) - 4; 65405b261ecSmrg while (e >= 0) 65505b261ecSmrg { 65605b261ecSmrg x++; 65705b261ecSmrg e += (ex = -((x << 3) + 4)); 65805b261ecSmrg } 65905b261ecSmrg y--; 66005b261ecSmrg slw = (x << 1) + 1; 66105b261ecSmrg if ((e == ex) && (slw > 1)) 66205b261ecSmrg slw--; 66305b261ecSmrg tpts->x = xorg - x; 66405b261ecSmrg tpts->y = yorg - y; 66505b261ecSmrg tpts++; 66605b261ecSmrg *twids++ = slw; 66705b261ecSmrg if ((y != 0) && ((slw > 1) || (e != ex))) 66805b261ecSmrg { 66905b261ecSmrg bpts--; 67005b261ecSmrg bpts->x = xorg - x; 67105b261ecSmrg bpts->y = yorg + y; 67205b261ecSmrg *--bwids = slw; 67305b261ecSmrg } 67405b261ecSmrg } 67505b261ecSmrg return (pGC->lineWidth); 67605b261ecSmrg} 67705b261ecSmrg 67805b261ecSmrg#define CLIPSTEPEDGE(edgey,edge,edgeleft) \ 67905b261ecSmrg if (ybase == edgey) \ 68005b261ecSmrg { \ 68105b261ecSmrg if (edgeleft) \ 68205b261ecSmrg { \ 68305b261ecSmrg if (edge->x > xcl) \ 68405b261ecSmrg xcl = edge->x; \ 68505b261ecSmrg } \ 68605b261ecSmrg else \ 68705b261ecSmrg { \ 68805b261ecSmrg if (edge->x < xcr) \ 68905b261ecSmrg xcr = edge->x; \ 69005b261ecSmrg } \ 69105b261ecSmrg edgey++; \ 69205b261ecSmrg edge->x += edge->stepx; \ 69305b261ecSmrg edge->e += edge->dx; \ 69405b261ecSmrg if (edge->e > 0) \ 69505b261ecSmrg { \ 69605b261ecSmrg edge->x += edge->signdx; \ 69705b261ecSmrg edge->e -= edge->dy; \ 69805b261ecSmrg } \ 69905b261ecSmrg } 70005b261ecSmrg 70105b261ecSmrgstatic int 70205b261ecSmrgmiLineArcD ( 70305b261ecSmrg DrawablePtr pDraw, 70405b261ecSmrg GCPtr pGC, 70505b261ecSmrg double xorg, 70605b261ecSmrg double yorg, 70705b261ecSmrg DDXPointPtr points, 70805b261ecSmrg int *widths, 70905b261ecSmrg PolyEdgePtr edge1, 71005b261ecSmrg int edgey1, 71105b261ecSmrg Bool edgeleft1, 71205b261ecSmrg PolyEdgePtr edge2, 71305b261ecSmrg int edgey2, 71405b261ecSmrg Bool edgeleft2) 71505b261ecSmrg{ 71605b261ecSmrg DDXPointPtr pts; 71705b261ecSmrg int *wids; 71805b261ecSmrg double radius, x0, y0, el, er, yk, xlk, xrk, k; 71905b261ecSmrg int xbase, ybase, y, boty, xl, xr, xcl, xcr; 72005b261ecSmrg int ymin, ymax; 72105b261ecSmrg Bool edge1IsMin, edge2IsMin; 72205b261ecSmrg int ymin1, ymin2; 72305b261ecSmrg 72405b261ecSmrg pts = points; 72505b261ecSmrg wids = widths; 72605b261ecSmrg xbase = floor(xorg); 72705b261ecSmrg x0 = xorg - xbase; 72805b261ecSmrg ybase = ICEIL (yorg); 72905b261ecSmrg y0 = yorg - ybase; 73005b261ecSmrg if (pGC->miTranslate) 73105b261ecSmrg { 73205b261ecSmrg xbase += pDraw->x; 73305b261ecSmrg ybase += pDraw->y; 73405b261ecSmrg edge1->x += pDraw->x; 73505b261ecSmrg edge2->x += pDraw->x; 73605b261ecSmrg edgey1 += pDraw->y; 73705b261ecSmrg edgey2 += pDraw->y; 73805b261ecSmrg } 73905b261ecSmrg xlk = x0 + x0 + 1.0; 74005b261ecSmrg xrk = x0 + x0 - 1.0; 74105b261ecSmrg yk = y0 + y0 - 1.0; 74205b261ecSmrg radius = ((double)pGC->lineWidth) / 2.0; 74305b261ecSmrg y = floor(radius - y0 + 1.0); 74405b261ecSmrg ybase -= y; 74505b261ecSmrg ymin = ybase; 74605b261ecSmrg ymax = 65536; 74705b261ecSmrg edge1IsMin = FALSE; 74805b261ecSmrg ymin1 = edgey1; 74905b261ecSmrg if (edge1->dy >= 0) 75005b261ecSmrg { 75105b261ecSmrg if (!edge1->dy) 75205b261ecSmrg { 75305b261ecSmrg if (edgeleft1) 75405b261ecSmrg edge1IsMin = TRUE; 75505b261ecSmrg else 75605b261ecSmrg ymax = edgey1; 75705b261ecSmrg edgey1 = 65536; 75805b261ecSmrg } 75905b261ecSmrg else 76005b261ecSmrg { 76105b261ecSmrg if ((edge1->signdx < 0) == edgeleft1) 76205b261ecSmrg edge1IsMin = TRUE; 76305b261ecSmrg } 76405b261ecSmrg } 76505b261ecSmrg edge2IsMin = FALSE; 76605b261ecSmrg ymin2 = edgey2; 76705b261ecSmrg if (edge2->dy >= 0) 76805b261ecSmrg { 76905b261ecSmrg if (!edge2->dy) 77005b261ecSmrg { 77105b261ecSmrg if (edgeleft2) 77205b261ecSmrg edge2IsMin = TRUE; 77305b261ecSmrg else 77405b261ecSmrg ymax = edgey2; 77505b261ecSmrg edgey2 = 65536; 77605b261ecSmrg } 77705b261ecSmrg else 77805b261ecSmrg { 77905b261ecSmrg if ((edge2->signdx < 0) == edgeleft2) 78005b261ecSmrg edge2IsMin = TRUE; 78105b261ecSmrg } 78205b261ecSmrg } 78305b261ecSmrg if (edge1IsMin) 78405b261ecSmrg { 78505b261ecSmrg ymin = ymin1; 78605b261ecSmrg if (edge2IsMin && ymin1 > ymin2) 78705b261ecSmrg ymin = ymin2; 78805b261ecSmrg } else if (edge2IsMin) 78905b261ecSmrg ymin = ymin2; 79005b261ecSmrg el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0); 79105b261ecSmrg er = el + xrk; 79205b261ecSmrg xl = 1; 79305b261ecSmrg xr = 0; 79405b261ecSmrg if (x0 < 0.5) 79505b261ecSmrg { 79605b261ecSmrg xl = 0; 79705b261ecSmrg el -= xlk; 79805b261ecSmrg } 79905b261ecSmrg boty = (y0 < -0.5) ? 1 : 0; 80005b261ecSmrg if (ybase + y - boty > ymax) 80105b261ecSmrg boty = ymax - ybase - y; 80205b261ecSmrg while (y > boty) 80305b261ecSmrg { 80405b261ecSmrg k = (y << 1) + yk; 80505b261ecSmrg er += k; 80605b261ecSmrg while (er > 0.0) 80705b261ecSmrg { 80805b261ecSmrg xr++; 80905b261ecSmrg er += xrk - (xr << 1); 81005b261ecSmrg } 81105b261ecSmrg el += k; 81205b261ecSmrg while (el >= 0.0) 81305b261ecSmrg { 81405b261ecSmrg xl--; 81505b261ecSmrg el += (xl << 1) - xlk; 81605b261ecSmrg } 81705b261ecSmrg y--; 81805b261ecSmrg ybase++; 81905b261ecSmrg if (ybase < ymin) 82005b261ecSmrg continue; 82105b261ecSmrg xcl = xl + xbase; 82205b261ecSmrg xcr = xr + xbase; 82305b261ecSmrg CLIPSTEPEDGE(edgey1, edge1, edgeleft1); 82405b261ecSmrg CLIPSTEPEDGE(edgey2, edge2, edgeleft2); 82505b261ecSmrg if (xcr >= xcl) 82605b261ecSmrg { 82705b261ecSmrg pts->x = xcl; 82805b261ecSmrg pts->y = ybase; 82905b261ecSmrg pts++; 83005b261ecSmrg *wids++ = xcr - xcl + 1; 83105b261ecSmrg } 83205b261ecSmrg } 83305b261ecSmrg er = xrk - (xr << 1) - er; 83405b261ecSmrg el = (xl << 1) - xlk - el; 83505b261ecSmrg boty = floor(-y0 - radius + 1.0); 83605b261ecSmrg if (ybase + y - boty > ymax) 83705b261ecSmrg boty = ymax - ybase - y; 83805b261ecSmrg while (y > boty) 83905b261ecSmrg { 84005b261ecSmrg k = (y << 1) + yk; 84105b261ecSmrg er -= k; 84205b261ecSmrg while ((er >= 0.0) && (xr >= 0)) 84305b261ecSmrg { 84405b261ecSmrg xr--; 84505b261ecSmrg er += xrk - (xr << 1); 84605b261ecSmrg } 84705b261ecSmrg el -= k; 84805b261ecSmrg while ((el > 0.0) && (xl <= 0)) 84905b261ecSmrg { 85005b261ecSmrg xl++; 85105b261ecSmrg el += (xl << 1) - xlk; 85205b261ecSmrg } 85305b261ecSmrg y--; 85405b261ecSmrg ybase++; 85505b261ecSmrg if (ybase < ymin) 85605b261ecSmrg continue; 85705b261ecSmrg xcl = xl + xbase; 85805b261ecSmrg xcr = xr + xbase; 85905b261ecSmrg CLIPSTEPEDGE(edgey1, edge1, edgeleft1); 86005b261ecSmrg CLIPSTEPEDGE(edgey2, edge2, edgeleft2); 86105b261ecSmrg if (xcr >= xcl) 86205b261ecSmrg { 86305b261ecSmrg pts->x = xcl; 86405b261ecSmrg pts->y = ybase; 86505b261ecSmrg pts++; 86605b261ecSmrg *wids++ = xcr - xcl + 1; 86705b261ecSmrg } 86805b261ecSmrg } 86905b261ecSmrg return (pts - points); 87005b261ecSmrg} 87105b261ecSmrg 87205b261ecSmrgstatic int 87305b261ecSmrgmiRoundJoinFace (LineFacePtr face, PolyEdgePtr edge, Bool *leftEdge) 87405b261ecSmrg{ 87505b261ecSmrg int y; 87605b261ecSmrg int dx, dy; 87705b261ecSmrg double xa, ya; 87805b261ecSmrg Bool left; 87905b261ecSmrg 88005b261ecSmrg dx = -face->dy; 88105b261ecSmrg dy = face->dx; 88205b261ecSmrg xa = face->xa; 88305b261ecSmrg ya = face->ya; 88405b261ecSmrg left = 1; 88505b261ecSmrg if (ya > 0) 88605b261ecSmrg { 88705b261ecSmrg ya = 0.0; 88805b261ecSmrg xa = 0.0; 88905b261ecSmrg } 89005b261ecSmrg if (dy < 0 || (dy == 0 && dx > 0)) 89105b261ecSmrg { 89205b261ecSmrg dx = -dx; 89305b261ecSmrg dy = -dy; 89405b261ecSmrg left = !left; 89505b261ecSmrg } 89605b261ecSmrg if (dx == 0 && dy == 0) 89705b261ecSmrg dy = 1; 89805b261ecSmrg if (dy == 0) 89905b261ecSmrg { 90005b261ecSmrg y = ICEIL (face->ya) + face->y; 90105b261ecSmrg edge->x = -32767; 90205b261ecSmrg edge->stepx = 0; 90305b261ecSmrg edge->signdx = 0; 90405b261ecSmrg edge->e = -1; 90505b261ecSmrg edge->dy = 0; 90605b261ecSmrg edge->dx = 0; 90705b261ecSmrg edge->height = 0; 90805b261ecSmrg } 90905b261ecSmrg else 91005b261ecSmrg { 91105b261ecSmrg y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge); 91205b261ecSmrg edge->height = 32767; 91305b261ecSmrg } 91405b261ecSmrg *leftEdge = !left; 91505b261ecSmrg return y; 91605b261ecSmrg} 91705b261ecSmrg 91805b261ecSmrg_X_EXPORT void 9194642e01fSmrgmiRoundJoinClip (LineFacePtr pLeft, LineFacePtr pRight, 9204642e01fSmrg PolyEdgePtr edge1, PolyEdgePtr edge2, 9214642e01fSmrg int *y1, int *y2, Bool *left1, Bool *left2) 92205b261ecSmrg{ 92305b261ecSmrg double denom; 92405b261ecSmrg 92505b261ecSmrg denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; 92605b261ecSmrg 92705b261ecSmrg if (denom >= 0) 92805b261ecSmrg { 92905b261ecSmrg pLeft->xa = -pLeft->xa; 93005b261ecSmrg pLeft->ya = -pLeft->ya; 93105b261ecSmrg } 93205b261ecSmrg else 93305b261ecSmrg { 93405b261ecSmrg pRight->xa = -pRight->xa; 93505b261ecSmrg pRight->ya = -pRight->ya; 93605b261ecSmrg } 93705b261ecSmrg *y1 = miRoundJoinFace (pLeft, edge1, left1); 93805b261ecSmrg *y2 = miRoundJoinFace (pRight, edge2, left2); 93905b261ecSmrg} 94005b261ecSmrg 94105b261ecSmrg_X_EXPORT int 9424642e01fSmrgmiRoundCapClip (LineFacePtr face, Bool isInt, PolyEdgePtr edge, Bool *leftEdge) 94305b261ecSmrg{ 94405b261ecSmrg int y; 94505b261ecSmrg int dx, dy; 94605b261ecSmrg double xa, ya, k; 94705b261ecSmrg Bool left; 94805b261ecSmrg 94905b261ecSmrg dx = -face->dy; 95005b261ecSmrg dy = face->dx; 95105b261ecSmrg xa = face->xa; 95205b261ecSmrg ya = face->ya; 95305b261ecSmrg k = 0.0; 95405b261ecSmrg if (!isInt) 95505b261ecSmrg k = face->k; 95605b261ecSmrg left = 1; 95705b261ecSmrg if (dy < 0 || (dy == 0 && dx > 0)) 95805b261ecSmrg { 95905b261ecSmrg dx = -dx; 96005b261ecSmrg dy = -dy; 96105b261ecSmrg xa = -xa; 96205b261ecSmrg ya = -ya; 96305b261ecSmrg left = !left; 96405b261ecSmrg } 96505b261ecSmrg if (dx == 0 && dy == 0) 96605b261ecSmrg dy = 1; 96705b261ecSmrg if (dy == 0) 96805b261ecSmrg { 96905b261ecSmrg y = ICEIL (face->ya) + face->y; 97005b261ecSmrg edge->x = -32767; 97105b261ecSmrg edge->stepx = 0; 97205b261ecSmrg edge->signdx = 0; 97305b261ecSmrg edge->e = -1; 97405b261ecSmrg edge->dy = 0; 97505b261ecSmrg edge->dx = 0; 97605b261ecSmrg edge->height = 0; 97705b261ecSmrg } 97805b261ecSmrg else 97905b261ecSmrg { 98005b261ecSmrg y = miPolyBuildEdge (xa, ya, k, dx, dy, face->x, face->y, !left, edge); 98105b261ecSmrg edge->height = 32767; 98205b261ecSmrg } 98305b261ecSmrg *leftEdge = !left; 98405b261ecSmrg return y; 98505b261ecSmrg} 98605b261ecSmrg 98705b261ecSmrgstatic void 98805b261ecSmrgmiLineArc ( 98905b261ecSmrg DrawablePtr pDraw, 99005b261ecSmrg GCPtr pGC, 99105b261ecSmrg unsigned long pixel, 99205b261ecSmrg SpanDataPtr spanData, 99305b261ecSmrg LineFacePtr leftFace, 99405b261ecSmrg LineFacePtr rightFace, 99505b261ecSmrg double xorg, 99605b261ecSmrg double yorg, 99705b261ecSmrg Bool isInt) 99805b261ecSmrg{ 99905b261ecSmrg DDXPointPtr points; 100005b261ecSmrg int *widths; 100105b261ecSmrg int xorgi = 0, yorgi = 0; 100205b261ecSmrg XID oldPixel; 100305b261ecSmrg Spans spanRec; 100405b261ecSmrg int n; 100505b261ecSmrg PolyEdgeRec edge1, edge2; 100605b261ecSmrg int edgey1, edgey2; 100705b261ecSmrg Bool edgeleft1, edgeleft2; 100805b261ecSmrg 100905b261ecSmrg if (isInt) 101005b261ecSmrg { 101105b261ecSmrg xorgi = leftFace ? leftFace->x : rightFace->x; 101205b261ecSmrg yorgi = leftFace ? leftFace->y : rightFace->y; 101305b261ecSmrg } 101405b261ecSmrg edgey1 = 65536; 101505b261ecSmrg edgey2 = 65536; 101605b261ecSmrg edge1.x = 0; /* not used, keep memory checkers happy */ 101705b261ecSmrg edge1.dy = -1; 101805b261ecSmrg edge2.x = 0; /* not used, keep memory checkers happy */ 101905b261ecSmrg edge2.dy = -1; 102005b261ecSmrg edgeleft1 = FALSE; 102105b261ecSmrg edgeleft2 = FALSE; 102205b261ecSmrg if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) && 102305b261ecSmrg ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) || 102405b261ecSmrg (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))) 102505b261ecSmrg { 102605b261ecSmrg if (isInt) 102705b261ecSmrg { 102805b261ecSmrg xorg = (double) xorgi; 102905b261ecSmrg yorg = (double) yorgi; 103005b261ecSmrg } 103105b261ecSmrg if (leftFace && rightFace) 103205b261ecSmrg { 103305b261ecSmrg miRoundJoinClip (leftFace, rightFace, &edge1, &edge2, 103405b261ecSmrg &edgey1, &edgey2, &edgeleft1, &edgeleft2); 103505b261ecSmrg } 103605b261ecSmrg else if (leftFace) 103705b261ecSmrg { 103805b261ecSmrg edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1); 103905b261ecSmrg } 104005b261ecSmrg else if (rightFace) 104105b261ecSmrg { 104205b261ecSmrg edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2); 104305b261ecSmrg } 104405b261ecSmrg isInt = FALSE; 104505b261ecSmrg } 104605b261ecSmrg if (!spanData) 104705b261ecSmrg { 10484642e01fSmrg points = (DDXPointPtr)xalloc(sizeof(DDXPointRec) * pGC->lineWidth); 104905b261ecSmrg if (!points) 105005b261ecSmrg return; 10514642e01fSmrg widths = (int *)xalloc(sizeof(int) * pGC->lineWidth); 105205b261ecSmrg if (!widths) 105305b261ecSmrg { 10544642e01fSmrg xfree(points); 105505b261ecSmrg return; 105605b261ecSmrg } 105705b261ecSmrg oldPixel = pGC->fgPixel; 105805b261ecSmrg if (pixel != oldPixel) 105905b261ecSmrg { 106005b261ecSmrg XID tmpPixel = (XID)pixel; 106105b261ecSmrg DoChangeGC(pGC, GCForeground, &tmpPixel, FALSE); 106205b261ecSmrg ValidateGC (pDraw, pGC); 106305b261ecSmrg } 106405b261ecSmrg } 106505b261ecSmrg else 106605b261ecSmrg { 106705b261ecSmrg points = (DDXPointPtr) xalloc (pGC->lineWidth * sizeof (DDXPointRec)); 106805b261ecSmrg if (!points) 106905b261ecSmrg return; 107005b261ecSmrg widths = (int *) xalloc (pGC->lineWidth * sizeof (int)); 107105b261ecSmrg if (!widths) 107205b261ecSmrg { 107305b261ecSmrg xfree (points); 107405b261ecSmrg return; 107505b261ecSmrg } 107605b261ecSmrg spanRec.points = points; 107705b261ecSmrg spanRec.widths = widths; 107805b261ecSmrg } 107905b261ecSmrg if (isInt) 108005b261ecSmrg n = miLineArcI(pDraw, pGC, xorgi, yorgi, points, widths); 108105b261ecSmrg else 108205b261ecSmrg n = miLineArcD(pDraw, pGC, xorg, yorg, points, widths, 108305b261ecSmrg &edge1, edgey1, edgeleft1, 108405b261ecSmrg &edge2, edgey2, edgeleft2); 108505b261ecSmrg 108605b261ecSmrg if (!spanData) 108705b261ecSmrg { 108805b261ecSmrg (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, TRUE); 10894642e01fSmrg xfree(widths); 10904642e01fSmrg xfree(points); 109105b261ecSmrg if (pixel != oldPixel) 109205b261ecSmrg { 109305b261ecSmrg DoChangeGC(pGC, GCForeground, &oldPixel, FALSE); 109405b261ecSmrg ValidateGC (pDraw, pGC); 109505b261ecSmrg } 109605b261ecSmrg } 109705b261ecSmrg else 109805b261ecSmrg { 109905b261ecSmrg spanRec.count = n; 110005b261ecSmrg AppendSpanGroup (pGC, pixel, &spanRec, spanData) 110105b261ecSmrg } 110205b261ecSmrg} 110305b261ecSmrg 110405b261ecSmrgstatic void 110505b261ecSmrgmiLineProjectingCap (DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel, 110605b261ecSmrg SpanDataPtr spanData, LineFacePtr face, Bool isLeft, 110705b261ecSmrg double xorg, double yorg, Bool isInt) 110805b261ecSmrg{ 110905b261ecSmrg int xorgi = 0, yorgi = 0; 111005b261ecSmrg int lw; 111105b261ecSmrg PolyEdgeRec lefts[2], rights[2]; 111205b261ecSmrg int lefty, righty, topy, bottomy; 111305b261ecSmrg PolyEdgePtr left, right; 111405b261ecSmrg PolyEdgePtr top, bottom; 111505b261ecSmrg double xa,ya; 111605b261ecSmrg double k; 111705b261ecSmrg double xap, yap; 111805b261ecSmrg int dx, dy; 111905b261ecSmrg double projectXoff, projectYoff; 112005b261ecSmrg double maxy; 112105b261ecSmrg int finaly; 112205b261ecSmrg 112305b261ecSmrg if (isInt) 112405b261ecSmrg { 112505b261ecSmrg xorgi = face->x; 112605b261ecSmrg yorgi = face->y; 112705b261ecSmrg } 112805b261ecSmrg lw = pGC->lineWidth; 112905b261ecSmrg dx = face->dx; 113005b261ecSmrg dy = face->dy; 113105b261ecSmrg k = face->k; 113205b261ecSmrg if (dy == 0) 113305b261ecSmrg { 113405b261ecSmrg lefts[0].height = lw; 113505b261ecSmrg lefts[0].x = xorgi; 113605b261ecSmrg if (isLeft) 113705b261ecSmrg lefts[0].x -= (lw >> 1); 113805b261ecSmrg lefts[0].stepx = 0; 113905b261ecSmrg lefts[0].signdx = 1; 114005b261ecSmrg lefts[0].e = -lw; 114105b261ecSmrg lefts[0].dx = 0; 114205b261ecSmrg lefts[0].dy = lw; 114305b261ecSmrg rights[0].height = lw; 114405b261ecSmrg rights[0].x = xorgi; 114505b261ecSmrg if (!isLeft) 114605b261ecSmrg rights[0].x += ((lw + 1) >> 1); 114705b261ecSmrg rights[0].stepx = 0; 114805b261ecSmrg rights[0].signdx = 1; 114905b261ecSmrg rights[0].e = -lw; 115005b261ecSmrg rights[0].dx = 0; 115105b261ecSmrg rights[0].dy = lw; 115205b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, yorgi - (lw >> 1), lw, 115305b261ecSmrg lefts, rights, 1, 1); 115405b261ecSmrg } 115505b261ecSmrg else if (dx == 0) 115605b261ecSmrg { 115705b261ecSmrg if (dy < 0) { 115805b261ecSmrg dy = -dy; 115905b261ecSmrg isLeft = !isLeft; 116005b261ecSmrg } 116105b261ecSmrg topy = yorgi; 116205b261ecSmrg bottomy = yorgi + dy; 116305b261ecSmrg if (isLeft) 116405b261ecSmrg topy -= (lw >> 1); 116505b261ecSmrg else 116605b261ecSmrg bottomy += (lw >> 1); 116705b261ecSmrg lefts[0].height = bottomy - topy; 116805b261ecSmrg lefts[0].x = xorgi - (lw >> 1); 116905b261ecSmrg lefts[0].stepx = 0; 117005b261ecSmrg lefts[0].signdx = 1; 117105b261ecSmrg lefts[0].e = -dy; 117205b261ecSmrg lefts[0].dx = dx; 117305b261ecSmrg lefts[0].dy = dy; 117405b261ecSmrg 117505b261ecSmrg rights[0].height = bottomy - topy; 117605b261ecSmrg rights[0].x = lefts[0].x + (lw-1); 117705b261ecSmrg rights[0].stepx = 0; 117805b261ecSmrg rights[0].signdx = 1; 117905b261ecSmrg rights[0].e = -dy; 118005b261ecSmrg rights[0].dx = dx; 118105b261ecSmrg rights[0].dy = dy; 118205b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, bottomy - topy, lefts, rights, 1, 1); 118305b261ecSmrg } 118405b261ecSmrg else 118505b261ecSmrg { 118605b261ecSmrg xa = face->xa; 118705b261ecSmrg ya = face->ya; 118805b261ecSmrg projectXoff = -ya; 118905b261ecSmrg projectYoff = xa; 119005b261ecSmrg if (dx < 0) 119105b261ecSmrg { 119205b261ecSmrg right = &rights[1]; 119305b261ecSmrg left = &lefts[0]; 119405b261ecSmrg top = &rights[0]; 119505b261ecSmrg bottom = &lefts[1]; 119605b261ecSmrg } 119705b261ecSmrg else 119805b261ecSmrg { 119905b261ecSmrg right = &rights[0]; 120005b261ecSmrg left = &lefts[1]; 120105b261ecSmrg top = &lefts[0]; 120205b261ecSmrg bottom = &rights[1]; 120305b261ecSmrg } 120405b261ecSmrg if (isLeft) 120505b261ecSmrg { 120605b261ecSmrg righty = miPolyBuildEdge (xa, ya, 120705b261ecSmrg k, dx, dy, xorgi, yorgi, 0, right); 120805b261ecSmrg 120905b261ecSmrg xa = -xa; 121005b261ecSmrg ya = -ya; 121105b261ecSmrg k = -k; 121205b261ecSmrg lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 121305b261ecSmrg k, dx, dy, xorgi, yorgi, 1, left); 121405b261ecSmrg if (dx > 0) 121505b261ecSmrg { 121605b261ecSmrg ya = -ya; 121705b261ecSmrg xa = -xa; 121805b261ecSmrg } 121905b261ecSmrg xap = xa - projectXoff; 122005b261ecSmrg yap = ya - projectYoff; 122105b261ecSmrg topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 122205b261ecSmrg -dy, dx, xorgi, yorgi, dx > 0, top); 122305b261ecSmrg bottomy = miPolyBuildEdge (xa, ya, 122405b261ecSmrg 0.0, -dy, dx, xorgi, yorgi, dx < 0, bottom); 122505b261ecSmrg maxy = -ya; 122605b261ecSmrg } 122705b261ecSmrg else 122805b261ecSmrg { 122905b261ecSmrg righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 123005b261ecSmrg k, dx, dy, xorgi, yorgi, 0, right); 123105b261ecSmrg 123205b261ecSmrg xa = -xa; 123305b261ecSmrg ya = -ya; 123405b261ecSmrg k = -k; 123505b261ecSmrg lefty = miPolyBuildEdge (xa, ya, 123605b261ecSmrg k, dx, dy, xorgi, yorgi, 1, left); 123705b261ecSmrg if (dx > 0) 123805b261ecSmrg { 123905b261ecSmrg ya = -ya; 124005b261ecSmrg xa = -xa; 124105b261ecSmrg } 124205b261ecSmrg xap = xa - projectXoff; 124305b261ecSmrg yap = ya - projectYoff; 124405b261ecSmrg topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0, top); 124505b261ecSmrg bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 124605b261ecSmrg -dy, dx, xorgi, xorgi, dx < 0, bottom); 124705b261ecSmrg maxy = -ya + projectYoff; 124805b261ecSmrg } 124905b261ecSmrg finaly = ICEIL(maxy) + yorgi; 125005b261ecSmrg if (dx < 0) 125105b261ecSmrg { 125205b261ecSmrg left->height = bottomy - lefty; 125305b261ecSmrg right->height = finaly - righty; 125405b261ecSmrg top->height = righty - topy; 125505b261ecSmrg } 125605b261ecSmrg else 125705b261ecSmrg { 125805b261ecSmrg right->height = bottomy - righty; 125905b261ecSmrg left->height = finaly - lefty; 126005b261ecSmrg top->height = lefty - topy; 126105b261ecSmrg } 126205b261ecSmrg bottom->height = finaly - bottomy; 126305b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, 126405b261ecSmrg bottom->height + bottomy - topy, lefts, rights, 2, 2); 126505b261ecSmrg } 126605b261ecSmrg} 126705b261ecSmrg 126805b261ecSmrgstatic void 126905b261ecSmrgmiWideSegment ( 127005b261ecSmrg DrawablePtr pDrawable, 127105b261ecSmrg GCPtr pGC, 127205b261ecSmrg unsigned long pixel, 127305b261ecSmrg SpanDataPtr spanData, 127405b261ecSmrg int x1, 127505b261ecSmrg int y1, 127605b261ecSmrg int x2, 127705b261ecSmrg int y2, 127805b261ecSmrg Bool projectLeft, 127905b261ecSmrg Bool projectRight, 128005b261ecSmrg LineFacePtr leftFace, 128105b261ecSmrg LineFacePtr rightFace) 128205b261ecSmrg{ 128305b261ecSmrg double l, L, r; 128405b261ecSmrg double xa, ya; 128505b261ecSmrg double projectXoff = 0.0, projectYoff = 0.0; 128605b261ecSmrg double k; 128705b261ecSmrg double maxy; 128805b261ecSmrg int x, y; 128905b261ecSmrg int dx, dy; 129005b261ecSmrg int finaly; 129105b261ecSmrg PolyEdgePtr left, right; 129205b261ecSmrg PolyEdgePtr top, bottom; 129305b261ecSmrg int lefty, righty, topy, bottomy; 129405b261ecSmrg int signdx; 129505b261ecSmrg PolyEdgeRec lefts[2], rights[2]; 129605b261ecSmrg LineFacePtr tface; 129705b261ecSmrg int lw = pGC->lineWidth; 129805b261ecSmrg 129905b261ecSmrg /* draw top-to-bottom always */ 130005b261ecSmrg if (y2 < y1 || (y2 == y1 && x2 < x1)) 130105b261ecSmrg { 130205b261ecSmrg x = x1; 130305b261ecSmrg x1 = x2; 130405b261ecSmrg x2 = x; 130505b261ecSmrg 130605b261ecSmrg y = y1; 130705b261ecSmrg y1 = y2; 130805b261ecSmrg y2 = y; 130905b261ecSmrg 131005b261ecSmrg x = projectLeft; 131105b261ecSmrg projectLeft = projectRight; 131205b261ecSmrg projectRight = x; 131305b261ecSmrg 131405b261ecSmrg tface = leftFace; 131505b261ecSmrg leftFace = rightFace; 131605b261ecSmrg rightFace = tface; 131705b261ecSmrg } 131805b261ecSmrg 131905b261ecSmrg dy = y2 - y1; 132005b261ecSmrg signdx = 1; 132105b261ecSmrg dx = x2 - x1; 132205b261ecSmrg if (dx < 0) 132305b261ecSmrg signdx = -1; 132405b261ecSmrg 132505b261ecSmrg leftFace->x = x1; 132605b261ecSmrg leftFace->y = y1; 132705b261ecSmrg leftFace->dx = dx; 132805b261ecSmrg leftFace->dy = dy; 132905b261ecSmrg 133005b261ecSmrg rightFace->x = x2; 133105b261ecSmrg rightFace->y = y2; 133205b261ecSmrg rightFace->dx = -dx; 133305b261ecSmrg rightFace->dy = -dy; 133405b261ecSmrg 133505b261ecSmrg if (dy == 0) 133605b261ecSmrg { 133705b261ecSmrg rightFace->xa = 0; 133805b261ecSmrg rightFace->ya = (double) lw / 2.0; 133905b261ecSmrg rightFace->k = -(double) (lw * dx) / 2.0; 134005b261ecSmrg leftFace->xa = 0; 134105b261ecSmrg leftFace->ya = -rightFace->ya; 134205b261ecSmrg leftFace->k = rightFace->k; 134305b261ecSmrg x = x1; 134405b261ecSmrg if (projectLeft) 134505b261ecSmrg x -= (lw >> 1); 134605b261ecSmrg y = y1 - (lw >> 1); 134705b261ecSmrg dx = x2 - x; 134805b261ecSmrg if (projectRight) 134905b261ecSmrg dx += ((lw + 1) >> 1); 135005b261ecSmrg dy = lw; 135105b261ecSmrg miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, 135205b261ecSmrg x, y, dx, dy); 135305b261ecSmrg } 135405b261ecSmrg else if (dx == 0) 135505b261ecSmrg { 135605b261ecSmrg leftFace->xa = (double) lw / 2.0; 135705b261ecSmrg leftFace->ya = 0; 135805b261ecSmrg leftFace->k = (double) (lw * dy) / 2.0; 135905b261ecSmrg rightFace->xa = -leftFace->xa; 136005b261ecSmrg rightFace->ya = 0; 136105b261ecSmrg rightFace->k = leftFace->k; 136205b261ecSmrg y = y1; 136305b261ecSmrg if (projectLeft) 136405b261ecSmrg y -= lw >> 1; 136505b261ecSmrg x = x1 - (lw >> 1); 136605b261ecSmrg dy = y2 - y; 136705b261ecSmrg if (projectRight) 136805b261ecSmrg dy += ((lw + 1) >> 1); 136905b261ecSmrg dx = lw; 137005b261ecSmrg miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, 137105b261ecSmrg x, y, dx, dy); 137205b261ecSmrg } 137305b261ecSmrg else 137405b261ecSmrg { 137505b261ecSmrg l = ((double) lw) / 2.0; 137605b261ecSmrg L = hypot ((double) dx, (double) dy); 137705b261ecSmrg 137805b261ecSmrg if (dx < 0) 137905b261ecSmrg { 138005b261ecSmrg right = &rights[1]; 138105b261ecSmrg left = &lefts[0]; 138205b261ecSmrg top = &rights[0]; 138305b261ecSmrg bottom = &lefts[1]; 138405b261ecSmrg } 138505b261ecSmrg else 138605b261ecSmrg { 138705b261ecSmrg right = &rights[0]; 138805b261ecSmrg left = &lefts[1]; 138905b261ecSmrg top = &lefts[0]; 139005b261ecSmrg bottom = &rights[1]; 139105b261ecSmrg } 139205b261ecSmrg r = l / L; 139305b261ecSmrg 139405b261ecSmrg /* coord of upper bound at integral y */ 139505b261ecSmrg ya = -r * dx; 139605b261ecSmrg xa = r * dy; 139705b261ecSmrg 139805b261ecSmrg if (projectLeft | projectRight) 139905b261ecSmrg { 140005b261ecSmrg projectXoff = -ya; 140105b261ecSmrg projectYoff = xa; 140205b261ecSmrg } 140305b261ecSmrg 140405b261ecSmrg /* xa * dy - ya * dx */ 140505b261ecSmrg k = l * L; 140605b261ecSmrg 140705b261ecSmrg leftFace->xa = xa; 140805b261ecSmrg leftFace->ya = ya; 140905b261ecSmrg leftFace->k = k; 141005b261ecSmrg rightFace->xa = -xa; 141105b261ecSmrg rightFace->ya = -ya; 141205b261ecSmrg rightFace->k = k; 141305b261ecSmrg 141405b261ecSmrg if (projectLeft) 141505b261ecSmrg righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 141605b261ecSmrg k, dx, dy, x1, y1, 0, right); 141705b261ecSmrg else 141805b261ecSmrg righty = miPolyBuildEdge (xa, ya, 141905b261ecSmrg k, dx, dy, x1, y1, 0, right); 142005b261ecSmrg 142105b261ecSmrg /* coord of lower bound at integral y */ 142205b261ecSmrg ya = -ya; 142305b261ecSmrg xa = -xa; 142405b261ecSmrg 142505b261ecSmrg /* xa * dy - ya * dx */ 142605b261ecSmrg k = - k; 142705b261ecSmrg 142805b261ecSmrg if (projectLeft) 142905b261ecSmrg lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 143005b261ecSmrg k, dx, dy, x1, y1, 1, left); 143105b261ecSmrg else 143205b261ecSmrg lefty = miPolyBuildEdge (xa, ya, 143305b261ecSmrg k, dx, dy, x1, y1, 1, left); 143405b261ecSmrg 143505b261ecSmrg /* coord of top face at integral y */ 143605b261ecSmrg 143705b261ecSmrg if (signdx > 0) 143805b261ecSmrg { 143905b261ecSmrg ya = -ya; 144005b261ecSmrg xa = -xa; 144105b261ecSmrg } 144205b261ecSmrg 144305b261ecSmrg if (projectLeft) 144405b261ecSmrg { 144505b261ecSmrg double xap = xa - projectXoff; 144605b261ecSmrg double yap = ya - projectYoff; 144705b261ecSmrg topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 144805b261ecSmrg -dy, dx, x1, y1, dx > 0, top); 144905b261ecSmrg } 145005b261ecSmrg else 145105b261ecSmrg topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top); 145205b261ecSmrg 145305b261ecSmrg /* coord of bottom face at integral y */ 145405b261ecSmrg 145505b261ecSmrg if (projectRight) 145605b261ecSmrg { 145705b261ecSmrg double xap = xa + projectXoff; 145805b261ecSmrg double yap = ya + projectYoff; 145905b261ecSmrg bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 146005b261ecSmrg -dy, dx, x2, y2, dx < 0, bottom); 146105b261ecSmrg maxy = -ya + projectYoff; 146205b261ecSmrg } 146305b261ecSmrg else 146405b261ecSmrg { 146505b261ecSmrg bottomy = miPolyBuildEdge (xa, ya, 146605b261ecSmrg 0.0, -dy, dx, x2, y2, dx < 0, bottom); 146705b261ecSmrg maxy = -ya; 146805b261ecSmrg } 146905b261ecSmrg 147005b261ecSmrg finaly = ICEIL (maxy) + y2; 147105b261ecSmrg 147205b261ecSmrg if (dx < 0) 147305b261ecSmrg { 147405b261ecSmrg left->height = bottomy - lefty; 147505b261ecSmrg right->height = finaly - righty; 147605b261ecSmrg top->height = righty - topy; 147705b261ecSmrg } 147805b261ecSmrg else 147905b261ecSmrg { 148005b261ecSmrg right->height = bottomy - righty; 148105b261ecSmrg left->height = finaly - lefty; 148205b261ecSmrg top->height = lefty - topy; 148305b261ecSmrg } 148405b261ecSmrg bottom->height = finaly - bottomy; 148505b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, 148605b261ecSmrg bottom->height + bottomy - topy, lefts, rights, 2, 2); 148705b261ecSmrg } 148805b261ecSmrg} 148905b261ecSmrg 149005b261ecSmrgstatic SpanDataPtr 149105b261ecSmrgmiSetupSpanData (GCPtr pGC, SpanDataPtr spanData, int npt) 149205b261ecSmrg{ 149305b261ecSmrg if ((npt < 3 && pGC->capStyle != CapRound) || miSpansEasyRop(pGC->alu)) 149405b261ecSmrg return (SpanDataPtr) NULL; 149505b261ecSmrg if (pGC->lineStyle == LineDoubleDash) 149605b261ecSmrg miInitSpanGroup (&spanData->bgGroup); 149705b261ecSmrg miInitSpanGroup (&spanData->fgGroup); 149805b261ecSmrg return spanData; 149905b261ecSmrg} 150005b261ecSmrg 150105b261ecSmrgstatic void 150205b261ecSmrgmiCleanupSpanData (DrawablePtr pDrawable, GCPtr pGC, SpanDataPtr spanData) 150305b261ecSmrg{ 150405b261ecSmrg if (pGC->lineStyle == LineDoubleDash) 150505b261ecSmrg { 150605b261ecSmrg XID oldPixel, pixel; 150705b261ecSmrg 150805b261ecSmrg pixel = pGC->bgPixel; 150905b261ecSmrg oldPixel = pGC->fgPixel; 151005b261ecSmrg if (pixel != oldPixel) 151105b261ecSmrg { 151205b261ecSmrg DoChangeGC (pGC, GCForeground, &pixel, FALSE); 151305b261ecSmrg ValidateGC (pDrawable, pGC); 151405b261ecSmrg } 151505b261ecSmrg miFillUniqueSpanGroup (pDrawable, pGC, &spanData->bgGroup); 151605b261ecSmrg miFreeSpanGroup (&spanData->bgGroup); 151705b261ecSmrg if (pixel != oldPixel) 151805b261ecSmrg { 151905b261ecSmrg DoChangeGC (pGC, GCForeground, &oldPixel, FALSE); 152005b261ecSmrg ValidateGC (pDrawable, pGC); 152105b261ecSmrg } 152205b261ecSmrg } 152305b261ecSmrg miFillUniqueSpanGroup (pDrawable, pGC, &spanData->fgGroup); 152405b261ecSmrg miFreeSpanGroup (&spanData->fgGroup); 152505b261ecSmrg} 152605b261ecSmrg 152705b261ecSmrg_X_EXPORT void 15284642e01fSmrgmiWideLine (DrawablePtr pDrawable, GCPtr pGC, 15294642e01fSmrg int mode, int npt, DDXPointPtr pPts) 153005b261ecSmrg{ 15314642e01fSmrg int x1, y1, x2, y2; 153205b261ecSmrg SpanDataRec spanDataRec; 153305b261ecSmrg SpanDataPtr spanData; 153405b261ecSmrg long pixel; 153505b261ecSmrg Bool projectLeft, projectRight; 153605b261ecSmrg LineFaceRec leftFace, rightFace, prevRightFace; 153705b261ecSmrg LineFaceRec firstFace; 153805b261ecSmrg int first; 153905b261ecSmrg Bool somethingDrawn = FALSE; 154005b261ecSmrg Bool selfJoin; 154105b261ecSmrg 154205b261ecSmrg spanData = miSetupSpanData (pGC, &spanDataRec, npt); 154305b261ecSmrg pixel = pGC->fgPixel; 154405b261ecSmrg x2 = pPts->x; 154505b261ecSmrg y2 = pPts->y; 154605b261ecSmrg first = TRUE; 154705b261ecSmrg selfJoin = FALSE; 154805b261ecSmrg if (npt > 1) 154905b261ecSmrg { 155005b261ecSmrg if (mode == CoordModePrevious) 155105b261ecSmrg { 155205b261ecSmrg int nptTmp; 155305b261ecSmrg DDXPointPtr pPtsTmp; 155405b261ecSmrg 155505b261ecSmrg x1 = x2; 155605b261ecSmrg y1 = y2; 155705b261ecSmrg nptTmp = npt; 155805b261ecSmrg pPtsTmp = pPts + 1; 155905b261ecSmrg while (--nptTmp) 156005b261ecSmrg { 156105b261ecSmrg x1 += pPtsTmp->x; 156205b261ecSmrg y1 += pPtsTmp->y; 156305b261ecSmrg ++pPtsTmp; 156405b261ecSmrg } 156505b261ecSmrg if (x2 == x1 && y2 == y1) 156605b261ecSmrg selfJoin = TRUE; 156705b261ecSmrg } 156805b261ecSmrg else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y) 156905b261ecSmrg { 157005b261ecSmrg selfJoin = TRUE; 157105b261ecSmrg } 157205b261ecSmrg } 157305b261ecSmrg projectLeft = pGC->capStyle == CapProjecting && !selfJoin; 157405b261ecSmrg projectRight = FALSE; 157505b261ecSmrg while (--npt) 157605b261ecSmrg { 157705b261ecSmrg x1 = x2; 157805b261ecSmrg y1 = y2; 157905b261ecSmrg ++pPts; 158005b261ecSmrg x2 = pPts->x; 158105b261ecSmrg y2 = pPts->y; 158205b261ecSmrg if (mode == CoordModePrevious) 158305b261ecSmrg { 158405b261ecSmrg x2 += x1; 158505b261ecSmrg y2 += y1; 158605b261ecSmrg } 158705b261ecSmrg if (x1 != x2 || y1 != y2) 158805b261ecSmrg { 158905b261ecSmrg somethingDrawn = TRUE; 159005b261ecSmrg if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin) 159105b261ecSmrg projectRight = TRUE; 159205b261ecSmrg miWideSegment (pDrawable, pGC, pixel, spanData, x1, y1, x2, y2, 159305b261ecSmrg projectLeft, projectRight, &leftFace, &rightFace); 159405b261ecSmrg if (first) 159505b261ecSmrg { 159605b261ecSmrg if (selfJoin) 159705b261ecSmrg firstFace = leftFace; 159805b261ecSmrg else if (pGC->capStyle == CapRound) 159905b261ecSmrg { 160005b261ecSmrg if (pGC->lineWidth == 1 && !spanData) 160105b261ecSmrg miLineOnePoint (pDrawable, pGC, pixel, spanData, x1, y1); 160205b261ecSmrg else 160305b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 160405b261ecSmrg &leftFace, (LineFacePtr) NULL, 160505b261ecSmrg (double)0.0, (double)0.0, 160605b261ecSmrg TRUE); 160705b261ecSmrg } 160805b261ecSmrg } 160905b261ecSmrg else 161005b261ecSmrg { 161105b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace, 161205b261ecSmrg &prevRightFace); 161305b261ecSmrg } 161405b261ecSmrg prevRightFace = rightFace; 161505b261ecSmrg first = FALSE; 161605b261ecSmrg projectLeft = FALSE; 161705b261ecSmrg } 161805b261ecSmrg if (npt == 1 && somethingDrawn) 161905b261ecSmrg { 162005b261ecSmrg if (selfJoin) 162105b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace, 162205b261ecSmrg &rightFace); 162305b261ecSmrg else if (pGC->capStyle == CapRound) 162405b261ecSmrg { 162505b261ecSmrg if (pGC->lineWidth == 1 && !spanData) 162605b261ecSmrg miLineOnePoint (pDrawable, pGC, pixel, spanData, x2, y2); 162705b261ecSmrg else 162805b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 162905b261ecSmrg (LineFacePtr) NULL, &rightFace, 163005b261ecSmrg (double)0.0, (double)0.0, 163105b261ecSmrg TRUE); 163205b261ecSmrg } 163305b261ecSmrg } 163405b261ecSmrg } 163505b261ecSmrg /* handle crock where all points are coincedent */ 163605b261ecSmrg if (!somethingDrawn) 163705b261ecSmrg { 163805b261ecSmrg projectLeft = pGC->capStyle == CapProjecting; 163905b261ecSmrg miWideSegment (pDrawable, pGC, pixel, spanData, 164005b261ecSmrg x2, y2, x2, y2, projectLeft, projectLeft, 164105b261ecSmrg &leftFace, &rightFace); 164205b261ecSmrg if (pGC->capStyle == CapRound) 164305b261ecSmrg { 164405b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 164505b261ecSmrg &leftFace, (LineFacePtr) NULL, 164605b261ecSmrg (double)0.0, (double)0.0, 164705b261ecSmrg TRUE); 164805b261ecSmrg rightFace.dx = -1; /* sleezy hack to make it work */ 164905b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 165005b261ecSmrg (LineFacePtr) NULL, &rightFace, 165105b261ecSmrg (double)0.0, (double)0.0, 165205b261ecSmrg TRUE); 165305b261ecSmrg } 165405b261ecSmrg } 165505b261ecSmrg if (spanData) 165605b261ecSmrg miCleanupSpanData (pDrawable, pGC, spanData); 165705b261ecSmrg} 165805b261ecSmrg 165905b261ecSmrg#define V_TOP 0 166005b261ecSmrg#define V_RIGHT 1 166105b261ecSmrg#define V_BOTTOM 2 166205b261ecSmrg#define V_LEFT 3 166305b261ecSmrg 166405b261ecSmrgstatic void 166505b261ecSmrgmiWideDashSegment ( 166605b261ecSmrg DrawablePtr pDrawable, 166705b261ecSmrg GCPtr pGC, 166805b261ecSmrg SpanDataPtr spanData, 166905b261ecSmrg int *pDashOffset, 167005b261ecSmrg int *pDashIndex, 167105b261ecSmrg int x1, 167205b261ecSmrg int y1, 167305b261ecSmrg int x2, 167405b261ecSmrg int y2, 167505b261ecSmrg Bool projectLeft, 167605b261ecSmrg Bool projectRight, 167705b261ecSmrg LineFacePtr leftFace, 167805b261ecSmrg LineFacePtr rightFace) 167905b261ecSmrg{ 168005b261ecSmrg int dashIndex, dashRemain; 168105b261ecSmrg unsigned char *pDash; 168205b261ecSmrg double L, l; 168305b261ecSmrg double k; 168405b261ecSmrg PolyVertexRec vertices[4]; 168505b261ecSmrg PolyVertexRec saveRight, saveBottom; 168605b261ecSmrg PolySlopeRec slopes[4]; 168705b261ecSmrg PolyEdgeRec left[2], right[2]; 168805b261ecSmrg LineFaceRec lcapFace, rcapFace; 168905b261ecSmrg int nleft, nright; 169005b261ecSmrg int h; 169105b261ecSmrg int y; 169205b261ecSmrg int dy, dx; 169305b261ecSmrg unsigned long pixel; 169405b261ecSmrg double LRemain; 169505b261ecSmrg double r; 169605b261ecSmrg double rdx, rdy; 169705b261ecSmrg double dashDx, dashDy; 169805b261ecSmrg double saveK = 0.0; 169905b261ecSmrg Bool first = TRUE; 170005b261ecSmrg double lcenterx, lcentery, rcenterx = 0.0, rcentery = 0.0; 170105b261ecSmrg unsigned long fgPixel, bgPixel; 170205b261ecSmrg 170305b261ecSmrg dx = x2 - x1; 170405b261ecSmrg dy = y2 - y1; 170505b261ecSmrg dashIndex = *pDashIndex; 170605b261ecSmrg pDash = pGC->dash; 170705b261ecSmrg dashRemain = pDash[dashIndex] - *pDashOffset; 170805b261ecSmrg fgPixel = pGC->fgPixel; 170905b261ecSmrg bgPixel = pGC->bgPixel; 171005b261ecSmrg if (pGC->fillStyle == FillOpaqueStippled || 171105b261ecSmrg pGC->fillStyle == FillTiled) 171205b261ecSmrg { 171305b261ecSmrg bgPixel = fgPixel; 171405b261ecSmrg } 171505b261ecSmrg 171605b261ecSmrg l = ((double) pGC->lineWidth) / 2.0; 171705b261ecSmrg if (dx == 0) 171805b261ecSmrg { 171905b261ecSmrg L = dy; 172005b261ecSmrg rdx = 0; 172105b261ecSmrg rdy = l; 172205b261ecSmrg if (dy < 0) 172305b261ecSmrg { 172405b261ecSmrg L = -dy; 172505b261ecSmrg rdy = -l; 172605b261ecSmrg } 172705b261ecSmrg } 172805b261ecSmrg else if (dy == 0) 172905b261ecSmrg { 173005b261ecSmrg L = dx; 173105b261ecSmrg rdx = l; 173205b261ecSmrg rdy = 0; 173305b261ecSmrg if (dx < 0) 173405b261ecSmrg { 173505b261ecSmrg L = -dx; 173605b261ecSmrg rdx = -l; 173705b261ecSmrg } 173805b261ecSmrg } 173905b261ecSmrg else 174005b261ecSmrg { 174105b261ecSmrg L = hypot ((double) dx, (double) dy); 174205b261ecSmrg r = l / L; 174305b261ecSmrg 174405b261ecSmrg rdx = r * dx; 174505b261ecSmrg rdy = r * dy; 174605b261ecSmrg } 174705b261ecSmrg k = l * L; 174805b261ecSmrg LRemain = L; 174905b261ecSmrg /* All position comments are relative to a line with dx and dy > 0, 175005b261ecSmrg * but the code does not depend on this */ 175105b261ecSmrg /* top */ 175205b261ecSmrg slopes[V_TOP].dx = dx; 175305b261ecSmrg slopes[V_TOP].dy = dy; 175405b261ecSmrg slopes[V_TOP].k = k; 175505b261ecSmrg /* right */ 175605b261ecSmrg slopes[V_RIGHT].dx = -dy; 175705b261ecSmrg slopes[V_RIGHT].dy = dx; 175805b261ecSmrg slopes[V_RIGHT].k = 0; 175905b261ecSmrg /* bottom */ 176005b261ecSmrg slopes[V_BOTTOM].dx = -dx; 176105b261ecSmrg slopes[V_BOTTOM].dy = -dy; 176205b261ecSmrg slopes[V_BOTTOM].k = k; 176305b261ecSmrg /* left */ 176405b261ecSmrg slopes[V_LEFT].dx = dy; 176505b261ecSmrg slopes[V_LEFT].dy = -dx; 176605b261ecSmrg slopes[V_LEFT].k = 0; 176705b261ecSmrg 176805b261ecSmrg /* preload the start coordinates */ 176905b261ecSmrg vertices[V_RIGHT].x = vertices[V_TOP].x = rdy; 177005b261ecSmrg vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx; 177105b261ecSmrg 177205b261ecSmrg vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy; 177305b261ecSmrg vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx; 177405b261ecSmrg 177505b261ecSmrg if (projectLeft) 177605b261ecSmrg { 177705b261ecSmrg vertices[V_TOP].x -= rdx; 177805b261ecSmrg vertices[V_TOP].y -= rdy; 177905b261ecSmrg 178005b261ecSmrg vertices[V_LEFT].x -= rdx; 178105b261ecSmrg vertices[V_LEFT].y -= rdy; 178205b261ecSmrg 178305b261ecSmrg slopes[V_LEFT].k = rdx * dx + rdy * dy; 178405b261ecSmrg } 178505b261ecSmrg 178605b261ecSmrg lcenterx = x1; 178705b261ecSmrg lcentery = y1; 178805b261ecSmrg 178905b261ecSmrg if (pGC->capStyle == CapRound) 179005b261ecSmrg { 179105b261ecSmrg lcapFace.dx = dx; 179205b261ecSmrg lcapFace.dy = dy; 179305b261ecSmrg lcapFace.x = x1; 179405b261ecSmrg lcapFace.y = y1; 179505b261ecSmrg 179605b261ecSmrg rcapFace.dx = -dx; 179705b261ecSmrg rcapFace.dy = -dy; 179805b261ecSmrg rcapFace.x = x1; 179905b261ecSmrg rcapFace.y = y1; 180005b261ecSmrg } 180105b261ecSmrg while (LRemain > dashRemain) 180205b261ecSmrg { 180305b261ecSmrg dashDx = (dashRemain * dx) / L; 180405b261ecSmrg dashDy = (dashRemain * dy) / L; 180505b261ecSmrg 180605b261ecSmrg rcenterx = lcenterx + dashDx; 180705b261ecSmrg rcentery = lcentery + dashDy; 180805b261ecSmrg 180905b261ecSmrg vertices[V_RIGHT].x += dashDx; 181005b261ecSmrg vertices[V_RIGHT].y += dashDy; 181105b261ecSmrg 181205b261ecSmrg vertices[V_BOTTOM].x += dashDx; 181305b261ecSmrg vertices[V_BOTTOM].y += dashDy; 181405b261ecSmrg 181505b261ecSmrg slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy; 181605b261ecSmrg 181705b261ecSmrg if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) 181805b261ecSmrg { 181905b261ecSmrg if (pGC->lineStyle == LineOnOffDash && 182005b261ecSmrg pGC->capStyle == CapProjecting) 182105b261ecSmrg { 182205b261ecSmrg saveRight = vertices[V_RIGHT]; 182305b261ecSmrg saveBottom = vertices[V_BOTTOM]; 182405b261ecSmrg saveK = slopes[V_RIGHT].k; 182505b261ecSmrg 182605b261ecSmrg if (!first) 182705b261ecSmrg { 182805b261ecSmrg vertices[V_TOP].x -= rdx; 182905b261ecSmrg vertices[V_TOP].y -= rdy; 183005b261ecSmrg 183105b261ecSmrg vertices[V_LEFT].x -= rdx; 183205b261ecSmrg vertices[V_LEFT].y -= rdy; 183305b261ecSmrg 183405b261ecSmrg slopes[V_LEFT].k = vertices[V_LEFT].x * 183505b261ecSmrg slopes[V_LEFT].dy - 183605b261ecSmrg vertices[V_LEFT].y * 183705b261ecSmrg slopes[V_LEFT].dx; 183805b261ecSmrg } 183905b261ecSmrg 184005b261ecSmrg vertices[V_RIGHT].x += rdx; 184105b261ecSmrg vertices[V_RIGHT].y += rdy; 184205b261ecSmrg 184305b261ecSmrg vertices[V_BOTTOM].x += rdx; 184405b261ecSmrg vertices[V_BOTTOM].y += rdy; 184505b261ecSmrg 184605b261ecSmrg slopes[V_RIGHT].k = vertices[V_RIGHT].x * 184705b261ecSmrg slopes[V_RIGHT].dy - 184805b261ecSmrg vertices[V_RIGHT].y * 184905b261ecSmrg slopes[V_RIGHT].dx; 185005b261ecSmrg } 185105b261ecSmrg y = miPolyBuildPoly (vertices, slopes, 4, x1, y1, 185205b261ecSmrg left, right, &nleft, &nright, &h); 185305b261ecSmrg pixel = (dashIndex & 1) ? bgPixel : fgPixel; 185405b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright); 185505b261ecSmrg 185605b261ecSmrg if (pGC->lineStyle == LineOnOffDash) 185705b261ecSmrg { 185805b261ecSmrg switch (pGC->capStyle) 185905b261ecSmrg { 186005b261ecSmrg case CapProjecting: 186105b261ecSmrg vertices[V_BOTTOM] = saveBottom; 186205b261ecSmrg vertices[V_RIGHT] = saveRight; 186305b261ecSmrg slopes[V_RIGHT].k = saveK; 186405b261ecSmrg break; 186505b261ecSmrg case CapRound: 186605b261ecSmrg if (!first) 186705b261ecSmrg { 186805b261ecSmrg if (dx < 0) 186905b261ecSmrg { 187005b261ecSmrg lcapFace.xa = -vertices[V_LEFT].x; 187105b261ecSmrg lcapFace.ya = -vertices[V_LEFT].y; 187205b261ecSmrg lcapFace.k = slopes[V_LEFT].k; 187305b261ecSmrg } 187405b261ecSmrg else 187505b261ecSmrg { 187605b261ecSmrg lcapFace.xa = vertices[V_TOP].x; 187705b261ecSmrg lcapFace.ya = vertices[V_TOP].y; 187805b261ecSmrg lcapFace.k = -slopes[V_LEFT].k; 187905b261ecSmrg } 188005b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 188105b261ecSmrg &lcapFace, (LineFacePtr) NULL, 188205b261ecSmrg lcenterx, lcentery, FALSE); 188305b261ecSmrg } 188405b261ecSmrg if (dx < 0) 188505b261ecSmrg { 188605b261ecSmrg rcapFace.xa = vertices[V_BOTTOM].x; 188705b261ecSmrg rcapFace.ya = vertices[V_BOTTOM].y; 188805b261ecSmrg rcapFace.k = slopes[V_RIGHT].k; 188905b261ecSmrg } 189005b261ecSmrg else 189105b261ecSmrg { 189205b261ecSmrg rcapFace.xa = -vertices[V_RIGHT].x; 189305b261ecSmrg rcapFace.ya = -vertices[V_RIGHT].y; 189405b261ecSmrg rcapFace.k = -slopes[V_RIGHT].k; 189505b261ecSmrg } 189605b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 189705b261ecSmrg (LineFacePtr) NULL, &rcapFace, 189805b261ecSmrg rcenterx, rcentery, FALSE); 189905b261ecSmrg break; 190005b261ecSmrg } 190105b261ecSmrg } 190205b261ecSmrg } 190305b261ecSmrg LRemain -= dashRemain; 190405b261ecSmrg ++dashIndex; 190505b261ecSmrg if (dashIndex == pGC->numInDashList) 190605b261ecSmrg dashIndex = 0; 190705b261ecSmrg dashRemain = pDash[dashIndex]; 190805b261ecSmrg 190905b261ecSmrg lcenterx = rcenterx; 191005b261ecSmrg lcentery = rcentery; 191105b261ecSmrg 191205b261ecSmrg vertices[V_TOP] = vertices[V_RIGHT]; 191305b261ecSmrg vertices[V_LEFT] = vertices[V_BOTTOM]; 191405b261ecSmrg slopes[V_LEFT].k = -slopes[V_RIGHT].k; 191505b261ecSmrg first = FALSE; 191605b261ecSmrg } 191705b261ecSmrg 191805b261ecSmrg if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) 191905b261ecSmrg { 192005b261ecSmrg vertices[V_TOP].x -= dx; 192105b261ecSmrg vertices[V_TOP].y -= dy; 192205b261ecSmrg 192305b261ecSmrg vertices[V_LEFT].x -= dx; 192405b261ecSmrg vertices[V_LEFT].y -= dy; 192505b261ecSmrg 192605b261ecSmrg vertices[V_RIGHT].x = rdy; 192705b261ecSmrg vertices[V_RIGHT].y = -rdx; 192805b261ecSmrg 192905b261ecSmrg vertices[V_BOTTOM].x = -rdy; 193005b261ecSmrg vertices[V_BOTTOM].y = rdx; 193105b261ecSmrg 193205b261ecSmrg 193305b261ecSmrg if (projectRight) 193405b261ecSmrg { 193505b261ecSmrg vertices[V_RIGHT].x += rdx; 193605b261ecSmrg vertices[V_RIGHT].y += rdy; 193705b261ecSmrg 193805b261ecSmrg vertices[V_BOTTOM].x += rdx; 193905b261ecSmrg vertices[V_BOTTOM].y += rdy; 194005b261ecSmrg slopes[V_RIGHT].k = vertices[V_RIGHT].x * 194105b261ecSmrg slopes[V_RIGHT].dy - 194205b261ecSmrg vertices[V_RIGHT].y * 194305b261ecSmrg slopes[V_RIGHT].dx; 194405b261ecSmrg } 194505b261ecSmrg else 194605b261ecSmrg slopes[V_RIGHT].k = 0; 194705b261ecSmrg 194805b261ecSmrg if (!first && pGC->lineStyle == LineOnOffDash && 194905b261ecSmrg pGC->capStyle == CapProjecting) 195005b261ecSmrg { 195105b261ecSmrg vertices[V_TOP].x -= rdx; 195205b261ecSmrg vertices[V_TOP].y -= rdy; 195305b261ecSmrg 195405b261ecSmrg vertices[V_LEFT].x -= rdx; 195505b261ecSmrg vertices[V_LEFT].y -= rdy; 195605b261ecSmrg slopes[V_LEFT].k = vertices[V_LEFT].x * 195705b261ecSmrg slopes[V_LEFT].dy - 195805b261ecSmrg vertices[V_LEFT].y * 195905b261ecSmrg slopes[V_LEFT].dx; 196005b261ecSmrg } 196105b261ecSmrg else 196205b261ecSmrg slopes[V_LEFT].k += dx * dx + dy * dy; 196305b261ecSmrg 196405b261ecSmrg 196505b261ecSmrg y = miPolyBuildPoly (vertices, slopes, 4, x2, y2, 196605b261ecSmrg left, right, &nleft, &nright, &h); 196705b261ecSmrg 196805b261ecSmrg pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel; 196905b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright); 197005b261ecSmrg if (!first && pGC->lineStyle == LineOnOffDash && 197105b261ecSmrg pGC->capStyle == CapRound) 197205b261ecSmrg { 197305b261ecSmrg lcapFace.x = x2; 197405b261ecSmrg lcapFace.y = y2; 197505b261ecSmrg if (dx < 0) 197605b261ecSmrg { 197705b261ecSmrg lcapFace.xa = -vertices[V_LEFT].x; 197805b261ecSmrg lcapFace.ya = -vertices[V_LEFT].y; 197905b261ecSmrg lcapFace.k = slopes[V_LEFT].k; 198005b261ecSmrg } 198105b261ecSmrg else 198205b261ecSmrg { 198305b261ecSmrg lcapFace.xa = vertices[V_TOP].x; 198405b261ecSmrg lcapFace.ya = vertices[V_TOP].y; 198505b261ecSmrg lcapFace.k = -slopes[V_LEFT].k; 198605b261ecSmrg } 198705b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 198805b261ecSmrg &lcapFace, (LineFacePtr) NULL, 198905b261ecSmrg rcenterx, rcentery, FALSE); 199005b261ecSmrg } 199105b261ecSmrg } 199205b261ecSmrg dashRemain = ((double) dashRemain) - LRemain; 199305b261ecSmrg if (dashRemain == 0) 199405b261ecSmrg { 199505b261ecSmrg dashIndex++; 199605b261ecSmrg if (dashIndex == pGC->numInDashList) 199705b261ecSmrg dashIndex = 0; 199805b261ecSmrg dashRemain = pDash[dashIndex]; 199905b261ecSmrg } 200005b261ecSmrg 200105b261ecSmrg leftFace->x = x1; 200205b261ecSmrg leftFace->y = y1; 200305b261ecSmrg leftFace->dx = dx; 200405b261ecSmrg leftFace->dy = dy; 200505b261ecSmrg leftFace->xa = rdy; 200605b261ecSmrg leftFace->ya = -rdx; 200705b261ecSmrg leftFace->k = k; 200805b261ecSmrg 200905b261ecSmrg rightFace->x = x2; 201005b261ecSmrg rightFace->y = y2; 201105b261ecSmrg rightFace->dx = -dx; 201205b261ecSmrg rightFace->dy = -dy; 201305b261ecSmrg rightFace->xa = -rdy; 201405b261ecSmrg rightFace->ya = rdx; 201505b261ecSmrg rightFace->k = k; 201605b261ecSmrg 201705b261ecSmrg *pDashIndex = dashIndex; 201805b261ecSmrg *pDashOffset = pDash[dashIndex] - dashRemain; 201905b261ecSmrg} 202005b261ecSmrg 202105b261ecSmrg_X_EXPORT void 20224642e01fSmrgmiWideDash (DrawablePtr pDrawable, GCPtr pGC, 20234642e01fSmrg int mode, int npt, DDXPointPtr pPts) 202405b261ecSmrg{ 202505b261ecSmrg int x1, y1, x2, y2; 202605b261ecSmrg unsigned long pixel; 202705b261ecSmrg Bool projectLeft, projectRight; 202805b261ecSmrg LineFaceRec leftFace, rightFace, prevRightFace; 202905b261ecSmrg LineFaceRec firstFace; 203005b261ecSmrg int first; 203105b261ecSmrg int dashIndex, dashOffset; 203205b261ecSmrg int prevDashIndex; 203305b261ecSmrg SpanDataRec spanDataRec; 203405b261ecSmrg SpanDataPtr spanData; 203505b261ecSmrg Bool somethingDrawn = FALSE; 203605b261ecSmrg Bool selfJoin; 203705b261ecSmrg Bool endIsFg = FALSE, startIsFg = FALSE; 203805b261ecSmrg Bool firstIsFg = FALSE, prevIsFg = FALSE; 203905b261ecSmrg 204005b261ecSmrg#if 0 204105b261ecSmrg /* XXX backward compatibility */ 204205b261ecSmrg if (pGC->lineWidth == 0) 204305b261ecSmrg { 204405b261ecSmrg miZeroDashLine (pDrawable, pGC, mode, npt, pPts); 204505b261ecSmrg return; 204605b261ecSmrg } 204705b261ecSmrg#endif 204805b261ecSmrg if (pGC->lineStyle == LineDoubleDash && 204905b261ecSmrg (pGC->fillStyle == FillOpaqueStippled || pGC->fillStyle == FillTiled)) 205005b261ecSmrg { 205105b261ecSmrg miWideLine (pDrawable, pGC, mode, npt, pPts); 205205b261ecSmrg return; 205305b261ecSmrg } 205405b261ecSmrg if (npt == 0) 205505b261ecSmrg return; 205605b261ecSmrg spanData = miSetupSpanData (pGC, &spanDataRec, npt); 205705b261ecSmrg x2 = pPts->x; 205805b261ecSmrg y2 = pPts->y; 205905b261ecSmrg first = TRUE; 206005b261ecSmrg selfJoin = FALSE; 206105b261ecSmrg if (mode == CoordModePrevious) 206205b261ecSmrg { 206305b261ecSmrg int nptTmp; 206405b261ecSmrg DDXPointPtr pPtsTmp; 206505b261ecSmrg 206605b261ecSmrg x1 = x2; 206705b261ecSmrg y1 = y2; 206805b261ecSmrg nptTmp = npt; 206905b261ecSmrg pPtsTmp = pPts + 1; 207005b261ecSmrg while (--nptTmp) 207105b261ecSmrg { 207205b261ecSmrg x1 += pPtsTmp->x; 207305b261ecSmrg y1 += pPtsTmp->y; 207405b261ecSmrg ++pPtsTmp; 207505b261ecSmrg } 207605b261ecSmrg if (x2 == x1 && y2 == y1) 207705b261ecSmrg selfJoin = TRUE; 207805b261ecSmrg } 207905b261ecSmrg else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y) 208005b261ecSmrg { 208105b261ecSmrg selfJoin = TRUE; 208205b261ecSmrg } 208305b261ecSmrg projectLeft = pGC->capStyle == CapProjecting && !selfJoin; 208405b261ecSmrg projectRight = FALSE; 208505b261ecSmrg dashIndex = 0; 208605b261ecSmrg dashOffset = 0; 208705b261ecSmrg miStepDash ((int)pGC->dashOffset, &dashIndex, 208805b261ecSmrg pGC->dash, (int)pGC->numInDashList, &dashOffset); 208905b261ecSmrg while (--npt) 209005b261ecSmrg { 209105b261ecSmrg x1 = x2; 209205b261ecSmrg y1 = y2; 209305b261ecSmrg ++pPts; 209405b261ecSmrg x2 = pPts->x; 209505b261ecSmrg y2 = pPts->y; 209605b261ecSmrg if (mode == CoordModePrevious) 209705b261ecSmrg { 209805b261ecSmrg x2 += x1; 209905b261ecSmrg y2 += y1; 210005b261ecSmrg } 210105b261ecSmrg if (x1 != x2 || y1 != y2) 210205b261ecSmrg { 210305b261ecSmrg somethingDrawn = TRUE; 210405b261ecSmrg if (npt == 1 && pGC->capStyle == CapProjecting && 210505b261ecSmrg (!selfJoin || !firstIsFg)) 210605b261ecSmrg projectRight = TRUE; 210705b261ecSmrg prevDashIndex = dashIndex; 210805b261ecSmrg miWideDashSegment (pDrawable, pGC, spanData, &dashOffset, &dashIndex, 210905b261ecSmrg x1, y1, x2, y2, 211005b261ecSmrg projectLeft, projectRight, &leftFace, &rightFace); 211105b261ecSmrg startIsFg = !(prevDashIndex & 1); 211205b261ecSmrg endIsFg = (dashIndex & 1) ^ (dashOffset != 0); 211305b261ecSmrg if (pGC->lineStyle == LineDoubleDash || startIsFg) 211405b261ecSmrg { 211505b261ecSmrg pixel = startIsFg ? pGC->fgPixel : pGC->bgPixel; 211605b261ecSmrg if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg)) 211705b261ecSmrg { 211805b261ecSmrg if (first && selfJoin) 211905b261ecSmrg { 212005b261ecSmrg firstFace = leftFace; 212105b261ecSmrg firstIsFg = startIsFg; 212205b261ecSmrg } 212305b261ecSmrg else if (pGC->capStyle == CapRound) 212405b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 212505b261ecSmrg &leftFace, (LineFacePtr) NULL, 212605b261ecSmrg (double)0.0, (double)0.0, TRUE); 212705b261ecSmrg } 212805b261ecSmrg else 212905b261ecSmrg { 213005b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace, 213105b261ecSmrg &prevRightFace); 213205b261ecSmrg } 213305b261ecSmrg } 213405b261ecSmrg prevRightFace = rightFace; 213505b261ecSmrg prevIsFg = endIsFg; 213605b261ecSmrg first = FALSE; 213705b261ecSmrg projectLeft = FALSE; 213805b261ecSmrg } 213905b261ecSmrg if (npt == 1 && somethingDrawn) 214005b261ecSmrg { 214105b261ecSmrg if (pGC->lineStyle == LineDoubleDash || endIsFg) 214205b261ecSmrg { 214305b261ecSmrg pixel = endIsFg ? pGC->fgPixel : pGC->bgPixel; 214405b261ecSmrg if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg)) 214505b261ecSmrg { 214605b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace, 214705b261ecSmrg &rightFace); 214805b261ecSmrg } 214905b261ecSmrg else 215005b261ecSmrg { 215105b261ecSmrg if (pGC->capStyle == CapRound) 215205b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 215305b261ecSmrg (LineFacePtr) NULL, &rightFace, 215405b261ecSmrg (double)0.0, (double)0.0, TRUE); 215505b261ecSmrg } 215605b261ecSmrg } 215705b261ecSmrg else 215805b261ecSmrg { 215905b261ecSmrg /* glue a cap to the start of the line if 216005b261ecSmrg * we're OnOffDash and ended on odd dash 216105b261ecSmrg */ 216205b261ecSmrg if (selfJoin && firstIsFg) 216305b261ecSmrg { 216405b261ecSmrg pixel = pGC->fgPixel; 216505b261ecSmrg if (pGC->capStyle == CapProjecting) 216605b261ecSmrg miLineProjectingCap (pDrawable, pGC, pixel, spanData, 216705b261ecSmrg &firstFace, TRUE, 216805b261ecSmrg (double)0.0, (double)0.0, TRUE); 216905b261ecSmrg else if (pGC->capStyle == CapRound) 217005b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 217105b261ecSmrg &firstFace, (LineFacePtr) NULL, 217205b261ecSmrg (double)0.0, (double)0.0, TRUE); 217305b261ecSmrg } 217405b261ecSmrg } 217505b261ecSmrg } 217605b261ecSmrg } 217705b261ecSmrg /* handle crock where all points are coincident */ 217805b261ecSmrg if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))) 217905b261ecSmrg { 218005b261ecSmrg /* not the same as endIsFg computation above */ 218105b261ecSmrg pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel; 218205b261ecSmrg switch (pGC->capStyle) { 218305b261ecSmrg case CapRound: 218405b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 218505b261ecSmrg (LineFacePtr) NULL, (LineFacePtr) NULL, 218605b261ecSmrg (double)x2, (double)y2, 218705b261ecSmrg FALSE); 218805b261ecSmrg break; 218905b261ecSmrg case CapProjecting: 219005b261ecSmrg x1 = pGC->lineWidth; 219105b261ecSmrg miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, 219205b261ecSmrg x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1); 219305b261ecSmrg break; 219405b261ecSmrg } 219505b261ecSmrg } 219605b261ecSmrg if (spanData) 219705b261ecSmrg miCleanupSpanData (pDrawable, pGC, spanData); 219805b261ecSmrg} 2199