miwideline.c revision 05b261ec
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 { 9805b261ecSmrg pptInit = (DDXPointPtr) ALLOCATE_LOCAL (overall_height * sizeof(*ppt)); 9905b261ecSmrg if (!pptInit) 10005b261ecSmrg return; 10105b261ecSmrg pwidthInit = (int *) ALLOCATE_LOCAL (overall_height * sizeof(*pwidth)); 10205b261ecSmrg if (!pwidthInit) 10305b261ecSmrg { 10405b261ecSmrg DEALLOCATE_LOCAL (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); 17005b261ecSmrg DEALLOCATE_LOCAL (pwidthInit); 17105b261ecSmrg DEALLOCATE_LOCAL (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 25505b261ecSmrgmiPolyBuildEdge (x0, y0, k, dx, dy, xi, yi, left, edge) 25605b261ecSmrg double x0, y0; 25705b261ecSmrg double k; /* x0 * dy - y0 * dx */ 25805b261ecSmrg int dx, dy; 25905b261ecSmrg int xi, yi; 26005b261ecSmrg int left; 26105b261ecSmrg PolyEdgePtr edge; 26205b261ecSmrg{ 26305b261ecSmrg int x, y, e; 26405b261ecSmrg int xady; 26505b261ecSmrg 26605b261ecSmrg if (dy < 0) 26705b261ecSmrg { 26805b261ecSmrg dy = -dy; 26905b261ecSmrg dx = -dx; 27005b261ecSmrg k = -k; 27105b261ecSmrg } 27205b261ecSmrg 27305b261ecSmrg#ifdef NOTDEF 27405b261ecSmrg { 27505b261ecSmrg double realk, kerror; 27605b261ecSmrg realk = x0 * dy - y0 * dx; 27705b261ecSmrg kerror = Fabs (realk - k); 27805b261ecSmrg if (kerror > .1) 27905b261ecSmrg printf ("realk: %g k: %g\n", realk, k); 28005b261ecSmrg } 28105b261ecSmrg#endif 28205b261ecSmrg y = ICEIL (y0); 28305b261ecSmrg xady = ICEIL (k) + y * dx; 28405b261ecSmrg 28505b261ecSmrg if (xady <= 0) 28605b261ecSmrg x = - (-xady / dy) - 1; 28705b261ecSmrg else 28805b261ecSmrg x = (xady - 1) / dy; 28905b261ecSmrg 29005b261ecSmrg e = xady - x * dy; 29105b261ecSmrg 29205b261ecSmrg if (dx >= 0) 29305b261ecSmrg { 29405b261ecSmrg edge->signdx = 1; 29505b261ecSmrg edge->stepx = dx / dy; 29605b261ecSmrg edge->dx = dx % dy; 29705b261ecSmrg } 29805b261ecSmrg else 29905b261ecSmrg { 30005b261ecSmrg edge->signdx = -1; 30105b261ecSmrg edge->stepx = - (-dx / dy); 30205b261ecSmrg edge->dx = -dx % dy; 30305b261ecSmrg e = dy - e + 1; 30405b261ecSmrg } 30505b261ecSmrg edge->dy = dy; 30605b261ecSmrg edge->x = x + left + xi; 30705b261ecSmrg edge->e = e - dy; /* bias to compare against 0 instead of dy */ 30805b261ecSmrg return y + yi; 30905b261ecSmrg} 31005b261ecSmrg 31105b261ecSmrg#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr))) 31205b261ecSmrg 31305b261ecSmrg_X_EXPORT /* static */ int 31405b261ecSmrgmiPolyBuildPoly (vertices, slopes, count, xi, yi, left, right, pnleft, pnright, h) 31505b261ecSmrg PolyVertexPtr vertices; 31605b261ecSmrg PolySlopePtr slopes; 31705b261ecSmrg int count; 31805b261ecSmrg int xi, yi; 31905b261ecSmrg PolyEdgePtr left, right; 32005b261ecSmrg int *pnleft, *pnright; 32105b261ecSmrg int *h; 32205b261ecSmrg{ 32305b261ecSmrg int top, bottom; 32405b261ecSmrg double miny, maxy; 32505b261ecSmrg int i; 32605b261ecSmrg int j; 32705b261ecSmrg int clockwise; 32805b261ecSmrg int slopeoff; 32905b261ecSmrg int s; 33005b261ecSmrg int nright, nleft; 33105b261ecSmrg int y, lasty = 0, bottomy, topy = 0; 33205b261ecSmrg 33305b261ecSmrg /* find the top of the polygon */ 33405b261ecSmrg maxy = miny = vertices[0].y; 33505b261ecSmrg bottom = top = 0; 33605b261ecSmrg for (i = 1; i < count; i++) 33705b261ecSmrg { 33805b261ecSmrg if (vertices[i].y < miny) 33905b261ecSmrg { 34005b261ecSmrg top = i; 34105b261ecSmrg miny = vertices[i].y; 34205b261ecSmrg } 34305b261ecSmrg if (vertices[i].y >= maxy) 34405b261ecSmrg { 34505b261ecSmrg bottom = i; 34605b261ecSmrg maxy = vertices[i].y; 34705b261ecSmrg } 34805b261ecSmrg } 34905b261ecSmrg clockwise = 1; 35005b261ecSmrg slopeoff = 0; 35105b261ecSmrg 35205b261ecSmrg i = top; 35305b261ecSmrg j = StepAround (top, -1, count); 35405b261ecSmrg 35505b261ecSmrg if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx) 35605b261ecSmrg { 35705b261ecSmrg clockwise = -1; 35805b261ecSmrg slopeoff = -1; 35905b261ecSmrg } 36005b261ecSmrg 36105b261ecSmrg bottomy = ICEIL (maxy) + yi; 36205b261ecSmrg 36305b261ecSmrg nright = 0; 36405b261ecSmrg 36505b261ecSmrg s = StepAround (top, slopeoff, count); 36605b261ecSmrg i = top; 36705b261ecSmrg while (i != bottom) 36805b261ecSmrg { 36905b261ecSmrg if (slopes[s].dy != 0) 37005b261ecSmrg { 37105b261ecSmrg y = miPolyBuildEdge (vertices[i].x, vertices[i].y, 37205b261ecSmrg slopes[s].k, 37305b261ecSmrg slopes[s].dx, slopes[s].dy, 37405b261ecSmrg xi, yi, 0, 37505b261ecSmrg &right[nright]); 37605b261ecSmrg if (nright != 0) 37705b261ecSmrg right[nright-1].height = y - lasty; 37805b261ecSmrg else 37905b261ecSmrg topy = y; 38005b261ecSmrg nright++; 38105b261ecSmrg lasty = y; 38205b261ecSmrg } 38305b261ecSmrg 38405b261ecSmrg i = StepAround (i, clockwise, count); 38505b261ecSmrg s = StepAround (s, clockwise, count); 38605b261ecSmrg } 38705b261ecSmrg if (nright != 0) 38805b261ecSmrg right[nright-1].height = bottomy - lasty; 38905b261ecSmrg 39005b261ecSmrg if (slopeoff == 0) 39105b261ecSmrg slopeoff = -1; 39205b261ecSmrg else 39305b261ecSmrg slopeoff = 0; 39405b261ecSmrg 39505b261ecSmrg nleft = 0; 39605b261ecSmrg s = StepAround (top, slopeoff, count); 39705b261ecSmrg i = top; 39805b261ecSmrg while (i != bottom) 39905b261ecSmrg { 40005b261ecSmrg if (slopes[s].dy != 0) 40105b261ecSmrg { 40205b261ecSmrg y = miPolyBuildEdge (vertices[i].x, vertices[i].y, 40305b261ecSmrg slopes[s].k, 40405b261ecSmrg slopes[s].dx, slopes[s].dy, xi, yi, 1, 40505b261ecSmrg &left[nleft]); 40605b261ecSmrg 40705b261ecSmrg if (nleft != 0) 40805b261ecSmrg left[nleft-1].height = y - lasty; 40905b261ecSmrg nleft++; 41005b261ecSmrg lasty = y; 41105b261ecSmrg } 41205b261ecSmrg i = StepAround (i, -clockwise, count); 41305b261ecSmrg s = StepAround (s, -clockwise, count); 41405b261ecSmrg } 41505b261ecSmrg if (nleft != 0) 41605b261ecSmrg left[nleft-1].height = bottomy - lasty; 41705b261ecSmrg *pnleft = nleft; 41805b261ecSmrg *pnright = nright; 41905b261ecSmrg *h = bottomy - topy; 42005b261ecSmrg return topy; 42105b261ecSmrg} 42205b261ecSmrg 42305b261ecSmrgstatic void 42405b261ecSmrgmiLineOnePoint ( 42505b261ecSmrg DrawablePtr pDrawable, 42605b261ecSmrg GCPtr pGC, 42705b261ecSmrg unsigned long pixel, 42805b261ecSmrg SpanDataPtr spanData, 42905b261ecSmrg int x, 43005b261ecSmrg int y) 43105b261ecSmrg{ 43205b261ecSmrg DDXPointRec pt; 43305b261ecSmrg int wid; 43405b261ecSmrg unsigned long oldPixel; 43505b261ecSmrg 43605b261ecSmrg MILINESETPIXEL (pDrawable, pGC, pixel, oldPixel); 43705b261ecSmrg if (pGC->fillStyle == FillSolid) 43805b261ecSmrg { 43905b261ecSmrg pt.x = x; 44005b261ecSmrg pt.y = y; 44105b261ecSmrg (*pGC->ops->PolyPoint) (pDrawable, pGC, CoordModeOrigin, 1, &pt); 44205b261ecSmrg } 44305b261ecSmrg else 44405b261ecSmrg { 44505b261ecSmrg wid = 1; 44605b261ecSmrg if (pGC->miTranslate) 44705b261ecSmrg { 44805b261ecSmrg x += pDrawable->x; 44905b261ecSmrg y += pDrawable->y; 45005b261ecSmrg } 45105b261ecSmrg pt.x = x; 45205b261ecSmrg pt.y = y; 45305b261ecSmrg (*pGC->ops->FillSpans) (pDrawable, pGC, 1, &pt, &wid, TRUE); 45405b261ecSmrg } 45505b261ecSmrg MILINERESETPIXEL (pDrawable, pGC, pixel, oldPixel); 45605b261ecSmrg} 45705b261ecSmrg 45805b261ecSmrgstatic void 45905b261ecSmrgmiLineJoin ( 46005b261ecSmrg DrawablePtr pDrawable, 46105b261ecSmrg GCPtr pGC, 46205b261ecSmrg unsigned long pixel, 46305b261ecSmrg SpanDataPtr spanData, 46405b261ecSmrg LineFacePtr pLeft, 46505b261ecSmrg LineFacePtr pRight) 46605b261ecSmrg{ 46705b261ecSmrg double mx = 0, my = 0; 46805b261ecSmrg double denom = 0.0; 46905b261ecSmrg PolyVertexRec vertices[4]; 47005b261ecSmrg PolySlopeRec slopes[4]; 47105b261ecSmrg int edgecount; 47205b261ecSmrg PolyEdgeRec left[4], right[4]; 47305b261ecSmrg int nleft, nright; 47405b261ecSmrg int y, height; 47505b261ecSmrg int swapslopes; 47605b261ecSmrg int joinStyle = pGC->joinStyle; 47705b261ecSmrg int lw = pGC->lineWidth; 47805b261ecSmrg 47905b261ecSmrg if (lw == 1 && !spanData) { 48005b261ecSmrg /* See if one of the lines will draw the joining pixel */ 48105b261ecSmrg if (pLeft->dx > 0 || (pLeft->dx == 0 && pLeft->dy > 0)) 48205b261ecSmrg return; 48305b261ecSmrg if (pRight->dx > 0 || (pRight->dx == 0 && pRight->dy > 0)) 48405b261ecSmrg return; 48505b261ecSmrg if (joinStyle != JoinRound) { 48605b261ecSmrg denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; 48705b261ecSmrg if (denom == 0) 48805b261ecSmrg return; /* no join to draw */ 48905b261ecSmrg } 49005b261ecSmrg if (joinStyle != JoinMiter) { 49105b261ecSmrg miLineOnePoint (pDrawable, pGC, pixel, spanData, pLeft->x, pLeft->y); 49205b261ecSmrg return; 49305b261ecSmrg } 49405b261ecSmrg } else { 49505b261ecSmrg if (joinStyle == JoinRound) 49605b261ecSmrg { 49705b261ecSmrg miLineArc(pDrawable, pGC, pixel, spanData, 49805b261ecSmrg pLeft, pRight, 49905b261ecSmrg (double)0.0, (double)0.0, TRUE); 50005b261ecSmrg return; 50105b261ecSmrg } 50205b261ecSmrg denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; 50305b261ecSmrg if (denom == 0.0) 50405b261ecSmrg return; /* no join to draw */ 50505b261ecSmrg } 50605b261ecSmrg 50705b261ecSmrg swapslopes = 0; 50805b261ecSmrg if (denom > 0) 50905b261ecSmrg { 51005b261ecSmrg pLeft->xa = -pLeft->xa; 51105b261ecSmrg pLeft->ya = -pLeft->ya; 51205b261ecSmrg pLeft->dx = -pLeft->dx; 51305b261ecSmrg pLeft->dy = -pLeft->dy; 51405b261ecSmrg } 51505b261ecSmrg else 51605b261ecSmrg { 51705b261ecSmrg swapslopes = 1; 51805b261ecSmrg pRight->xa = -pRight->xa; 51905b261ecSmrg pRight->ya = -pRight->ya; 52005b261ecSmrg pRight->dx = -pRight->dx; 52105b261ecSmrg pRight->dy = -pRight->dy; 52205b261ecSmrg } 52305b261ecSmrg 52405b261ecSmrg vertices[0].x = pRight->xa; 52505b261ecSmrg vertices[0].y = pRight->ya; 52605b261ecSmrg slopes[0].dx = -pRight->dy; 52705b261ecSmrg slopes[0].dy = pRight->dx; 52805b261ecSmrg slopes[0].k = 0; 52905b261ecSmrg 53005b261ecSmrg vertices[1].x = 0; 53105b261ecSmrg vertices[1].y = 0; 53205b261ecSmrg slopes[1].dx = pLeft->dy; 53305b261ecSmrg slopes[1].dy = -pLeft->dx; 53405b261ecSmrg slopes[1].k = 0; 53505b261ecSmrg 53605b261ecSmrg vertices[2].x = pLeft->xa; 53705b261ecSmrg vertices[2].y = pLeft->ya; 53805b261ecSmrg 53905b261ecSmrg if (joinStyle == JoinMiter) 54005b261ecSmrg { 54105b261ecSmrg my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) - 54205b261ecSmrg pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx )) / 54305b261ecSmrg denom; 54405b261ecSmrg if (pLeft->dy != 0) 54505b261ecSmrg { 54605b261ecSmrg mx = pLeft->xa + (my - pLeft->ya) * 54705b261ecSmrg (double) pLeft->dx / (double) pLeft->dy; 54805b261ecSmrg } 54905b261ecSmrg else 55005b261ecSmrg { 55105b261ecSmrg mx = pRight->xa + (my - pRight->ya) * 55205b261ecSmrg (double) pRight->dx / (double) pRight->dy; 55305b261ecSmrg } 55405b261ecSmrg /* check miter limit */ 55505b261ecSmrg if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw) 55605b261ecSmrg joinStyle = JoinBevel; 55705b261ecSmrg } 55805b261ecSmrg 55905b261ecSmrg if (joinStyle == JoinMiter) 56005b261ecSmrg { 56105b261ecSmrg slopes[2].dx = pLeft->dx; 56205b261ecSmrg slopes[2].dy = pLeft->dy; 56305b261ecSmrg slopes[2].k = pLeft->k; 56405b261ecSmrg if (swapslopes) 56505b261ecSmrg { 56605b261ecSmrg slopes[2].dx = -slopes[2].dx; 56705b261ecSmrg slopes[2].dy = -slopes[2].dy; 56805b261ecSmrg slopes[2].k = -slopes[2].k; 56905b261ecSmrg } 57005b261ecSmrg vertices[3].x = mx; 57105b261ecSmrg vertices[3].y = my; 57205b261ecSmrg slopes[3].dx = pRight->dx; 57305b261ecSmrg slopes[3].dy = pRight->dy; 57405b261ecSmrg slopes[3].k = pRight->k; 57505b261ecSmrg if (swapslopes) 57605b261ecSmrg { 57705b261ecSmrg slopes[3].dx = -slopes[3].dx; 57805b261ecSmrg slopes[3].dy = -slopes[3].dy; 57905b261ecSmrg slopes[3].k = -slopes[3].k; 58005b261ecSmrg } 58105b261ecSmrg edgecount = 4; 58205b261ecSmrg } 58305b261ecSmrg else 58405b261ecSmrg { 58505b261ecSmrg double scale, dx, dy, adx, ady; 58605b261ecSmrg 58705b261ecSmrg adx = dx = pRight->xa - pLeft->xa; 58805b261ecSmrg ady = dy = pRight->ya - pLeft->ya; 58905b261ecSmrg if (adx < 0) 59005b261ecSmrg adx = -adx; 59105b261ecSmrg if (ady < 0) 59205b261ecSmrg ady = -ady; 59305b261ecSmrg scale = ady; 59405b261ecSmrg if (adx > ady) 59505b261ecSmrg scale = adx; 59605b261ecSmrg slopes[2].dx = (dx * 65536) / scale; 59705b261ecSmrg slopes[2].dy = (dy * 65536) / scale; 59805b261ecSmrg slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy - 59905b261ecSmrg (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0; 60005b261ecSmrg edgecount = 3; 60105b261ecSmrg } 60205b261ecSmrg 60305b261ecSmrg y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y, 60405b261ecSmrg left, right, &nleft, &nright, &height); 60505b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, height, left, right, nleft, nright); 60605b261ecSmrg} 60705b261ecSmrg 60805b261ecSmrgstatic int 60905b261ecSmrgmiLineArcI ( 61005b261ecSmrg DrawablePtr pDraw, 61105b261ecSmrg GCPtr pGC, 61205b261ecSmrg int xorg, 61305b261ecSmrg int yorg, 61405b261ecSmrg DDXPointPtr points, 61505b261ecSmrg int *widths) 61605b261ecSmrg{ 61705b261ecSmrg DDXPointPtr tpts, bpts; 61805b261ecSmrg int *twids, *bwids; 61905b261ecSmrg int x, y, e, ex, slw; 62005b261ecSmrg 62105b261ecSmrg tpts = points; 62205b261ecSmrg twids = widths; 62305b261ecSmrg if (pGC->miTranslate) 62405b261ecSmrg { 62505b261ecSmrg xorg += pDraw->x; 62605b261ecSmrg yorg += pDraw->y; 62705b261ecSmrg } 62805b261ecSmrg slw = pGC->lineWidth; 62905b261ecSmrg if (slw == 1) 63005b261ecSmrg { 63105b261ecSmrg tpts->x = xorg; 63205b261ecSmrg tpts->y = yorg; 63305b261ecSmrg *twids = 1; 63405b261ecSmrg return 1; 63505b261ecSmrg } 63605b261ecSmrg bpts = tpts + slw; 63705b261ecSmrg bwids = twids + slw; 63805b261ecSmrg y = (slw >> 1) + 1; 63905b261ecSmrg if (slw & 1) 64005b261ecSmrg e = - ((y << 2) + 3); 64105b261ecSmrg else 64205b261ecSmrg e = - (y << 3); 64305b261ecSmrg ex = -4; 64405b261ecSmrg x = 0; 64505b261ecSmrg while (y) 64605b261ecSmrg { 64705b261ecSmrg e += (y << 3) - 4; 64805b261ecSmrg while (e >= 0) 64905b261ecSmrg { 65005b261ecSmrg x++; 65105b261ecSmrg e += (ex = -((x << 3) + 4)); 65205b261ecSmrg } 65305b261ecSmrg y--; 65405b261ecSmrg slw = (x << 1) + 1; 65505b261ecSmrg if ((e == ex) && (slw > 1)) 65605b261ecSmrg slw--; 65705b261ecSmrg tpts->x = xorg - x; 65805b261ecSmrg tpts->y = yorg - y; 65905b261ecSmrg tpts++; 66005b261ecSmrg *twids++ = slw; 66105b261ecSmrg if ((y != 0) && ((slw > 1) || (e != ex))) 66205b261ecSmrg { 66305b261ecSmrg bpts--; 66405b261ecSmrg bpts->x = xorg - x; 66505b261ecSmrg bpts->y = yorg + y; 66605b261ecSmrg *--bwids = slw; 66705b261ecSmrg } 66805b261ecSmrg } 66905b261ecSmrg return (pGC->lineWidth); 67005b261ecSmrg} 67105b261ecSmrg 67205b261ecSmrg#define CLIPSTEPEDGE(edgey,edge,edgeleft) \ 67305b261ecSmrg if (ybase == edgey) \ 67405b261ecSmrg { \ 67505b261ecSmrg if (edgeleft) \ 67605b261ecSmrg { \ 67705b261ecSmrg if (edge->x > xcl) \ 67805b261ecSmrg xcl = edge->x; \ 67905b261ecSmrg } \ 68005b261ecSmrg else \ 68105b261ecSmrg { \ 68205b261ecSmrg if (edge->x < xcr) \ 68305b261ecSmrg xcr = edge->x; \ 68405b261ecSmrg } \ 68505b261ecSmrg edgey++; \ 68605b261ecSmrg edge->x += edge->stepx; \ 68705b261ecSmrg edge->e += edge->dx; \ 68805b261ecSmrg if (edge->e > 0) \ 68905b261ecSmrg { \ 69005b261ecSmrg edge->x += edge->signdx; \ 69105b261ecSmrg edge->e -= edge->dy; \ 69205b261ecSmrg } \ 69305b261ecSmrg } 69405b261ecSmrg 69505b261ecSmrgstatic int 69605b261ecSmrgmiLineArcD ( 69705b261ecSmrg DrawablePtr pDraw, 69805b261ecSmrg GCPtr pGC, 69905b261ecSmrg double xorg, 70005b261ecSmrg double yorg, 70105b261ecSmrg DDXPointPtr points, 70205b261ecSmrg int *widths, 70305b261ecSmrg PolyEdgePtr edge1, 70405b261ecSmrg int edgey1, 70505b261ecSmrg Bool edgeleft1, 70605b261ecSmrg PolyEdgePtr edge2, 70705b261ecSmrg int edgey2, 70805b261ecSmrg Bool edgeleft2) 70905b261ecSmrg{ 71005b261ecSmrg DDXPointPtr pts; 71105b261ecSmrg int *wids; 71205b261ecSmrg double radius, x0, y0, el, er, yk, xlk, xrk, k; 71305b261ecSmrg int xbase, ybase, y, boty, xl, xr, xcl, xcr; 71405b261ecSmrg int ymin, ymax; 71505b261ecSmrg Bool edge1IsMin, edge2IsMin; 71605b261ecSmrg int ymin1, ymin2; 71705b261ecSmrg 71805b261ecSmrg pts = points; 71905b261ecSmrg wids = widths; 72005b261ecSmrg xbase = floor(xorg); 72105b261ecSmrg x0 = xorg - xbase; 72205b261ecSmrg ybase = ICEIL (yorg); 72305b261ecSmrg y0 = yorg - ybase; 72405b261ecSmrg if (pGC->miTranslate) 72505b261ecSmrg { 72605b261ecSmrg xbase += pDraw->x; 72705b261ecSmrg ybase += pDraw->y; 72805b261ecSmrg edge1->x += pDraw->x; 72905b261ecSmrg edge2->x += pDraw->x; 73005b261ecSmrg edgey1 += pDraw->y; 73105b261ecSmrg edgey2 += pDraw->y; 73205b261ecSmrg } 73305b261ecSmrg xlk = x0 + x0 + 1.0; 73405b261ecSmrg xrk = x0 + x0 - 1.0; 73505b261ecSmrg yk = y0 + y0 - 1.0; 73605b261ecSmrg radius = ((double)pGC->lineWidth) / 2.0; 73705b261ecSmrg y = floor(radius - y0 + 1.0); 73805b261ecSmrg ybase -= y; 73905b261ecSmrg ymin = ybase; 74005b261ecSmrg ymax = 65536; 74105b261ecSmrg edge1IsMin = FALSE; 74205b261ecSmrg ymin1 = edgey1; 74305b261ecSmrg if (edge1->dy >= 0) 74405b261ecSmrg { 74505b261ecSmrg if (!edge1->dy) 74605b261ecSmrg { 74705b261ecSmrg if (edgeleft1) 74805b261ecSmrg edge1IsMin = TRUE; 74905b261ecSmrg else 75005b261ecSmrg ymax = edgey1; 75105b261ecSmrg edgey1 = 65536; 75205b261ecSmrg } 75305b261ecSmrg else 75405b261ecSmrg { 75505b261ecSmrg if ((edge1->signdx < 0) == edgeleft1) 75605b261ecSmrg edge1IsMin = TRUE; 75705b261ecSmrg } 75805b261ecSmrg } 75905b261ecSmrg edge2IsMin = FALSE; 76005b261ecSmrg ymin2 = edgey2; 76105b261ecSmrg if (edge2->dy >= 0) 76205b261ecSmrg { 76305b261ecSmrg if (!edge2->dy) 76405b261ecSmrg { 76505b261ecSmrg if (edgeleft2) 76605b261ecSmrg edge2IsMin = TRUE; 76705b261ecSmrg else 76805b261ecSmrg ymax = edgey2; 76905b261ecSmrg edgey2 = 65536; 77005b261ecSmrg } 77105b261ecSmrg else 77205b261ecSmrg { 77305b261ecSmrg if ((edge2->signdx < 0) == edgeleft2) 77405b261ecSmrg edge2IsMin = TRUE; 77505b261ecSmrg } 77605b261ecSmrg } 77705b261ecSmrg if (edge1IsMin) 77805b261ecSmrg { 77905b261ecSmrg ymin = ymin1; 78005b261ecSmrg if (edge2IsMin && ymin1 > ymin2) 78105b261ecSmrg ymin = ymin2; 78205b261ecSmrg } else if (edge2IsMin) 78305b261ecSmrg ymin = ymin2; 78405b261ecSmrg el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0); 78505b261ecSmrg er = el + xrk; 78605b261ecSmrg xl = 1; 78705b261ecSmrg xr = 0; 78805b261ecSmrg if (x0 < 0.5) 78905b261ecSmrg { 79005b261ecSmrg xl = 0; 79105b261ecSmrg el -= xlk; 79205b261ecSmrg } 79305b261ecSmrg boty = (y0 < -0.5) ? 1 : 0; 79405b261ecSmrg if (ybase + y - boty > ymax) 79505b261ecSmrg boty = ymax - ybase - y; 79605b261ecSmrg while (y > boty) 79705b261ecSmrg { 79805b261ecSmrg k = (y << 1) + yk; 79905b261ecSmrg er += k; 80005b261ecSmrg while (er > 0.0) 80105b261ecSmrg { 80205b261ecSmrg xr++; 80305b261ecSmrg er += xrk - (xr << 1); 80405b261ecSmrg } 80505b261ecSmrg el += k; 80605b261ecSmrg while (el >= 0.0) 80705b261ecSmrg { 80805b261ecSmrg xl--; 80905b261ecSmrg el += (xl << 1) - xlk; 81005b261ecSmrg } 81105b261ecSmrg y--; 81205b261ecSmrg ybase++; 81305b261ecSmrg if (ybase < ymin) 81405b261ecSmrg continue; 81505b261ecSmrg xcl = xl + xbase; 81605b261ecSmrg xcr = xr + xbase; 81705b261ecSmrg CLIPSTEPEDGE(edgey1, edge1, edgeleft1); 81805b261ecSmrg CLIPSTEPEDGE(edgey2, edge2, edgeleft2); 81905b261ecSmrg if (xcr >= xcl) 82005b261ecSmrg { 82105b261ecSmrg pts->x = xcl; 82205b261ecSmrg pts->y = ybase; 82305b261ecSmrg pts++; 82405b261ecSmrg *wids++ = xcr - xcl + 1; 82505b261ecSmrg } 82605b261ecSmrg } 82705b261ecSmrg er = xrk - (xr << 1) - er; 82805b261ecSmrg el = (xl << 1) - xlk - el; 82905b261ecSmrg boty = floor(-y0 - radius + 1.0); 83005b261ecSmrg if (ybase + y - boty > ymax) 83105b261ecSmrg boty = ymax - ybase - y; 83205b261ecSmrg while (y > boty) 83305b261ecSmrg { 83405b261ecSmrg k = (y << 1) + yk; 83505b261ecSmrg er -= k; 83605b261ecSmrg while ((er >= 0.0) && (xr >= 0)) 83705b261ecSmrg { 83805b261ecSmrg xr--; 83905b261ecSmrg er += xrk - (xr << 1); 84005b261ecSmrg } 84105b261ecSmrg el -= k; 84205b261ecSmrg while ((el > 0.0) && (xl <= 0)) 84305b261ecSmrg { 84405b261ecSmrg xl++; 84505b261ecSmrg el += (xl << 1) - xlk; 84605b261ecSmrg } 84705b261ecSmrg y--; 84805b261ecSmrg ybase++; 84905b261ecSmrg if (ybase < ymin) 85005b261ecSmrg continue; 85105b261ecSmrg xcl = xl + xbase; 85205b261ecSmrg xcr = xr + xbase; 85305b261ecSmrg CLIPSTEPEDGE(edgey1, edge1, edgeleft1); 85405b261ecSmrg CLIPSTEPEDGE(edgey2, edge2, edgeleft2); 85505b261ecSmrg if (xcr >= xcl) 85605b261ecSmrg { 85705b261ecSmrg pts->x = xcl; 85805b261ecSmrg pts->y = ybase; 85905b261ecSmrg pts++; 86005b261ecSmrg *wids++ = xcr - xcl + 1; 86105b261ecSmrg } 86205b261ecSmrg } 86305b261ecSmrg return (pts - points); 86405b261ecSmrg} 86505b261ecSmrg 86605b261ecSmrgstatic int 86705b261ecSmrgmiRoundJoinFace (LineFacePtr face, PolyEdgePtr edge, Bool *leftEdge) 86805b261ecSmrg{ 86905b261ecSmrg int y; 87005b261ecSmrg int dx, dy; 87105b261ecSmrg double xa, ya; 87205b261ecSmrg Bool left; 87305b261ecSmrg 87405b261ecSmrg dx = -face->dy; 87505b261ecSmrg dy = face->dx; 87605b261ecSmrg xa = face->xa; 87705b261ecSmrg ya = face->ya; 87805b261ecSmrg left = 1; 87905b261ecSmrg if (ya > 0) 88005b261ecSmrg { 88105b261ecSmrg ya = 0.0; 88205b261ecSmrg xa = 0.0; 88305b261ecSmrg } 88405b261ecSmrg if (dy < 0 || (dy == 0 && dx > 0)) 88505b261ecSmrg { 88605b261ecSmrg dx = -dx; 88705b261ecSmrg dy = -dy; 88805b261ecSmrg left = !left; 88905b261ecSmrg } 89005b261ecSmrg if (dx == 0 && dy == 0) 89105b261ecSmrg dy = 1; 89205b261ecSmrg if (dy == 0) 89305b261ecSmrg { 89405b261ecSmrg y = ICEIL (face->ya) + face->y; 89505b261ecSmrg edge->x = -32767; 89605b261ecSmrg edge->stepx = 0; 89705b261ecSmrg edge->signdx = 0; 89805b261ecSmrg edge->e = -1; 89905b261ecSmrg edge->dy = 0; 90005b261ecSmrg edge->dx = 0; 90105b261ecSmrg edge->height = 0; 90205b261ecSmrg } 90305b261ecSmrg else 90405b261ecSmrg { 90505b261ecSmrg y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge); 90605b261ecSmrg edge->height = 32767; 90705b261ecSmrg } 90805b261ecSmrg *leftEdge = !left; 90905b261ecSmrg return y; 91005b261ecSmrg} 91105b261ecSmrg 91205b261ecSmrg_X_EXPORT void 91305b261ecSmrgmiRoundJoinClip (pLeft, pRight, edge1, edge2, y1, y2, left1, left2) 91405b261ecSmrg LineFacePtr pLeft, pRight; 91505b261ecSmrg PolyEdgePtr edge1, edge2; 91605b261ecSmrg int *y1, *y2; 91705b261ecSmrg Bool *left1, *left2; 91805b261ecSmrg{ 91905b261ecSmrg double denom; 92005b261ecSmrg 92105b261ecSmrg denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; 92205b261ecSmrg 92305b261ecSmrg if (denom >= 0) 92405b261ecSmrg { 92505b261ecSmrg pLeft->xa = -pLeft->xa; 92605b261ecSmrg pLeft->ya = -pLeft->ya; 92705b261ecSmrg } 92805b261ecSmrg else 92905b261ecSmrg { 93005b261ecSmrg pRight->xa = -pRight->xa; 93105b261ecSmrg pRight->ya = -pRight->ya; 93205b261ecSmrg } 93305b261ecSmrg *y1 = miRoundJoinFace (pLeft, edge1, left1); 93405b261ecSmrg *y2 = miRoundJoinFace (pRight, edge2, left2); 93505b261ecSmrg} 93605b261ecSmrg 93705b261ecSmrg_X_EXPORT int 93805b261ecSmrgmiRoundCapClip (face, isInt, edge, leftEdge) 93905b261ecSmrg LineFacePtr face; 94005b261ecSmrg Bool isInt; 94105b261ecSmrg PolyEdgePtr edge; 94205b261ecSmrg 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 { 104805b261ecSmrg points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * pGC->lineWidth); 104905b261ecSmrg if (!points) 105005b261ecSmrg return; 105105b261ecSmrg widths = (int *)ALLOCATE_LOCAL(sizeof(int) * pGC->lineWidth); 105205b261ecSmrg if (!widths) 105305b261ecSmrg { 105405b261ecSmrg DEALLOCATE_LOCAL(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); 108905b261ecSmrg DEALLOCATE_LOCAL(widths); 109005b261ecSmrg DEALLOCATE_LOCAL(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 152805b261ecSmrgmiWideLine (pDrawable, pGC, mode, npt, pPts) 152905b261ecSmrg DrawablePtr pDrawable; 153005b261ecSmrg GCPtr pGC; 153105b261ecSmrg int mode; 153205b261ecSmrg int npt; 153305b261ecSmrg DDXPointPtr pPts; 153405b261ecSmrg{ 153505b261ecSmrg int x1, y1, x2, y2; 153605b261ecSmrg SpanDataRec spanDataRec; 153705b261ecSmrg SpanDataPtr spanData; 153805b261ecSmrg long pixel; 153905b261ecSmrg Bool projectLeft, projectRight; 154005b261ecSmrg LineFaceRec leftFace, rightFace, prevRightFace; 154105b261ecSmrg LineFaceRec firstFace; 154205b261ecSmrg int first; 154305b261ecSmrg Bool somethingDrawn = FALSE; 154405b261ecSmrg Bool selfJoin; 154505b261ecSmrg 154605b261ecSmrg spanData = miSetupSpanData (pGC, &spanDataRec, npt); 154705b261ecSmrg pixel = pGC->fgPixel; 154805b261ecSmrg x2 = pPts->x; 154905b261ecSmrg y2 = pPts->y; 155005b261ecSmrg first = TRUE; 155105b261ecSmrg selfJoin = FALSE; 155205b261ecSmrg if (npt > 1) 155305b261ecSmrg { 155405b261ecSmrg if (mode == CoordModePrevious) 155505b261ecSmrg { 155605b261ecSmrg int nptTmp; 155705b261ecSmrg DDXPointPtr pPtsTmp; 155805b261ecSmrg 155905b261ecSmrg x1 = x2; 156005b261ecSmrg y1 = y2; 156105b261ecSmrg nptTmp = npt; 156205b261ecSmrg pPtsTmp = pPts + 1; 156305b261ecSmrg while (--nptTmp) 156405b261ecSmrg { 156505b261ecSmrg x1 += pPtsTmp->x; 156605b261ecSmrg y1 += pPtsTmp->y; 156705b261ecSmrg ++pPtsTmp; 156805b261ecSmrg } 156905b261ecSmrg if (x2 == x1 && y2 == y1) 157005b261ecSmrg selfJoin = TRUE; 157105b261ecSmrg } 157205b261ecSmrg else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y) 157305b261ecSmrg { 157405b261ecSmrg selfJoin = TRUE; 157505b261ecSmrg } 157605b261ecSmrg } 157705b261ecSmrg projectLeft = pGC->capStyle == CapProjecting && !selfJoin; 157805b261ecSmrg projectRight = FALSE; 157905b261ecSmrg while (--npt) 158005b261ecSmrg { 158105b261ecSmrg x1 = x2; 158205b261ecSmrg y1 = y2; 158305b261ecSmrg ++pPts; 158405b261ecSmrg x2 = pPts->x; 158505b261ecSmrg y2 = pPts->y; 158605b261ecSmrg if (mode == CoordModePrevious) 158705b261ecSmrg { 158805b261ecSmrg x2 += x1; 158905b261ecSmrg y2 += y1; 159005b261ecSmrg } 159105b261ecSmrg if (x1 != x2 || y1 != y2) 159205b261ecSmrg { 159305b261ecSmrg somethingDrawn = TRUE; 159405b261ecSmrg if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin) 159505b261ecSmrg projectRight = TRUE; 159605b261ecSmrg miWideSegment (pDrawable, pGC, pixel, spanData, x1, y1, x2, y2, 159705b261ecSmrg projectLeft, projectRight, &leftFace, &rightFace); 159805b261ecSmrg if (first) 159905b261ecSmrg { 160005b261ecSmrg if (selfJoin) 160105b261ecSmrg firstFace = leftFace; 160205b261ecSmrg else if (pGC->capStyle == CapRound) 160305b261ecSmrg { 160405b261ecSmrg if (pGC->lineWidth == 1 && !spanData) 160505b261ecSmrg miLineOnePoint (pDrawable, pGC, pixel, spanData, x1, y1); 160605b261ecSmrg else 160705b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 160805b261ecSmrg &leftFace, (LineFacePtr) NULL, 160905b261ecSmrg (double)0.0, (double)0.0, 161005b261ecSmrg TRUE); 161105b261ecSmrg } 161205b261ecSmrg } 161305b261ecSmrg else 161405b261ecSmrg { 161505b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace, 161605b261ecSmrg &prevRightFace); 161705b261ecSmrg } 161805b261ecSmrg prevRightFace = rightFace; 161905b261ecSmrg first = FALSE; 162005b261ecSmrg projectLeft = FALSE; 162105b261ecSmrg } 162205b261ecSmrg if (npt == 1 && somethingDrawn) 162305b261ecSmrg { 162405b261ecSmrg if (selfJoin) 162505b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace, 162605b261ecSmrg &rightFace); 162705b261ecSmrg else if (pGC->capStyle == CapRound) 162805b261ecSmrg { 162905b261ecSmrg if (pGC->lineWidth == 1 && !spanData) 163005b261ecSmrg miLineOnePoint (pDrawable, pGC, pixel, spanData, x2, y2); 163105b261ecSmrg else 163205b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 163305b261ecSmrg (LineFacePtr) NULL, &rightFace, 163405b261ecSmrg (double)0.0, (double)0.0, 163505b261ecSmrg TRUE); 163605b261ecSmrg } 163705b261ecSmrg } 163805b261ecSmrg } 163905b261ecSmrg /* handle crock where all points are coincedent */ 164005b261ecSmrg if (!somethingDrawn) 164105b261ecSmrg { 164205b261ecSmrg projectLeft = pGC->capStyle == CapProjecting; 164305b261ecSmrg miWideSegment (pDrawable, pGC, pixel, spanData, 164405b261ecSmrg x2, y2, x2, y2, projectLeft, projectLeft, 164505b261ecSmrg &leftFace, &rightFace); 164605b261ecSmrg if (pGC->capStyle == CapRound) 164705b261ecSmrg { 164805b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 164905b261ecSmrg &leftFace, (LineFacePtr) NULL, 165005b261ecSmrg (double)0.0, (double)0.0, 165105b261ecSmrg TRUE); 165205b261ecSmrg rightFace.dx = -1; /* sleezy hack to make it work */ 165305b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 165405b261ecSmrg (LineFacePtr) NULL, &rightFace, 165505b261ecSmrg (double)0.0, (double)0.0, 165605b261ecSmrg TRUE); 165705b261ecSmrg } 165805b261ecSmrg } 165905b261ecSmrg if (spanData) 166005b261ecSmrg miCleanupSpanData (pDrawable, pGC, spanData); 166105b261ecSmrg} 166205b261ecSmrg 166305b261ecSmrg#define V_TOP 0 166405b261ecSmrg#define V_RIGHT 1 166505b261ecSmrg#define V_BOTTOM 2 166605b261ecSmrg#define V_LEFT 3 166705b261ecSmrg 166805b261ecSmrgstatic void 166905b261ecSmrgmiWideDashSegment ( 167005b261ecSmrg DrawablePtr pDrawable, 167105b261ecSmrg GCPtr pGC, 167205b261ecSmrg SpanDataPtr spanData, 167305b261ecSmrg int *pDashOffset, 167405b261ecSmrg int *pDashIndex, 167505b261ecSmrg int x1, 167605b261ecSmrg int y1, 167705b261ecSmrg int x2, 167805b261ecSmrg int y2, 167905b261ecSmrg Bool projectLeft, 168005b261ecSmrg Bool projectRight, 168105b261ecSmrg LineFacePtr leftFace, 168205b261ecSmrg LineFacePtr rightFace) 168305b261ecSmrg{ 168405b261ecSmrg int dashIndex, dashRemain; 168505b261ecSmrg unsigned char *pDash; 168605b261ecSmrg double L, l; 168705b261ecSmrg double k; 168805b261ecSmrg PolyVertexRec vertices[4]; 168905b261ecSmrg PolyVertexRec saveRight, saveBottom; 169005b261ecSmrg PolySlopeRec slopes[4]; 169105b261ecSmrg PolyEdgeRec left[2], right[2]; 169205b261ecSmrg LineFaceRec lcapFace, rcapFace; 169305b261ecSmrg int nleft, nright; 169405b261ecSmrg int h; 169505b261ecSmrg int y; 169605b261ecSmrg int dy, dx; 169705b261ecSmrg unsigned long pixel; 169805b261ecSmrg double LRemain; 169905b261ecSmrg double r; 170005b261ecSmrg double rdx, rdy; 170105b261ecSmrg double dashDx, dashDy; 170205b261ecSmrg double saveK = 0.0; 170305b261ecSmrg Bool first = TRUE; 170405b261ecSmrg double lcenterx, lcentery, rcenterx = 0.0, rcentery = 0.0; 170505b261ecSmrg unsigned long fgPixel, bgPixel; 170605b261ecSmrg 170705b261ecSmrg dx = x2 - x1; 170805b261ecSmrg dy = y2 - y1; 170905b261ecSmrg dashIndex = *pDashIndex; 171005b261ecSmrg pDash = pGC->dash; 171105b261ecSmrg dashRemain = pDash[dashIndex] - *pDashOffset; 171205b261ecSmrg fgPixel = pGC->fgPixel; 171305b261ecSmrg bgPixel = pGC->bgPixel; 171405b261ecSmrg if (pGC->fillStyle == FillOpaqueStippled || 171505b261ecSmrg pGC->fillStyle == FillTiled) 171605b261ecSmrg { 171705b261ecSmrg bgPixel = fgPixel; 171805b261ecSmrg } 171905b261ecSmrg 172005b261ecSmrg l = ((double) pGC->lineWidth) / 2.0; 172105b261ecSmrg if (dx == 0) 172205b261ecSmrg { 172305b261ecSmrg L = dy; 172405b261ecSmrg rdx = 0; 172505b261ecSmrg rdy = l; 172605b261ecSmrg if (dy < 0) 172705b261ecSmrg { 172805b261ecSmrg L = -dy; 172905b261ecSmrg rdy = -l; 173005b261ecSmrg } 173105b261ecSmrg } 173205b261ecSmrg else if (dy == 0) 173305b261ecSmrg { 173405b261ecSmrg L = dx; 173505b261ecSmrg rdx = l; 173605b261ecSmrg rdy = 0; 173705b261ecSmrg if (dx < 0) 173805b261ecSmrg { 173905b261ecSmrg L = -dx; 174005b261ecSmrg rdx = -l; 174105b261ecSmrg } 174205b261ecSmrg } 174305b261ecSmrg else 174405b261ecSmrg { 174505b261ecSmrg L = hypot ((double) dx, (double) dy); 174605b261ecSmrg r = l / L; 174705b261ecSmrg 174805b261ecSmrg rdx = r * dx; 174905b261ecSmrg rdy = r * dy; 175005b261ecSmrg } 175105b261ecSmrg k = l * L; 175205b261ecSmrg LRemain = L; 175305b261ecSmrg /* All position comments are relative to a line with dx and dy > 0, 175405b261ecSmrg * but the code does not depend on this */ 175505b261ecSmrg /* top */ 175605b261ecSmrg slopes[V_TOP].dx = dx; 175705b261ecSmrg slopes[V_TOP].dy = dy; 175805b261ecSmrg slopes[V_TOP].k = k; 175905b261ecSmrg /* right */ 176005b261ecSmrg slopes[V_RIGHT].dx = -dy; 176105b261ecSmrg slopes[V_RIGHT].dy = dx; 176205b261ecSmrg slopes[V_RIGHT].k = 0; 176305b261ecSmrg /* bottom */ 176405b261ecSmrg slopes[V_BOTTOM].dx = -dx; 176505b261ecSmrg slopes[V_BOTTOM].dy = -dy; 176605b261ecSmrg slopes[V_BOTTOM].k = k; 176705b261ecSmrg /* left */ 176805b261ecSmrg slopes[V_LEFT].dx = dy; 176905b261ecSmrg slopes[V_LEFT].dy = -dx; 177005b261ecSmrg slopes[V_LEFT].k = 0; 177105b261ecSmrg 177205b261ecSmrg /* preload the start coordinates */ 177305b261ecSmrg vertices[V_RIGHT].x = vertices[V_TOP].x = rdy; 177405b261ecSmrg vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx; 177505b261ecSmrg 177605b261ecSmrg vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy; 177705b261ecSmrg vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx; 177805b261ecSmrg 177905b261ecSmrg if (projectLeft) 178005b261ecSmrg { 178105b261ecSmrg vertices[V_TOP].x -= rdx; 178205b261ecSmrg vertices[V_TOP].y -= rdy; 178305b261ecSmrg 178405b261ecSmrg vertices[V_LEFT].x -= rdx; 178505b261ecSmrg vertices[V_LEFT].y -= rdy; 178605b261ecSmrg 178705b261ecSmrg slopes[V_LEFT].k = rdx * dx + rdy * dy; 178805b261ecSmrg } 178905b261ecSmrg 179005b261ecSmrg lcenterx = x1; 179105b261ecSmrg lcentery = y1; 179205b261ecSmrg 179305b261ecSmrg if (pGC->capStyle == CapRound) 179405b261ecSmrg { 179505b261ecSmrg lcapFace.dx = dx; 179605b261ecSmrg lcapFace.dy = dy; 179705b261ecSmrg lcapFace.x = x1; 179805b261ecSmrg lcapFace.y = y1; 179905b261ecSmrg 180005b261ecSmrg rcapFace.dx = -dx; 180105b261ecSmrg rcapFace.dy = -dy; 180205b261ecSmrg rcapFace.x = x1; 180305b261ecSmrg rcapFace.y = y1; 180405b261ecSmrg } 180505b261ecSmrg while (LRemain > dashRemain) 180605b261ecSmrg { 180705b261ecSmrg dashDx = (dashRemain * dx) / L; 180805b261ecSmrg dashDy = (dashRemain * dy) / L; 180905b261ecSmrg 181005b261ecSmrg rcenterx = lcenterx + dashDx; 181105b261ecSmrg rcentery = lcentery + dashDy; 181205b261ecSmrg 181305b261ecSmrg vertices[V_RIGHT].x += dashDx; 181405b261ecSmrg vertices[V_RIGHT].y += dashDy; 181505b261ecSmrg 181605b261ecSmrg vertices[V_BOTTOM].x += dashDx; 181705b261ecSmrg vertices[V_BOTTOM].y += dashDy; 181805b261ecSmrg 181905b261ecSmrg slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy; 182005b261ecSmrg 182105b261ecSmrg if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) 182205b261ecSmrg { 182305b261ecSmrg if (pGC->lineStyle == LineOnOffDash && 182405b261ecSmrg pGC->capStyle == CapProjecting) 182505b261ecSmrg { 182605b261ecSmrg saveRight = vertices[V_RIGHT]; 182705b261ecSmrg saveBottom = vertices[V_BOTTOM]; 182805b261ecSmrg saveK = slopes[V_RIGHT].k; 182905b261ecSmrg 183005b261ecSmrg if (!first) 183105b261ecSmrg { 183205b261ecSmrg vertices[V_TOP].x -= rdx; 183305b261ecSmrg vertices[V_TOP].y -= rdy; 183405b261ecSmrg 183505b261ecSmrg vertices[V_LEFT].x -= rdx; 183605b261ecSmrg vertices[V_LEFT].y -= rdy; 183705b261ecSmrg 183805b261ecSmrg slopes[V_LEFT].k = vertices[V_LEFT].x * 183905b261ecSmrg slopes[V_LEFT].dy - 184005b261ecSmrg vertices[V_LEFT].y * 184105b261ecSmrg slopes[V_LEFT].dx; 184205b261ecSmrg } 184305b261ecSmrg 184405b261ecSmrg vertices[V_RIGHT].x += rdx; 184505b261ecSmrg vertices[V_RIGHT].y += rdy; 184605b261ecSmrg 184705b261ecSmrg vertices[V_BOTTOM].x += rdx; 184805b261ecSmrg vertices[V_BOTTOM].y += rdy; 184905b261ecSmrg 185005b261ecSmrg slopes[V_RIGHT].k = vertices[V_RIGHT].x * 185105b261ecSmrg slopes[V_RIGHT].dy - 185205b261ecSmrg vertices[V_RIGHT].y * 185305b261ecSmrg slopes[V_RIGHT].dx; 185405b261ecSmrg } 185505b261ecSmrg y = miPolyBuildPoly (vertices, slopes, 4, x1, y1, 185605b261ecSmrg left, right, &nleft, &nright, &h); 185705b261ecSmrg pixel = (dashIndex & 1) ? bgPixel : fgPixel; 185805b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright); 185905b261ecSmrg 186005b261ecSmrg if (pGC->lineStyle == LineOnOffDash) 186105b261ecSmrg { 186205b261ecSmrg switch (pGC->capStyle) 186305b261ecSmrg { 186405b261ecSmrg case CapProjecting: 186505b261ecSmrg vertices[V_BOTTOM] = saveBottom; 186605b261ecSmrg vertices[V_RIGHT] = saveRight; 186705b261ecSmrg slopes[V_RIGHT].k = saveK; 186805b261ecSmrg break; 186905b261ecSmrg case CapRound: 187005b261ecSmrg if (!first) 187105b261ecSmrg { 187205b261ecSmrg if (dx < 0) 187305b261ecSmrg { 187405b261ecSmrg lcapFace.xa = -vertices[V_LEFT].x; 187505b261ecSmrg lcapFace.ya = -vertices[V_LEFT].y; 187605b261ecSmrg lcapFace.k = slopes[V_LEFT].k; 187705b261ecSmrg } 187805b261ecSmrg else 187905b261ecSmrg { 188005b261ecSmrg lcapFace.xa = vertices[V_TOP].x; 188105b261ecSmrg lcapFace.ya = vertices[V_TOP].y; 188205b261ecSmrg lcapFace.k = -slopes[V_LEFT].k; 188305b261ecSmrg } 188405b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 188505b261ecSmrg &lcapFace, (LineFacePtr) NULL, 188605b261ecSmrg lcenterx, lcentery, FALSE); 188705b261ecSmrg } 188805b261ecSmrg if (dx < 0) 188905b261ecSmrg { 189005b261ecSmrg rcapFace.xa = vertices[V_BOTTOM].x; 189105b261ecSmrg rcapFace.ya = vertices[V_BOTTOM].y; 189205b261ecSmrg rcapFace.k = slopes[V_RIGHT].k; 189305b261ecSmrg } 189405b261ecSmrg else 189505b261ecSmrg { 189605b261ecSmrg rcapFace.xa = -vertices[V_RIGHT].x; 189705b261ecSmrg rcapFace.ya = -vertices[V_RIGHT].y; 189805b261ecSmrg rcapFace.k = -slopes[V_RIGHT].k; 189905b261ecSmrg } 190005b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 190105b261ecSmrg (LineFacePtr) NULL, &rcapFace, 190205b261ecSmrg rcenterx, rcentery, FALSE); 190305b261ecSmrg break; 190405b261ecSmrg } 190505b261ecSmrg } 190605b261ecSmrg } 190705b261ecSmrg LRemain -= dashRemain; 190805b261ecSmrg ++dashIndex; 190905b261ecSmrg if (dashIndex == pGC->numInDashList) 191005b261ecSmrg dashIndex = 0; 191105b261ecSmrg dashRemain = pDash[dashIndex]; 191205b261ecSmrg 191305b261ecSmrg lcenterx = rcenterx; 191405b261ecSmrg lcentery = rcentery; 191505b261ecSmrg 191605b261ecSmrg vertices[V_TOP] = vertices[V_RIGHT]; 191705b261ecSmrg vertices[V_LEFT] = vertices[V_BOTTOM]; 191805b261ecSmrg slopes[V_LEFT].k = -slopes[V_RIGHT].k; 191905b261ecSmrg first = FALSE; 192005b261ecSmrg } 192105b261ecSmrg 192205b261ecSmrg if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) 192305b261ecSmrg { 192405b261ecSmrg vertices[V_TOP].x -= dx; 192505b261ecSmrg vertices[V_TOP].y -= dy; 192605b261ecSmrg 192705b261ecSmrg vertices[V_LEFT].x -= dx; 192805b261ecSmrg vertices[V_LEFT].y -= dy; 192905b261ecSmrg 193005b261ecSmrg vertices[V_RIGHT].x = rdy; 193105b261ecSmrg vertices[V_RIGHT].y = -rdx; 193205b261ecSmrg 193305b261ecSmrg vertices[V_BOTTOM].x = -rdy; 193405b261ecSmrg vertices[V_BOTTOM].y = rdx; 193505b261ecSmrg 193605b261ecSmrg 193705b261ecSmrg if (projectRight) 193805b261ecSmrg { 193905b261ecSmrg vertices[V_RIGHT].x += rdx; 194005b261ecSmrg vertices[V_RIGHT].y += rdy; 194105b261ecSmrg 194205b261ecSmrg vertices[V_BOTTOM].x += rdx; 194305b261ecSmrg vertices[V_BOTTOM].y += rdy; 194405b261ecSmrg slopes[V_RIGHT].k = vertices[V_RIGHT].x * 194505b261ecSmrg slopes[V_RIGHT].dy - 194605b261ecSmrg vertices[V_RIGHT].y * 194705b261ecSmrg slopes[V_RIGHT].dx; 194805b261ecSmrg } 194905b261ecSmrg else 195005b261ecSmrg slopes[V_RIGHT].k = 0; 195105b261ecSmrg 195205b261ecSmrg if (!first && pGC->lineStyle == LineOnOffDash && 195305b261ecSmrg pGC->capStyle == CapProjecting) 195405b261ecSmrg { 195505b261ecSmrg vertices[V_TOP].x -= rdx; 195605b261ecSmrg vertices[V_TOP].y -= rdy; 195705b261ecSmrg 195805b261ecSmrg vertices[V_LEFT].x -= rdx; 195905b261ecSmrg vertices[V_LEFT].y -= rdy; 196005b261ecSmrg slopes[V_LEFT].k = vertices[V_LEFT].x * 196105b261ecSmrg slopes[V_LEFT].dy - 196205b261ecSmrg vertices[V_LEFT].y * 196305b261ecSmrg slopes[V_LEFT].dx; 196405b261ecSmrg } 196505b261ecSmrg else 196605b261ecSmrg slopes[V_LEFT].k += dx * dx + dy * dy; 196705b261ecSmrg 196805b261ecSmrg 196905b261ecSmrg y = miPolyBuildPoly (vertices, slopes, 4, x2, y2, 197005b261ecSmrg left, right, &nleft, &nright, &h); 197105b261ecSmrg 197205b261ecSmrg pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel; 197305b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright); 197405b261ecSmrg if (!first && pGC->lineStyle == LineOnOffDash && 197505b261ecSmrg pGC->capStyle == CapRound) 197605b261ecSmrg { 197705b261ecSmrg lcapFace.x = x2; 197805b261ecSmrg lcapFace.y = y2; 197905b261ecSmrg if (dx < 0) 198005b261ecSmrg { 198105b261ecSmrg lcapFace.xa = -vertices[V_LEFT].x; 198205b261ecSmrg lcapFace.ya = -vertices[V_LEFT].y; 198305b261ecSmrg lcapFace.k = slopes[V_LEFT].k; 198405b261ecSmrg } 198505b261ecSmrg else 198605b261ecSmrg { 198705b261ecSmrg lcapFace.xa = vertices[V_TOP].x; 198805b261ecSmrg lcapFace.ya = vertices[V_TOP].y; 198905b261ecSmrg lcapFace.k = -slopes[V_LEFT].k; 199005b261ecSmrg } 199105b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 199205b261ecSmrg &lcapFace, (LineFacePtr) NULL, 199305b261ecSmrg rcenterx, rcentery, FALSE); 199405b261ecSmrg } 199505b261ecSmrg } 199605b261ecSmrg dashRemain = ((double) dashRemain) - LRemain; 199705b261ecSmrg if (dashRemain == 0) 199805b261ecSmrg { 199905b261ecSmrg dashIndex++; 200005b261ecSmrg if (dashIndex == pGC->numInDashList) 200105b261ecSmrg dashIndex = 0; 200205b261ecSmrg dashRemain = pDash[dashIndex]; 200305b261ecSmrg } 200405b261ecSmrg 200505b261ecSmrg leftFace->x = x1; 200605b261ecSmrg leftFace->y = y1; 200705b261ecSmrg leftFace->dx = dx; 200805b261ecSmrg leftFace->dy = dy; 200905b261ecSmrg leftFace->xa = rdy; 201005b261ecSmrg leftFace->ya = -rdx; 201105b261ecSmrg leftFace->k = k; 201205b261ecSmrg 201305b261ecSmrg rightFace->x = x2; 201405b261ecSmrg rightFace->y = y2; 201505b261ecSmrg rightFace->dx = -dx; 201605b261ecSmrg rightFace->dy = -dy; 201705b261ecSmrg rightFace->xa = -rdy; 201805b261ecSmrg rightFace->ya = rdx; 201905b261ecSmrg rightFace->k = k; 202005b261ecSmrg 202105b261ecSmrg *pDashIndex = dashIndex; 202205b261ecSmrg *pDashOffset = pDash[dashIndex] - dashRemain; 202305b261ecSmrg} 202405b261ecSmrg 202505b261ecSmrg_X_EXPORT void 202605b261ecSmrgmiWideDash (pDrawable, pGC, mode, npt, pPts) 202705b261ecSmrg DrawablePtr pDrawable; 202805b261ecSmrg GCPtr pGC; 202905b261ecSmrg int mode; 203005b261ecSmrg int npt; 203105b261ecSmrg DDXPointPtr pPts; 203205b261ecSmrg{ 203305b261ecSmrg int x1, y1, x2, y2; 203405b261ecSmrg unsigned long pixel; 203505b261ecSmrg Bool projectLeft, projectRight; 203605b261ecSmrg LineFaceRec leftFace, rightFace, prevRightFace; 203705b261ecSmrg LineFaceRec firstFace; 203805b261ecSmrg int first; 203905b261ecSmrg int dashIndex, dashOffset; 204005b261ecSmrg int prevDashIndex; 204105b261ecSmrg SpanDataRec spanDataRec; 204205b261ecSmrg SpanDataPtr spanData; 204305b261ecSmrg Bool somethingDrawn = FALSE; 204405b261ecSmrg Bool selfJoin; 204505b261ecSmrg Bool endIsFg = FALSE, startIsFg = FALSE; 204605b261ecSmrg Bool firstIsFg = FALSE, prevIsFg = FALSE; 204705b261ecSmrg 204805b261ecSmrg#if 0 204905b261ecSmrg /* XXX backward compatibility */ 205005b261ecSmrg if (pGC->lineWidth == 0) 205105b261ecSmrg { 205205b261ecSmrg miZeroDashLine (pDrawable, pGC, mode, npt, pPts); 205305b261ecSmrg return; 205405b261ecSmrg } 205505b261ecSmrg#endif 205605b261ecSmrg if (pGC->lineStyle == LineDoubleDash && 205705b261ecSmrg (pGC->fillStyle == FillOpaqueStippled || pGC->fillStyle == FillTiled)) 205805b261ecSmrg { 205905b261ecSmrg miWideLine (pDrawable, pGC, mode, npt, pPts); 206005b261ecSmrg return; 206105b261ecSmrg } 206205b261ecSmrg if (npt == 0) 206305b261ecSmrg return; 206405b261ecSmrg spanData = miSetupSpanData (pGC, &spanDataRec, npt); 206505b261ecSmrg x2 = pPts->x; 206605b261ecSmrg y2 = pPts->y; 206705b261ecSmrg first = TRUE; 206805b261ecSmrg selfJoin = FALSE; 206905b261ecSmrg if (mode == CoordModePrevious) 207005b261ecSmrg { 207105b261ecSmrg int nptTmp; 207205b261ecSmrg DDXPointPtr pPtsTmp; 207305b261ecSmrg 207405b261ecSmrg x1 = x2; 207505b261ecSmrg y1 = y2; 207605b261ecSmrg nptTmp = npt; 207705b261ecSmrg pPtsTmp = pPts + 1; 207805b261ecSmrg while (--nptTmp) 207905b261ecSmrg { 208005b261ecSmrg x1 += pPtsTmp->x; 208105b261ecSmrg y1 += pPtsTmp->y; 208205b261ecSmrg ++pPtsTmp; 208305b261ecSmrg } 208405b261ecSmrg if (x2 == x1 && y2 == y1) 208505b261ecSmrg selfJoin = TRUE; 208605b261ecSmrg } 208705b261ecSmrg else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y) 208805b261ecSmrg { 208905b261ecSmrg selfJoin = TRUE; 209005b261ecSmrg } 209105b261ecSmrg projectLeft = pGC->capStyle == CapProjecting && !selfJoin; 209205b261ecSmrg projectRight = FALSE; 209305b261ecSmrg dashIndex = 0; 209405b261ecSmrg dashOffset = 0; 209505b261ecSmrg miStepDash ((int)pGC->dashOffset, &dashIndex, 209605b261ecSmrg pGC->dash, (int)pGC->numInDashList, &dashOffset); 209705b261ecSmrg while (--npt) 209805b261ecSmrg { 209905b261ecSmrg x1 = x2; 210005b261ecSmrg y1 = y2; 210105b261ecSmrg ++pPts; 210205b261ecSmrg x2 = pPts->x; 210305b261ecSmrg y2 = pPts->y; 210405b261ecSmrg if (mode == CoordModePrevious) 210505b261ecSmrg { 210605b261ecSmrg x2 += x1; 210705b261ecSmrg y2 += y1; 210805b261ecSmrg } 210905b261ecSmrg if (x1 != x2 || y1 != y2) 211005b261ecSmrg { 211105b261ecSmrg somethingDrawn = TRUE; 211205b261ecSmrg if (npt == 1 && pGC->capStyle == CapProjecting && 211305b261ecSmrg (!selfJoin || !firstIsFg)) 211405b261ecSmrg projectRight = TRUE; 211505b261ecSmrg prevDashIndex = dashIndex; 211605b261ecSmrg miWideDashSegment (pDrawable, pGC, spanData, &dashOffset, &dashIndex, 211705b261ecSmrg x1, y1, x2, y2, 211805b261ecSmrg projectLeft, projectRight, &leftFace, &rightFace); 211905b261ecSmrg startIsFg = !(prevDashIndex & 1); 212005b261ecSmrg endIsFg = (dashIndex & 1) ^ (dashOffset != 0); 212105b261ecSmrg if (pGC->lineStyle == LineDoubleDash || startIsFg) 212205b261ecSmrg { 212305b261ecSmrg pixel = startIsFg ? pGC->fgPixel : pGC->bgPixel; 212405b261ecSmrg if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg)) 212505b261ecSmrg { 212605b261ecSmrg if (first && selfJoin) 212705b261ecSmrg { 212805b261ecSmrg firstFace = leftFace; 212905b261ecSmrg firstIsFg = startIsFg; 213005b261ecSmrg } 213105b261ecSmrg else if (pGC->capStyle == CapRound) 213205b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 213305b261ecSmrg &leftFace, (LineFacePtr) NULL, 213405b261ecSmrg (double)0.0, (double)0.0, TRUE); 213505b261ecSmrg } 213605b261ecSmrg else 213705b261ecSmrg { 213805b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace, 213905b261ecSmrg &prevRightFace); 214005b261ecSmrg } 214105b261ecSmrg } 214205b261ecSmrg prevRightFace = rightFace; 214305b261ecSmrg prevIsFg = endIsFg; 214405b261ecSmrg first = FALSE; 214505b261ecSmrg projectLeft = FALSE; 214605b261ecSmrg } 214705b261ecSmrg if (npt == 1 && somethingDrawn) 214805b261ecSmrg { 214905b261ecSmrg if (pGC->lineStyle == LineDoubleDash || endIsFg) 215005b261ecSmrg { 215105b261ecSmrg pixel = endIsFg ? pGC->fgPixel : pGC->bgPixel; 215205b261ecSmrg if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg)) 215305b261ecSmrg { 215405b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace, 215505b261ecSmrg &rightFace); 215605b261ecSmrg } 215705b261ecSmrg else 215805b261ecSmrg { 215905b261ecSmrg if (pGC->capStyle == CapRound) 216005b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 216105b261ecSmrg (LineFacePtr) NULL, &rightFace, 216205b261ecSmrg (double)0.0, (double)0.0, TRUE); 216305b261ecSmrg } 216405b261ecSmrg } 216505b261ecSmrg else 216605b261ecSmrg { 216705b261ecSmrg /* glue a cap to the start of the line if 216805b261ecSmrg * we're OnOffDash and ended on odd dash 216905b261ecSmrg */ 217005b261ecSmrg if (selfJoin && firstIsFg) 217105b261ecSmrg { 217205b261ecSmrg pixel = pGC->fgPixel; 217305b261ecSmrg if (pGC->capStyle == CapProjecting) 217405b261ecSmrg miLineProjectingCap (pDrawable, pGC, pixel, spanData, 217505b261ecSmrg &firstFace, TRUE, 217605b261ecSmrg (double)0.0, (double)0.0, TRUE); 217705b261ecSmrg else if (pGC->capStyle == CapRound) 217805b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 217905b261ecSmrg &firstFace, (LineFacePtr) NULL, 218005b261ecSmrg (double)0.0, (double)0.0, TRUE); 218105b261ecSmrg } 218205b261ecSmrg } 218305b261ecSmrg } 218405b261ecSmrg } 218505b261ecSmrg /* handle crock where all points are coincident */ 218605b261ecSmrg if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))) 218705b261ecSmrg { 218805b261ecSmrg /* not the same as endIsFg computation above */ 218905b261ecSmrg pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel; 219005b261ecSmrg switch (pGC->capStyle) { 219105b261ecSmrg case CapRound: 219205b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 219305b261ecSmrg (LineFacePtr) NULL, (LineFacePtr) NULL, 219405b261ecSmrg (double)x2, (double)y2, 219505b261ecSmrg FALSE); 219605b261ecSmrg break; 219705b261ecSmrg case CapProjecting: 219805b261ecSmrg x1 = pGC->lineWidth; 219905b261ecSmrg miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, 220005b261ecSmrg x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1); 220105b261ecSmrg break; 220205b261ecSmrg } 220305b261ecSmrg } 220405b261ecSmrg if (spanData) 220505b261ecSmrg miCleanupSpanData (pDrawable, pGC, spanData); 220605b261ecSmrg} 2207