miwideline.c revision 6747b715
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 556747b715Smrgstatic Bool 566747b715SmrgInitSpans(Spans *spans, size_t nspans) 576747b715Smrg{ 586747b715Smrg spans->points = malloc(nspans * sizeof (*spans->points)); 596747b715Smrg if (!spans->points) 606747b715Smrg return FALSE; 616747b715Smrg spans->widths = malloc(nspans * sizeof (*spans->widths)); 626747b715Smrg if (!spans->widths) 636747b715Smrg { 646747b715Smrg free(spans->points); 656747b715Smrg return FALSE; 666747b715Smrg } 676747b715Smrg return TRUE; 686747b715Smrg} 696747b715Smrg 706747b715Smrg/* 716747b715Smrg * interface data to span-merging polygon filler 726747b715Smrg */ 736747b715Smrg 746747b715Smrgtypedef struct _SpanData { 756747b715Smrg SpanGroup fgGroup, bgGroup; 766747b715Smrg} SpanDataRec, *SpanDataPtr; 776747b715Smrg 786747b715Smrgstatic void 796747b715SmrgAppendSpanGroup(GCPtr pGC, unsigned long pixel, Spans *spanPtr, SpanDataPtr spanData) 806747b715Smrg{ 816747b715Smrg SpanGroup *group, *othergroup = NULL; 826747b715Smrg if (pixel == pGC->fgPixel) 836747b715Smrg { 846747b715Smrg group = &spanData->fgGroup; 856747b715Smrg if (pGC->lineStyle == LineDoubleDash) 866747b715Smrg othergroup = &spanData->bgGroup; 876747b715Smrg } 886747b715Smrg else 896747b715Smrg { 906747b715Smrg group = &spanData->bgGroup; 916747b715Smrg othergroup = &spanData->fgGroup; 926747b715Smrg } 936747b715Smrg miAppendSpans (group, othergroup, spanPtr); 946747b715Smrg} 956747b715Smrg 966747b715Smrg 9705b261ecSmrgstatic void miLineArc(DrawablePtr pDraw, GCPtr pGC, 9805b261ecSmrg unsigned long pixel, SpanDataPtr spanData, 9905b261ecSmrg LineFacePtr leftFace, 10005b261ecSmrg LineFacePtr rightFace, 10105b261ecSmrg double xorg, double yorg, Bool isInt); 10205b261ecSmrg 10305b261ecSmrg 10405b261ecSmrg/* 10505b261ecSmrg * spans-based polygon filler 10605b261ecSmrg */ 10705b261ecSmrg 1086747b715Smrgstatic void 1096747b715SmrgfillSpans(DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel, Spans *spans, SpanDataPtr spanData) 1106747b715Smrg{ 1116747b715Smrg if (!spanData) 1126747b715Smrg { 1136747b715Smrg ChangeGCVal oldPixel, tmpPixel; 1146747b715Smrg oldPixel.val = pGC->fgPixel; 1156747b715Smrg if (pixel != oldPixel.val) 1166747b715Smrg { 1176747b715Smrg tmpPixel.val = (XID)pixel; 1186747b715Smrg ChangeGC (NullClient, pGC, GCForeground, &tmpPixel); 1196747b715Smrg ValidateGC (pDrawable, pGC); 1206747b715Smrg } 1216747b715Smrg (*pGC->ops->FillSpans) (pDrawable, pGC, spans->count, spans->points, spans->widths, TRUE); 1226747b715Smrg free(spans->widths); 1236747b715Smrg free(spans->points); 1246747b715Smrg if (pixel != oldPixel.val) 1256747b715Smrg { 1266747b715Smrg ChangeGC (NullClient, pGC, GCForeground, &oldPixel); 1276747b715Smrg ValidateGC (pDrawable, pGC); 1286747b715Smrg } 1296747b715Smrg } 1306747b715Smrg else 1316747b715Smrg AppendSpanGroup (pGC, pixel, spans, spanData); 1326747b715Smrg} 1336747b715Smrg 13405b261ecSmrgstatic void 13505b261ecSmrgmiFillPolyHelper (DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel, 13605b261ecSmrg SpanDataPtr spanData, int y, int overall_height, 13705b261ecSmrg PolyEdgePtr left, PolyEdgePtr right, 13805b261ecSmrg int left_count, int right_count) 13905b261ecSmrg{ 14005b261ecSmrg int left_x = 0, left_e = 0; 14105b261ecSmrg int left_stepx = 0; 14205b261ecSmrg int left_signdx = 0; 14305b261ecSmrg int left_dy = 0, left_dx = 0; 14405b261ecSmrg 14505b261ecSmrg int right_x = 0, right_e = 0; 14605b261ecSmrg int right_stepx = 0; 14705b261ecSmrg int right_signdx = 0; 14805b261ecSmrg int right_dy = 0, right_dx = 0; 14905b261ecSmrg 15005b261ecSmrg int height = 0; 15105b261ecSmrg int left_height = 0, right_height = 0; 15205b261ecSmrg 15305b261ecSmrg DDXPointPtr ppt; 15405b261ecSmrg int *pwidth; 15505b261ecSmrg int xorg; 15605b261ecSmrg Spans spanRec; 15705b261ecSmrg 1586747b715Smrg if (!InitSpans(&spanRec, overall_height)) 1596747b715Smrg return; 1606747b715Smrg ppt = spanRec.points; 1616747b715Smrg pwidth = spanRec.widths; 16205b261ecSmrg 16305b261ecSmrg xorg = 0; 16405b261ecSmrg if (pGC->miTranslate) 16505b261ecSmrg { 16605b261ecSmrg y += pDrawable->y; 16705b261ecSmrg xorg = pDrawable->x; 16805b261ecSmrg } 16905b261ecSmrg while ((left_count || left_height) && 17005b261ecSmrg (right_count || right_height)) 17105b261ecSmrg { 1726747b715Smrg if (!left_height && left_count) 1736747b715Smrg { 1746747b715Smrg left_height = left->height; 1756747b715Smrg left_x = left->x; 1766747b715Smrg left_stepx = left->stepx; 1776747b715Smrg left_signdx = left->signdx; 1786747b715Smrg left_e = left->e; 1796747b715Smrg left_dy = left->dy; 1806747b715Smrg left_dx = left->dx; 1816747b715Smrg --left_count; 1826747b715Smrg ++left; 1836747b715Smrg } 1846747b715Smrg 1856747b715Smrg if (!right_height && right_count) 1866747b715Smrg { 1876747b715Smrg right_height = right->height; 1886747b715Smrg right_x = right->x; 1896747b715Smrg right_stepx = right->stepx; 1906747b715Smrg right_signdx = right->signdx; 1916747b715Smrg right_e = right->e; 1926747b715Smrg right_dy = right->dy; 1936747b715Smrg right_dx = right->dx; 1946747b715Smrg --right_count; 1956747b715Smrg ++right; 1966747b715Smrg } 19705b261ecSmrg 19805b261ecSmrg height = left_height; 19905b261ecSmrg if (height > right_height) 20005b261ecSmrg height = right_height; 20105b261ecSmrg 20205b261ecSmrg left_height -= height; 20305b261ecSmrg right_height -= height; 20405b261ecSmrg 20505b261ecSmrg while (--height >= 0) 20605b261ecSmrg { 20705b261ecSmrg if (right_x >= left_x) 20805b261ecSmrg { 20905b261ecSmrg ppt->y = y; 21005b261ecSmrg ppt->x = left_x + xorg; 21105b261ecSmrg ppt++; 21205b261ecSmrg *pwidth++ = right_x - left_x + 1; 21305b261ecSmrg } 2146747b715Smrg y++; 21505b261ecSmrg 2166747b715Smrg left_x += left_stepx; 2176747b715Smrg left_e += left_dx; 2186747b715Smrg if (left_e > 0) 2196747b715Smrg { 2206747b715Smrg left_x += left_signdx; 2216747b715Smrg left_e -= left_dy; 2226747b715Smrg } 2236747b715Smrg 2246747b715Smrg right_x += right_stepx; 2256747b715Smrg right_e += right_dx; 2266747b715Smrg if (right_e > 0) 2276747b715Smrg { 2286747b715Smrg right_x += right_signdx; 2296747b715Smrg right_e -= right_dy; 2306747b715Smrg } 23105b261ecSmrg } 23205b261ecSmrg } 2336747b715Smrg spanRec.count = ppt - spanRec.points; 2346747b715Smrg fillSpans (pDrawable, pGC, pixel, &spanRec, spanData); 23505b261ecSmrg} 23605b261ecSmrg 23705b261ecSmrgstatic void 23805b261ecSmrgmiFillRectPolyHelper ( 23905b261ecSmrg DrawablePtr pDrawable, 24005b261ecSmrg GCPtr pGC, 24105b261ecSmrg unsigned long pixel, 24205b261ecSmrg SpanDataPtr spanData, 24305b261ecSmrg int x, 24405b261ecSmrg int y, 24505b261ecSmrg int w, 24605b261ecSmrg int h) 24705b261ecSmrg{ 24805b261ecSmrg DDXPointPtr ppt; 24905b261ecSmrg int *pwidth; 2506747b715Smrg ChangeGCVal oldPixel, tmpPixel; 25105b261ecSmrg Spans spanRec; 25205b261ecSmrg xRectangle rect; 25305b261ecSmrg 25405b261ecSmrg if (!spanData) 25505b261ecSmrg { 25605b261ecSmrg rect.x = x; 25705b261ecSmrg rect.y = y; 25805b261ecSmrg rect.width = w; 25905b261ecSmrg rect.height = h; 2606747b715Smrg oldPixel.val = pGC->fgPixel; 2616747b715Smrg if (pixel != oldPixel.val) 26205b261ecSmrg { 2636747b715Smrg tmpPixel.val = (XID)pixel; 2646747b715Smrg ChangeGC (NullClient, pGC, GCForeground, &tmpPixel); 26505b261ecSmrg ValidateGC (pDrawable, pGC); 26605b261ecSmrg } 26705b261ecSmrg (*pGC->ops->PolyFillRect) (pDrawable, pGC, 1, &rect); 2686747b715Smrg if (pixel != oldPixel.val) 26905b261ecSmrg { 2706747b715Smrg ChangeGC (NullClient, pGC, GCForeground, &oldPixel); 27105b261ecSmrg ValidateGC (pDrawable, pGC); 27205b261ecSmrg } 27305b261ecSmrg } 27405b261ecSmrg else 27505b261ecSmrg { 2766747b715Smrg if (!InitSpans(&spanRec, h)) 27705b261ecSmrg return; 27805b261ecSmrg ppt = spanRec.points; 27905b261ecSmrg pwidth = spanRec.widths; 28005b261ecSmrg 28105b261ecSmrg if (pGC->miTranslate) 28205b261ecSmrg { 28305b261ecSmrg y += pDrawable->y; 28405b261ecSmrg x += pDrawable->x; 28505b261ecSmrg } 28605b261ecSmrg while (h--) 28705b261ecSmrg { 28805b261ecSmrg ppt->x = x; 28905b261ecSmrg ppt->y = y; 29005b261ecSmrg ppt++; 29105b261ecSmrg *pwidth++ = w; 29205b261ecSmrg y++; 29305b261ecSmrg } 29405b261ecSmrg spanRec.count = ppt - spanRec.points; 2956747b715Smrg AppendSpanGroup (pGC, pixel, &spanRec, spanData); 29605b261ecSmrg } 29705b261ecSmrg} 29805b261ecSmrg 2996747b715Smrg/* static */ int 3004642e01fSmrgmiPolyBuildEdge ( 3014642e01fSmrg double x0, 3024642e01fSmrg double y0, 3034642e01fSmrg double k, /* x0 * dy - y0 * dx */ 3044642e01fSmrg int dx, 3054642e01fSmrg int dy, 3064642e01fSmrg int xi, 3074642e01fSmrg int yi, 3084642e01fSmrg int left, 3094642e01fSmrg PolyEdgePtr edge) 31005b261ecSmrg{ 31105b261ecSmrg int x, y, e; 31205b261ecSmrg int xady; 31305b261ecSmrg 31405b261ecSmrg if (dy < 0) 31505b261ecSmrg { 31605b261ecSmrg dy = -dy; 31705b261ecSmrg dx = -dx; 31805b261ecSmrg k = -k; 31905b261ecSmrg } 32005b261ecSmrg 32105b261ecSmrg#ifdef NOTDEF 32205b261ecSmrg { 32305b261ecSmrg double realk, kerror; 32405b261ecSmrg realk = x0 * dy - y0 * dx; 32505b261ecSmrg kerror = Fabs (realk - k); 32605b261ecSmrg if (kerror > .1) 32705b261ecSmrg printf ("realk: %g k: %g\n", realk, k); 32805b261ecSmrg } 32905b261ecSmrg#endif 33005b261ecSmrg y = ICEIL (y0); 33105b261ecSmrg xady = ICEIL (k) + y * dx; 33205b261ecSmrg 33305b261ecSmrg if (xady <= 0) 33405b261ecSmrg x = - (-xady / dy) - 1; 33505b261ecSmrg else 33605b261ecSmrg x = (xady - 1) / dy; 33705b261ecSmrg 33805b261ecSmrg e = xady - x * dy; 33905b261ecSmrg 34005b261ecSmrg if (dx >= 0) 34105b261ecSmrg { 34205b261ecSmrg edge->signdx = 1; 34305b261ecSmrg edge->stepx = dx / dy; 34405b261ecSmrg edge->dx = dx % dy; 34505b261ecSmrg } 34605b261ecSmrg else 34705b261ecSmrg { 34805b261ecSmrg edge->signdx = -1; 34905b261ecSmrg edge->stepx = - (-dx / dy); 35005b261ecSmrg edge->dx = -dx % dy; 35105b261ecSmrg e = dy - e + 1; 35205b261ecSmrg } 35305b261ecSmrg edge->dy = dy; 35405b261ecSmrg edge->x = x + left + xi; 35505b261ecSmrg edge->e = e - dy; /* bias to compare against 0 instead of dy */ 35605b261ecSmrg return y + yi; 35705b261ecSmrg} 35805b261ecSmrg 35905b261ecSmrg#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr))) 36005b261ecSmrg 3616747b715Smrg/* static */ int 3624642e01fSmrgmiPolyBuildPoly ( 3634642e01fSmrg PolyVertexPtr vertices, 3644642e01fSmrg PolySlopePtr slopes, 3654642e01fSmrg int count, 3664642e01fSmrg int xi, 3674642e01fSmrg int yi, 3684642e01fSmrg PolyEdgePtr left, 3694642e01fSmrg PolyEdgePtr right, 3704642e01fSmrg int *pnleft, 3714642e01fSmrg int *pnright, 3724642e01fSmrg int *h) 37305b261ecSmrg{ 37405b261ecSmrg int top, bottom; 37505b261ecSmrg double miny, maxy; 37605b261ecSmrg int i; 37705b261ecSmrg int j; 37805b261ecSmrg int clockwise; 37905b261ecSmrg int slopeoff; 38005b261ecSmrg int s; 38105b261ecSmrg int nright, nleft; 38205b261ecSmrg int y, lasty = 0, bottomy, topy = 0; 38305b261ecSmrg 38405b261ecSmrg /* find the top of the polygon */ 38505b261ecSmrg maxy = miny = vertices[0].y; 38605b261ecSmrg bottom = top = 0; 38705b261ecSmrg for (i = 1; i < count; i++) 38805b261ecSmrg { 38905b261ecSmrg if (vertices[i].y < miny) 39005b261ecSmrg { 39105b261ecSmrg top = i; 39205b261ecSmrg miny = vertices[i].y; 39305b261ecSmrg } 39405b261ecSmrg if (vertices[i].y >= maxy) 39505b261ecSmrg { 39605b261ecSmrg bottom = i; 39705b261ecSmrg maxy = vertices[i].y; 39805b261ecSmrg } 39905b261ecSmrg } 40005b261ecSmrg clockwise = 1; 40105b261ecSmrg slopeoff = 0; 40205b261ecSmrg 40305b261ecSmrg i = top; 40405b261ecSmrg j = StepAround (top, -1, count); 40505b261ecSmrg 40605b261ecSmrg if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx) 40705b261ecSmrg { 40805b261ecSmrg clockwise = -1; 40905b261ecSmrg slopeoff = -1; 41005b261ecSmrg } 41105b261ecSmrg 41205b261ecSmrg bottomy = ICEIL (maxy) + yi; 41305b261ecSmrg 41405b261ecSmrg nright = 0; 41505b261ecSmrg 41605b261ecSmrg s = StepAround (top, slopeoff, count); 41705b261ecSmrg i = top; 41805b261ecSmrg while (i != bottom) 41905b261ecSmrg { 42005b261ecSmrg if (slopes[s].dy != 0) 42105b261ecSmrg { 42205b261ecSmrg y = miPolyBuildEdge (vertices[i].x, vertices[i].y, 42305b261ecSmrg slopes[s].k, 42405b261ecSmrg slopes[s].dx, slopes[s].dy, 42505b261ecSmrg xi, yi, 0, 42605b261ecSmrg &right[nright]); 42705b261ecSmrg if (nright != 0) 42805b261ecSmrg right[nright-1].height = y - lasty; 42905b261ecSmrg else 43005b261ecSmrg topy = y; 43105b261ecSmrg nright++; 43205b261ecSmrg lasty = y; 43305b261ecSmrg } 43405b261ecSmrg 43505b261ecSmrg i = StepAround (i, clockwise, count); 43605b261ecSmrg s = StepAround (s, clockwise, count); 43705b261ecSmrg } 43805b261ecSmrg if (nright != 0) 43905b261ecSmrg right[nright-1].height = bottomy - lasty; 44005b261ecSmrg 44105b261ecSmrg if (slopeoff == 0) 44205b261ecSmrg slopeoff = -1; 44305b261ecSmrg else 44405b261ecSmrg slopeoff = 0; 44505b261ecSmrg 44605b261ecSmrg nleft = 0; 44705b261ecSmrg s = StepAround (top, slopeoff, count); 44805b261ecSmrg i = top; 44905b261ecSmrg while (i != bottom) 45005b261ecSmrg { 45105b261ecSmrg if (slopes[s].dy != 0) 45205b261ecSmrg { 45305b261ecSmrg y = miPolyBuildEdge (vertices[i].x, vertices[i].y, 45405b261ecSmrg slopes[s].k, 45505b261ecSmrg slopes[s].dx, slopes[s].dy, xi, yi, 1, 45605b261ecSmrg &left[nleft]); 45705b261ecSmrg 45805b261ecSmrg if (nleft != 0) 45905b261ecSmrg left[nleft-1].height = y - lasty; 46005b261ecSmrg nleft++; 46105b261ecSmrg lasty = y; 46205b261ecSmrg } 46305b261ecSmrg i = StepAround (i, -clockwise, count); 46405b261ecSmrg s = StepAround (s, -clockwise, count); 46505b261ecSmrg } 46605b261ecSmrg if (nleft != 0) 46705b261ecSmrg left[nleft-1].height = bottomy - lasty; 46805b261ecSmrg *pnleft = nleft; 46905b261ecSmrg *pnright = nright; 47005b261ecSmrg *h = bottomy - topy; 47105b261ecSmrg return topy; 47205b261ecSmrg} 47305b261ecSmrg 47405b261ecSmrgstatic void 47505b261ecSmrgmiLineOnePoint ( 47605b261ecSmrg DrawablePtr pDrawable, 47705b261ecSmrg GCPtr pGC, 47805b261ecSmrg unsigned long pixel, 47905b261ecSmrg SpanDataPtr spanData, 48005b261ecSmrg int x, 48105b261ecSmrg int y) 48205b261ecSmrg{ 48305b261ecSmrg DDXPointRec pt; 48405b261ecSmrg int wid; 48505b261ecSmrg unsigned long oldPixel; 48605b261ecSmrg 48705b261ecSmrg MILINESETPIXEL (pDrawable, pGC, pixel, oldPixel); 48805b261ecSmrg if (pGC->fillStyle == FillSolid) 48905b261ecSmrg { 49005b261ecSmrg pt.x = x; 49105b261ecSmrg pt.y = y; 49205b261ecSmrg (*pGC->ops->PolyPoint) (pDrawable, pGC, CoordModeOrigin, 1, &pt); 49305b261ecSmrg } 49405b261ecSmrg else 49505b261ecSmrg { 49605b261ecSmrg wid = 1; 49705b261ecSmrg if (pGC->miTranslate) 49805b261ecSmrg { 49905b261ecSmrg x += pDrawable->x; 50005b261ecSmrg y += pDrawable->y; 50105b261ecSmrg } 50205b261ecSmrg pt.x = x; 50305b261ecSmrg pt.y = y; 50405b261ecSmrg (*pGC->ops->FillSpans) (pDrawable, pGC, 1, &pt, &wid, TRUE); 50505b261ecSmrg } 50605b261ecSmrg MILINERESETPIXEL (pDrawable, pGC, pixel, oldPixel); 50705b261ecSmrg} 50805b261ecSmrg 50905b261ecSmrgstatic void 51005b261ecSmrgmiLineJoin ( 51105b261ecSmrg DrawablePtr pDrawable, 51205b261ecSmrg GCPtr pGC, 51305b261ecSmrg unsigned long pixel, 51405b261ecSmrg SpanDataPtr spanData, 51505b261ecSmrg LineFacePtr pLeft, 51605b261ecSmrg LineFacePtr pRight) 51705b261ecSmrg{ 51805b261ecSmrg double mx = 0, my = 0; 51905b261ecSmrg double denom = 0.0; 52005b261ecSmrg PolyVertexRec vertices[4]; 52105b261ecSmrg PolySlopeRec slopes[4]; 52205b261ecSmrg int edgecount; 52305b261ecSmrg PolyEdgeRec left[4], right[4]; 52405b261ecSmrg int nleft, nright; 52505b261ecSmrg int y, height; 52605b261ecSmrg int swapslopes; 52705b261ecSmrg int joinStyle = pGC->joinStyle; 52805b261ecSmrg int lw = pGC->lineWidth; 52905b261ecSmrg 53005b261ecSmrg if (lw == 1 && !spanData) { 53105b261ecSmrg /* See if one of the lines will draw the joining pixel */ 53205b261ecSmrg if (pLeft->dx > 0 || (pLeft->dx == 0 && pLeft->dy > 0)) 53305b261ecSmrg return; 53405b261ecSmrg if (pRight->dx > 0 || (pRight->dx == 0 && pRight->dy > 0)) 53505b261ecSmrg return; 53605b261ecSmrg if (joinStyle != JoinRound) { 53705b261ecSmrg denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; 53805b261ecSmrg if (denom == 0) 53905b261ecSmrg return; /* no join to draw */ 54005b261ecSmrg } 54105b261ecSmrg if (joinStyle != JoinMiter) { 54205b261ecSmrg miLineOnePoint (pDrawable, pGC, pixel, spanData, pLeft->x, pLeft->y); 54305b261ecSmrg return; 54405b261ecSmrg } 54505b261ecSmrg } else { 54605b261ecSmrg if (joinStyle == JoinRound) 54705b261ecSmrg { 54805b261ecSmrg miLineArc(pDrawable, pGC, pixel, spanData, 54905b261ecSmrg pLeft, pRight, 55005b261ecSmrg (double)0.0, (double)0.0, TRUE); 55105b261ecSmrg return; 55205b261ecSmrg } 55305b261ecSmrg denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; 55405b261ecSmrg if (denom == 0.0) 55505b261ecSmrg return; /* no join to draw */ 55605b261ecSmrg } 55705b261ecSmrg 55805b261ecSmrg swapslopes = 0; 55905b261ecSmrg if (denom > 0) 56005b261ecSmrg { 56105b261ecSmrg pLeft->xa = -pLeft->xa; 56205b261ecSmrg pLeft->ya = -pLeft->ya; 56305b261ecSmrg pLeft->dx = -pLeft->dx; 56405b261ecSmrg pLeft->dy = -pLeft->dy; 56505b261ecSmrg } 56605b261ecSmrg else 56705b261ecSmrg { 56805b261ecSmrg swapslopes = 1; 56905b261ecSmrg pRight->xa = -pRight->xa; 57005b261ecSmrg pRight->ya = -pRight->ya; 57105b261ecSmrg pRight->dx = -pRight->dx; 57205b261ecSmrg pRight->dy = -pRight->dy; 57305b261ecSmrg } 57405b261ecSmrg 57505b261ecSmrg vertices[0].x = pRight->xa; 57605b261ecSmrg vertices[0].y = pRight->ya; 57705b261ecSmrg slopes[0].dx = -pRight->dy; 57805b261ecSmrg slopes[0].dy = pRight->dx; 57905b261ecSmrg slopes[0].k = 0; 58005b261ecSmrg 58105b261ecSmrg vertices[1].x = 0; 58205b261ecSmrg vertices[1].y = 0; 58305b261ecSmrg slopes[1].dx = pLeft->dy; 58405b261ecSmrg slopes[1].dy = -pLeft->dx; 58505b261ecSmrg slopes[1].k = 0; 58605b261ecSmrg 58705b261ecSmrg vertices[2].x = pLeft->xa; 58805b261ecSmrg vertices[2].y = pLeft->ya; 58905b261ecSmrg 59005b261ecSmrg if (joinStyle == JoinMiter) 59105b261ecSmrg { 59205b261ecSmrg my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) - 59305b261ecSmrg pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx )) / 59405b261ecSmrg denom; 59505b261ecSmrg if (pLeft->dy != 0) 59605b261ecSmrg { 59705b261ecSmrg mx = pLeft->xa + (my - pLeft->ya) * 59805b261ecSmrg (double) pLeft->dx / (double) pLeft->dy; 59905b261ecSmrg } 60005b261ecSmrg else 60105b261ecSmrg { 60205b261ecSmrg mx = pRight->xa + (my - pRight->ya) * 60305b261ecSmrg (double) pRight->dx / (double) pRight->dy; 60405b261ecSmrg } 60505b261ecSmrg /* check miter limit */ 60605b261ecSmrg if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw) 60705b261ecSmrg joinStyle = JoinBevel; 60805b261ecSmrg } 60905b261ecSmrg 61005b261ecSmrg if (joinStyle == JoinMiter) 61105b261ecSmrg { 61205b261ecSmrg slopes[2].dx = pLeft->dx; 61305b261ecSmrg slopes[2].dy = pLeft->dy; 61405b261ecSmrg slopes[2].k = pLeft->k; 61505b261ecSmrg if (swapslopes) 61605b261ecSmrg { 61705b261ecSmrg slopes[2].dx = -slopes[2].dx; 61805b261ecSmrg slopes[2].dy = -slopes[2].dy; 61905b261ecSmrg slopes[2].k = -slopes[2].k; 62005b261ecSmrg } 62105b261ecSmrg vertices[3].x = mx; 62205b261ecSmrg vertices[3].y = my; 62305b261ecSmrg slopes[3].dx = pRight->dx; 62405b261ecSmrg slopes[3].dy = pRight->dy; 62505b261ecSmrg slopes[3].k = pRight->k; 62605b261ecSmrg if (swapslopes) 62705b261ecSmrg { 62805b261ecSmrg slopes[3].dx = -slopes[3].dx; 62905b261ecSmrg slopes[3].dy = -slopes[3].dy; 63005b261ecSmrg slopes[3].k = -slopes[3].k; 63105b261ecSmrg } 63205b261ecSmrg edgecount = 4; 63305b261ecSmrg } 63405b261ecSmrg else 63505b261ecSmrg { 63605b261ecSmrg double scale, dx, dy, adx, ady; 63705b261ecSmrg 63805b261ecSmrg adx = dx = pRight->xa - pLeft->xa; 63905b261ecSmrg ady = dy = pRight->ya - pLeft->ya; 64005b261ecSmrg if (adx < 0) 64105b261ecSmrg adx = -adx; 64205b261ecSmrg if (ady < 0) 64305b261ecSmrg ady = -ady; 64405b261ecSmrg scale = ady; 64505b261ecSmrg if (adx > ady) 64605b261ecSmrg scale = adx; 64705b261ecSmrg slopes[2].dx = (dx * 65536) / scale; 64805b261ecSmrg slopes[2].dy = (dy * 65536) / scale; 64905b261ecSmrg slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy - 65005b261ecSmrg (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0; 65105b261ecSmrg edgecount = 3; 65205b261ecSmrg } 65305b261ecSmrg 65405b261ecSmrg y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y, 65505b261ecSmrg left, right, &nleft, &nright, &height); 65605b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, height, left, right, nleft, nright); 65705b261ecSmrg} 65805b261ecSmrg 65905b261ecSmrgstatic int 66005b261ecSmrgmiLineArcI ( 66105b261ecSmrg DrawablePtr pDraw, 66205b261ecSmrg GCPtr pGC, 66305b261ecSmrg int xorg, 66405b261ecSmrg int yorg, 66505b261ecSmrg DDXPointPtr points, 66605b261ecSmrg int *widths) 66705b261ecSmrg{ 66805b261ecSmrg DDXPointPtr tpts, bpts; 66905b261ecSmrg int *twids, *bwids; 67005b261ecSmrg int x, y, e, ex, slw; 67105b261ecSmrg 67205b261ecSmrg tpts = points; 67305b261ecSmrg twids = widths; 67405b261ecSmrg if (pGC->miTranslate) 67505b261ecSmrg { 67605b261ecSmrg xorg += pDraw->x; 67705b261ecSmrg yorg += pDraw->y; 67805b261ecSmrg } 67905b261ecSmrg slw = pGC->lineWidth; 68005b261ecSmrg if (slw == 1) 68105b261ecSmrg { 68205b261ecSmrg tpts->x = xorg; 68305b261ecSmrg tpts->y = yorg; 68405b261ecSmrg *twids = 1; 68505b261ecSmrg return 1; 68605b261ecSmrg } 68705b261ecSmrg bpts = tpts + slw; 68805b261ecSmrg bwids = twids + slw; 68905b261ecSmrg y = (slw >> 1) + 1; 69005b261ecSmrg if (slw & 1) 69105b261ecSmrg e = - ((y << 2) + 3); 69205b261ecSmrg else 69305b261ecSmrg e = - (y << 3); 69405b261ecSmrg ex = -4; 69505b261ecSmrg x = 0; 69605b261ecSmrg while (y) 69705b261ecSmrg { 69805b261ecSmrg e += (y << 3) - 4; 69905b261ecSmrg while (e >= 0) 70005b261ecSmrg { 70105b261ecSmrg x++; 70205b261ecSmrg e += (ex = -((x << 3) + 4)); 70305b261ecSmrg } 70405b261ecSmrg y--; 70505b261ecSmrg slw = (x << 1) + 1; 70605b261ecSmrg if ((e == ex) && (slw > 1)) 70705b261ecSmrg slw--; 70805b261ecSmrg tpts->x = xorg - x; 70905b261ecSmrg tpts->y = yorg - y; 71005b261ecSmrg tpts++; 71105b261ecSmrg *twids++ = slw; 71205b261ecSmrg if ((y != 0) && ((slw > 1) || (e != ex))) 71305b261ecSmrg { 71405b261ecSmrg bpts--; 71505b261ecSmrg bpts->x = xorg - x; 71605b261ecSmrg bpts->y = yorg + y; 71705b261ecSmrg *--bwids = slw; 71805b261ecSmrg } 71905b261ecSmrg } 7206747b715Smrg return pGC->lineWidth; 72105b261ecSmrg} 72205b261ecSmrg 72305b261ecSmrg#define CLIPSTEPEDGE(edgey,edge,edgeleft) \ 72405b261ecSmrg if (ybase == edgey) \ 72505b261ecSmrg { \ 72605b261ecSmrg if (edgeleft) \ 72705b261ecSmrg { \ 72805b261ecSmrg if (edge->x > xcl) \ 72905b261ecSmrg xcl = edge->x; \ 73005b261ecSmrg } \ 73105b261ecSmrg else \ 73205b261ecSmrg { \ 73305b261ecSmrg if (edge->x < xcr) \ 73405b261ecSmrg xcr = edge->x; \ 73505b261ecSmrg } \ 73605b261ecSmrg edgey++; \ 73705b261ecSmrg edge->x += edge->stepx; \ 73805b261ecSmrg edge->e += edge->dx; \ 73905b261ecSmrg if (edge->e > 0) \ 74005b261ecSmrg { \ 74105b261ecSmrg edge->x += edge->signdx; \ 74205b261ecSmrg edge->e -= edge->dy; \ 74305b261ecSmrg } \ 74405b261ecSmrg } 74505b261ecSmrg 74605b261ecSmrgstatic int 74705b261ecSmrgmiLineArcD ( 74805b261ecSmrg DrawablePtr pDraw, 74905b261ecSmrg GCPtr pGC, 75005b261ecSmrg double xorg, 75105b261ecSmrg double yorg, 75205b261ecSmrg DDXPointPtr points, 75305b261ecSmrg int *widths, 75405b261ecSmrg PolyEdgePtr edge1, 75505b261ecSmrg int edgey1, 75605b261ecSmrg Bool edgeleft1, 75705b261ecSmrg PolyEdgePtr edge2, 75805b261ecSmrg int edgey2, 75905b261ecSmrg Bool edgeleft2) 76005b261ecSmrg{ 76105b261ecSmrg DDXPointPtr pts; 76205b261ecSmrg int *wids; 76305b261ecSmrg double radius, x0, y0, el, er, yk, xlk, xrk, k; 76405b261ecSmrg int xbase, ybase, y, boty, xl, xr, xcl, xcr; 76505b261ecSmrg int ymin, ymax; 76605b261ecSmrg Bool edge1IsMin, edge2IsMin; 76705b261ecSmrg int ymin1, ymin2; 76805b261ecSmrg 76905b261ecSmrg pts = points; 77005b261ecSmrg wids = widths; 77105b261ecSmrg xbase = floor(xorg); 77205b261ecSmrg x0 = xorg - xbase; 77305b261ecSmrg ybase = ICEIL (yorg); 77405b261ecSmrg y0 = yorg - ybase; 77505b261ecSmrg if (pGC->miTranslate) 77605b261ecSmrg { 77705b261ecSmrg xbase += pDraw->x; 77805b261ecSmrg ybase += pDraw->y; 77905b261ecSmrg edge1->x += pDraw->x; 78005b261ecSmrg edge2->x += pDraw->x; 78105b261ecSmrg edgey1 += pDraw->y; 78205b261ecSmrg edgey2 += pDraw->y; 78305b261ecSmrg } 78405b261ecSmrg xlk = x0 + x0 + 1.0; 78505b261ecSmrg xrk = x0 + x0 - 1.0; 78605b261ecSmrg yk = y0 + y0 - 1.0; 78705b261ecSmrg radius = ((double)pGC->lineWidth) / 2.0; 78805b261ecSmrg y = floor(radius - y0 + 1.0); 78905b261ecSmrg ybase -= y; 79005b261ecSmrg ymin = ybase; 79105b261ecSmrg ymax = 65536; 79205b261ecSmrg edge1IsMin = FALSE; 79305b261ecSmrg ymin1 = edgey1; 79405b261ecSmrg if (edge1->dy >= 0) 79505b261ecSmrg { 79605b261ecSmrg if (!edge1->dy) 79705b261ecSmrg { 79805b261ecSmrg if (edgeleft1) 79905b261ecSmrg edge1IsMin = TRUE; 80005b261ecSmrg else 80105b261ecSmrg ymax = edgey1; 80205b261ecSmrg edgey1 = 65536; 80305b261ecSmrg } 80405b261ecSmrg else 80505b261ecSmrg { 80605b261ecSmrg if ((edge1->signdx < 0) == edgeleft1) 80705b261ecSmrg edge1IsMin = TRUE; 80805b261ecSmrg } 80905b261ecSmrg } 81005b261ecSmrg edge2IsMin = FALSE; 81105b261ecSmrg ymin2 = edgey2; 81205b261ecSmrg if (edge2->dy >= 0) 81305b261ecSmrg { 81405b261ecSmrg if (!edge2->dy) 81505b261ecSmrg { 81605b261ecSmrg if (edgeleft2) 81705b261ecSmrg edge2IsMin = TRUE; 81805b261ecSmrg else 81905b261ecSmrg ymax = edgey2; 82005b261ecSmrg edgey2 = 65536; 82105b261ecSmrg } 82205b261ecSmrg else 82305b261ecSmrg { 82405b261ecSmrg if ((edge2->signdx < 0) == edgeleft2) 82505b261ecSmrg edge2IsMin = TRUE; 82605b261ecSmrg } 82705b261ecSmrg } 82805b261ecSmrg if (edge1IsMin) 82905b261ecSmrg { 83005b261ecSmrg ymin = ymin1; 83105b261ecSmrg if (edge2IsMin && ymin1 > ymin2) 83205b261ecSmrg ymin = ymin2; 83305b261ecSmrg } else if (edge2IsMin) 83405b261ecSmrg ymin = ymin2; 83505b261ecSmrg el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0); 83605b261ecSmrg er = el + xrk; 83705b261ecSmrg xl = 1; 83805b261ecSmrg xr = 0; 83905b261ecSmrg if (x0 < 0.5) 84005b261ecSmrg { 84105b261ecSmrg xl = 0; 84205b261ecSmrg el -= xlk; 84305b261ecSmrg } 84405b261ecSmrg boty = (y0 < -0.5) ? 1 : 0; 84505b261ecSmrg if (ybase + y - boty > ymax) 84605b261ecSmrg boty = ymax - ybase - y; 84705b261ecSmrg while (y > boty) 84805b261ecSmrg { 84905b261ecSmrg k = (y << 1) + yk; 85005b261ecSmrg er += k; 85105b261ecSmrg while (er > 0.0) 85205b261ecSmrg { 85305b261ecSmrg xr++; 85405b261ecSmrg er += xrk - (xr << 1); 85505b261ecSmrg } 85605b261ecSmrg el += k; 85705b261ecSmrg while (el >= 0.0) 85805b261ecSmrg { 85905b261ecSmrg xl--; 86005b261ecSmrg el += (xl << 1) - xlk; 86105b261ecSmrg } 86205b261ecSmrg y--; 86305b261ecSmrg ybase++; 86405b261ecSmrg if (ybase < ymin) 86505b261ecSmrg continue; 86605b261ecSmrg xcl = xl + xbase; 86705b261ecSmrg xcr = xr + xbase; 86805b261ecSmrg CLIPSTEPEDGE(edgey1, edge1, edgeleft1); 86905b261ecSmrg CLIPSTEPEDGE(edgey2, edge2, edgeleft2); 87005b261ecSmrg if (xcr >= xcl) 87105b261ecSmrg { 87205b261ecSmrg pts->x = xcl; 87305b261ecSmrg pts->y = ybase; 87405b261ecSmrg pts++; 87505b261ecSmrg *wids++ = xcr - xcl + 1; 87605b261ecSmrg } 87705b261ecSmrg } 87805b261ecSmrg er = xrk - (xr << 1) - er; 87905b261ecSmrg el = (xl << 1) - xlk - el; 88005b261ecSmrg boty = floor(-y0 - radius + 1.0); 88105b261ecSmrg if (ybase + y - boty > ymax) 88205b261ecSmrg boty = ymax - ybase - y; 88305b261ecSmrg while (y > boty) 88405b261ecSmrg { 88505b261ecSmrg k = (y << 1) + yk; 88605b261ecSmrg er -= k; 88705b261ecSmrg while ((er >= 0.0) && (xr >= 0)) 88805b261ecSmrg { 88905b261ecSmrg xr--; 89005b261ecSmrg er += xrk - (xr << 1); 89105b261ecSmrg } 89205b261ecSmrg el -= k; 89305b261ecSmrg while ((el > 0.0) && (xl <= 0)) 89405b261ecSmrg { 89505b261ecSmrg xl++; 89605b261ecSmrg el += (xl << 1) - xlk; 89705b261ecSmrg } 89805b261ecSmrg y--; 89905b261ecSmrg ybase++; 90005b261ecSmrg if (ybase < ymin) 90105b261ecSmrg continue; 90205b261ecSmrg xcl = xl + xbase; 90305b261ecSmrg xcr = xr + xbase; 90405b261ecSmrg CLIPSTEPEDGE(edgey1, edge1, edgeleft1); 90505b261ecSmrg CLIPSTEPEDGE(edgey2, edge2, edgeleft2); 90605b261ecSmrg if (xcr >= xcl) 90705b261ecSmrg { 90805b261ecSmrg pts->x = xcl; 90905b261ecSmrg pts->y = ybase; 91005b261ecSmrg pts++; 91105b261ecSmrg *wids++ = xcr - xcl + 1; 91205b261ecSmrg } 91305b261ecSmrg } 9146747b715Smrg return pts - points; 91505b261ecSmrg} 91605b261ecSmrg 91705b261ecSmrgstatic int 91805b261ecSmrgmiRoundJoinFace (LineFacePtr face, PolyEdgePtr edge, Bool *leftEdge) 91905b261ecSmrg{ 92005b261ecSmrg int y; 92105b261ecSmrg int dx, dy; 92205b261ecSmrg double xa, ya; 92305b261ecSmrg Bool left; 92405b261ecSmrg 92505b261ecSmrg dx = -face->dy; 92605b261ecSmrg dy = face->dx; 92705b261ecSmrg xa = face->xa; 92805b261ecSmrg ya = face->ya; 92905b261ecSmrg left = 1; 93005b261ecSmrg if (ya > 0) 93105b261ecSmrg { 93205b261ecSmrg ya = 0.0; 93305b261ecSmrg xa = 0.0; 93405b261ecSmrg } 93505b261ecSmrg if (dy < 0 || (dy == 0 && dx > 0)) 93605b261ecSmrg { 93705b261ecSmrg dx = -dx; 93805b261ecSmrg dy = -dy; 93905b261ecSmrg left = !left; 94005b261ecSmrg } 94105b261ecSmrg if (dx == 0 && dy == 0) 94205b261ecSmrg dy = 1; 94305b261ecSmrg if (dy == 0) 94405b261ecSmrg { 94505b261ecSmrg y = ICEIL (face->ya) + face->y; 94605b261ecSmrg edge->x = -32767; 94705b261ecSmrg edge->stepx = 0; 94805b261ecSmrg edge->signdx = 0; 94905b261ecSmrg edge->e = -1; 95005b261ecSmrg edge->dy = 0; 95105b261ecSmrg edge->dx = 0; 95205b261ecSmrg edge->height = 0; 95305b261ecSmrg } 95405b261ecSmrg else 95505b261ecSmrg { 95605b261ecSmrg y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge); 95705b261ecSmrg edge->height = 32767; 95805b261ecSmrg } 95905b261ecSmrg *leftEdge = !left; 96005b261ecSmrg return y; 96105b261ecSmrg} 96205b261ecSmrg 9636747b715Smrgvoid 9644642e01fSmrgmiRoundJoinClip (LineFacePtr pLeft, LineFacePtr pRight, 9654642e01fSmrg PolyEdgePtr edge1, PolyEdgePtr edge2, 9664642e01fSmrg int *y1, int *y2, Bool *left1, Bool *left2) 96705b261ecSmrg{ 96805b261ecSmrg double denom; 96905b261ecSmrg 97005b261ecSmrg denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy; 97105b261ecSmrg 97205b261ecSmrg if (denom >= 0) 97305b261ecSmrg { 97405b261ecSmrg pLeft->xa = -pLeft->xa; 97505b261ecSmrg pLeft->ya = -pLeft->ya; 97605b261ecSmrg } 97705b261ecSmrg else 97805b261ecSmrg { 97905b261ecSmrg pRight->xa = -pRight->xa; 98005b261ecSmrg pRight->ya = -pRight->ya; 98105b261ecSmrg } 98205b261ecSmrg *y1 = miRoundJoinFace (pLeft, edge1, left1); 98305b261ecSmrg *y2 = miRoundJoinFace (pRight, edge2, left2); 98405b261ecSmrg} 98505b261ecSmrg 9866747b715Smrgint 9874642e01fSmrgmiRoundCapClip (LineFacePtr face, Bool isInt, PolyEdgePtr edge, Bool *leftEdge) 98805b261ecSmrg{ 98905b261ecSmrg int y; 99005b261ecSmrg int dx, dy; 99105b261ecSmrg double xa, ya, k; 99205b261ecSmrg Bool left; 99305b261ecSmrg 99405b261ecSmrg dx = -face->dy; 99505b261ecSmrg dy = face->dx; 99605b261ecSmrg xa = face->xa; 99705b261ecSmrg ya = face->ya; 99805b261ecSmrg k = 0.0; 99905b261ecSmrg if (!isInt) 100005b261ecSmrg k = face->k; 100105b261ecSmrg left = 1; 100205b261ecSmrg if (dy < 0 || (dy == 0 && dx > 0)) 100305b261ecSmrg { 100405b261ecSmrg dx = -dx; 100505b261ecSmrg dy = -dy; 100605b261ecSmrg xa = -xa; 100705b261ecSmrg ya = -ya; 100805b261ecSmrg left = !left; 100905b261ecSmrg } 101005b261ecSmrg if (dx == 0 && dy == 0) 101105b261ecSmrg dy = 1; 101205b261ecSmrg if (dy == 0) 101305b261ecSmrg { 101405b261ecSmrg y = ICEIL (face->ya) + face->y; 101505b261ecSmrg edge->x = -32767; 101605b261ecSmrg edge->stepx = 0; 101705b261ecSmrg edge->signdx = 0; 101805b261ecSmrg edge->e = -1; 101905b261ecSmrg edge->dy = 0; 102005b261ecSmrg edge->dx = 0; 102105b261ecSmrg edge->height = 0; 102205b261ecSmrg } 102305b261ecSmrg else 102405b261ecSmrg { 102505b261ecSmrg y = miPolyBuildEdge (xa, ya, k, dx, dy, face->x, face->y, !left, edge); 102605b261ecSmrg edge->height = 32767; 102705b261ecSmrg } 102805b261ecSmrg *leftEdge = !left; 102905b261ecSmrg return y; 103005b261ecSmrg} 103105b261ecSmrg 103205b261ecSmrgstatic void 103305b261ecSmrgmiLineArc ( 103405b261ecSmrg DrawablePtr pDraw, 103505b261ecSmrg GCPtr pGC, 103605b261ecSmrg unsigned long pixel, 103705b261ecSmrg SpanDataPtr spanData, 103805b261ecSmrg LineFacePtr leftFace, 103905b261ecSmrg LineFacePtr rightFace, 104005b261ecSmrg double xorg, 104105b261ecSmrg double yorg, 104205b261ecSmrg Bool isInt) 104305b261ecSmrg{ 104405b261ecSmrg int xorgi = 0, yorgi = 0; 104505b261ecSmrg Spans spanRec; 104605b261ecSmrg int n; 104705b261ecSmrg PolyEdgeRec edge1, edge2; 104805b261ecSmrg int edgey1, edgey2; 104905b261ecSmrg Bool edgeleft1, edgeleft2; 105005b261ecSmrg 105105b261ecSmrg if (isInt) 105205b261ecSmrg { 105305b261ecSmrg xorgi = leftFace ? leftFace->x : rightFace->x; 105405b261ecSmrg yorgi = leftFace ? leftFace->y : rightFace->y; 105505b261ecSmrg } 105605b261ecSmrg edgey1 = 65536; 105705b261ecSmrg edgey2 = 65536; 105805b261ecSmrg edge1.x = 0; /* not used, keep memory checkers happy */ 105905b261ecSmrg edge1.dy = -1; 106005b261ecSmrg edge2.x = 0; /* not used, keep memory checkers happy */ 106105b261ecSmrg edge2.dy = -1; 106205b261ecSmrg edgeleft1 = FALSE; 106305b261ecSmrg edgeleft2 = FALSE; 106405b261ecSmrg if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) && 106505b261ecSmrg ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) || 106605b261ecSmrg (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))) 106705b261ecSmrg { 106805b261ecSmrg if (isInt) 106905b261ecSmrg { 107005b261ecSmrg xorg = (double) xorgi; 107105b261ecSmrg yorg = (double) yorgi; 107205b261ecSmrg } 107305b261ecSmrg if (leftFace && rightFace) 107405b261ecSmrg { 107505b261ecSmrg miRoundJoinClip (leftFace, rightFace, &edge1, &edge2, 107605b261ecSmrg &edgey1, &edgey2, &edgeleft1, &edgeleft2); 107705b261ecSmrg } 107805b261ecSmrg else if (leftFace) 107905b261ecSmrg { 108005b261ecSmrg edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1); 108105b261ecSmrg } 108205b261ecSmrg else if (rightFace) 108305b261ecSmrg { 108405b261ecSmrg edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2); 108505b261ecSmrg } 108605b261ecSmrg isInt = FALSE; 108705b261ecSmrg } 10886747b715Smrg if (!InitSpans(&spanRec, pGC->lineWidth)) 10896747b715Smrg return; 109005b261ecSmrg if (isInt) 10916747b715Smrg n = miLineArcI(pDraw, pGC, xorgi, yorgi, spanRec.points, spanRec.widths); 109205b261ecSmrg else 10936747b715Smrg n = miLineArcD(pDraw, pGC, xorg, yorg, spanRec.points, spanRec.widths, 109405b261ecSmrg &edge1, edgey1, edgeleft1, 109505b261ecSmrg &edge2, edgey2, edgeleft2); 10966747b715Smrg spanRec.count = n; 10976747b715Smrg fillSpans (pDraw, pGC, pixel, &spanRec, spanData); 109805b261ecSmrg} 109905b261ecSmrg 110005b261ecSmrgstatic void 110105b261ecSmrgmiLineProjectingCap (DrawablePtr pDrawable, GCPtr pGC, unsigned long pixel, 110205b261ecSmrg SpanDataPtr spanData, LineFacePtr face, Bool isLeft, 110305b261ecSmrg double xorg, double yorg, Bool isInt) 110405b261ecSmrg{ 110505b261ecSmrg int xorgi = 0, yorgi = 0; 110605b261ecSmrg int lw; 110705b261ecSmrg PolyEdgeRec lefts[2], rights[2]; 110805b261ecSmrg int lefty, righty, topy, bottomy; 110905b261ecSmrg PolyEdgePtr left, right; 111005b261ecSmrg PolyEdgePtr top, bottom; 111105b261ecSmrg double xa,ya; 111205b261ecSmrg double k; 111305b261ecSmrg double xap, yap; 111405b261ecSmrg int dx, dy; 111505b261ecSmrg double projectXoff, projectYoff; 111605b261ecSmrg double maxy; 111705b261ecSmrg int finaly; 111805b261ecSmrg 111905b261ecSmrg if (isInt) 112005b261ecSmrg { 112105b261ecSmrg xorgi = face->x; 112205b261ecSmrg yorgi = face->y; 112305b261ecSmrg } 112405b261ecSmrg lw = pGC->lineWidth; 112505b261ecSmrg dx = face->dx; 112605b261ecSmrg dy = face->dy; 112705b261ecSmrg k = face->k; 112805b261ecSmrg if (dy == 0) 112905b261ecSmrg { 113005b261ecSmrg lefts[0].height = lw; 113105b261ecSmrg lefts[0].x = xorgi; 113205b261ecSmrg if (isLeft) 113305b261ecSmrg lefts[0].x -= (lw >> 1); 113405b261ecSmrg lefts[0].stepx = 0; 113505b261ecSmrg lefts[0].signdx = 1; 113605b261ecSmrg lefts[0].e = -lw; 113705b261ecSmrg lefts[0].dx = 0; 113805b261ecSmrg lefts[0].dy = lw; 113905b261ecSmrg rights[0].height = lw; 114005b261ecSmrg rights[0].x = xorgi; 114105b261ecSmrg if (!isLeft) 114205b261ecSmrg rights[0].x += ((lw + 1) >> 1); 114305b261ecSmrg rights[0].stepx = 0; 114405b261ecSmrg rights[0].signdx = 1; 114505b261ecSmrg rights[0].e = -lw; 114605b261ecSmrg rights[0].dx = 0; 114705b261ecSmrg rights[0].dy = lw; 114805b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, yorgi - (lw >> 1), lw, 114905b261ecSmrg lefts, rights, 1, 1); 115005b261ecSmrg } 115105b261ecSmrg else if (dx == 0) 115205b261ecSmrg { 115305b261ecSmrg if (dy < 0) { 115405b261ecSmrg dy = -dy; 115505b261ecSmrg isLeft = !isLeft; 115605b261ecSmrg } 115705b261ecSmrg topy = yorgi; 115805b261ecSmrg bottomy = yorgi + dy; 115905b261ecSmrg if (isLeft) 116005b261ecSmrg topy -= (lw >> 1); 116105b261ecSmrg else 116205b261ecSmrg bottomy += (lw >> 1); 116305b261ecSmrg lefts[0].height = bottomy - topy; 116405b261ecSmrg lefts[0].x = xorgi - (lw >> 1); 116505b261ecSmrg lefts[0].stepx = 0; 116605b261ecSmrg lefts[0].signdx = 1; 116705b261ecSmrg lefts[0].e = -dy; 116805b261ecSmrg lefts[0].dx = dx; 116905b261ecSmrg lefts[0].dy = dy; 117005b261ecSmrg 117105b261ecSmrg rights[0].height = bottomy - topy; 117205b261ecSmrg rights[0].x = lefts[0].x + (lw-1); 117305b261ecSmrg rights[0].stepx = 0; 117405b261ecSmrg rights[0].signdx = 1; 117505b261ecSmrg rights[0].e = -dy; 117605b261ecSmrg rights[0].dx = dx; 117705b261ecSmrg rights[0].dy = dy; 117805b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, bottomy - topy, lefts, rights, 1, 1); 117905b261ecSmrg } 118005b261ecSmrg else 118105b261ecSmrg { 118205b261ecSmrg xa = face->xa; 118305b261ecSmrg ya = face->ya; 118405b261ecSmrg projectXoff = -ya; 118505b261ecSmrg projectYoff = xa; 118605b261ecSmrg if (dx < 0) 118705b261ecSmrg { 118805b261ecSmrg right = &rights[1]; 118905b261ecSmrg left = &lefts[0]; 119005b261ecSmrg top = &rights[0]; 119105b261ecSmrg bottom = &lefts[1]; 119205b261ecSmrg } 119305b261ecSmrg else 119405b261ecSmrg { 119505b261ecSmrg right = &rights[0]; 119605b261ecSmrg left = &lefts[1]; 119705b261ecSmrg top = &lefts[0]; 119805b261ecSmrg bottom = &rights[1]; 119905b261ecSmrg } 120005b261ecSmrg if (isLeft) 120105b261ecSmrg { 120205b261ecSmrg righty = miPolyBuildEdge (xa, ya, 120305b261ecSmrg k, dx, dy, xorgi, yorgi, 0, right); 120405b261ecSmrg 120505b261ecSmrg xa = -xa; 120605b261ecSmrg ya = -ya; 120705b261ecSmrg k = -k; 120805b261ecSmrg lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 120905b261ecSmrg k, dx, dy, xorgi, yorgi, 1, left); 121005b261ecSmrg if (dx > 0) 121105b261ecSmrg { 121205b261ecSmrg ya = -ya; 121305b261ecSmrg xa = -xa; 121405b261ecSmrg } 121505b261ecSmrg xap = xa - projectXoff; 121605b261ecSmrg yap = ya - projectYoff; 121705b261ecSmrg topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 121805b261ecSmrg -dy, dx, xorgi, yorgi, dx > 0, top); 121905b261ecSmrg bottomy = miPolyBuildEdge (xa, ya, 122005b261ecSmrg 0.0, -dy, dx, xorgi, yorgi, dx < 0, bottom); 122105b261ecSmrg maxy = -ya; 122205b261ecSmrg } 122305b261ecSmrg else 122405b261ecSmrg { 122505b261ecSmrg righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 122605b261ecSmrg k, dx, dy, xorgi, yorgi, 0, right); 122705b261ecSmrg 122805b261ecSmrg xa = -xa; 122905b261ecSmrg ya = -ya; 123005b261ecSmrg k = -k; 123105b261ecSmrg lefty = miPolyBuildEdge (xa, ya, 123205b261ecSmrg k, dx, dy, xorgi, yorgi, 1, left); 123305b261ecSmrg if (dx > 0) 123405b261ecSmrg { 123505b261ecSmrg ya = -ya; 123605b261ecSmrg xa = -xa; 123705b261ecSmrg } 123805b261ecSmrg xap = xa - projectXoff; 123905b261ecSmrg yap = ya - projectYoff; 124005b261ecSmrg topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0, top); 124105b261ecSmrg bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 124205b261ecSmrg -dy, dx, xorgi, xorgi, dx < 0, bottom); 124305b261ecSmrg maxy = -ya + projectYoff; 124405b261ecSmrg } 124505b261ecSmrg finaly = ICEIL(maxy) + yorgi; 124605b261ecSmrg if (dx < 0) 124705b261ecSmrg { 124805b261ecSmrg left->height = bottomy - lefty; 124905b261ecSmrg right->height = finaly - righty; 125005b261ecSmrg top->height = righty - topy; 125105b261ecSmrg } 125205b261ecSmrg else 125305b261ecSmrg { 125405b261ecSmrg right->height = bottomy - righty; 125505b261ecSmrg left->height = finaly - lefty; 125605b261ecSmrg top->height = lefty - topy; 125705b261ecSmrg } 125805b261ecSmrg bottom->height = finaly - bottomy; 125905b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, 126005b261ecSmrg bottom->height + bottomy - topy, lefts, rights, 2, 2); 126105b261ecSmrg } 126205b261ecSmrg} 126305b261ecSmrg 126405b261ecSmrgstatic void 126505b261ecSmrgmiWideSegment ( 126605b261ecSmrg DrawablePtr pDrawable, 126705b261ecSmrg GCPtr pGC, 126805b261ecSmrg unsigned long pixel, 126905b261ecSmrg SpanDataPtr spanData, 127005b261ecSmrg int x1, 127105b261ecSmrg int y1, 127205b261ecSmrg int x2, 127305b261ecSmrg int y2, 127405b261ecSmrg Bool projectLeft, 127505b261ecSmrg Bool projectRight, 127605b261ecSmrg LineFacePtr leftFace, 127705b261ecSmrg LineFacePtr rightFace) 127805b261ecSmrg{ 127905b261ecSmrg double l, L, r; 128005b261ecSmrg double xa, ya; 128105b261ecSmrg double projectXoff = 0.0, projectYoff = 0.0; 128205b261ecSmrg double k; 128305b261ecSmrg double maxy; 128405b261ecSmrg int x, y; 128505b261ecSmrg int dx, dy; 128605b261ecSmrg int finaly; 128705b261ecSmrg PolyEdgePtr left, right; 128805b261ecSmrg PolyEdgePtr top, bottom; 128905b261ecSmrg int lefty, righty, topy, bottomy; 129005b261ecSmrg int signdx; 129105b261ecSmrg PolyEdgeRec lefts[2], rights[2]; 129205b261ecSmrg LineFacePtr tface; 129305b261ecSmrg int lw = pGC->lineWidth; 129405b261ecSmrg 129505b261ecSmrg /* draw top-to-bottom always */ 129605b261ecSmrg if (y2 < y1 || (y2 == y1 && x2 < x1)) 129705b261ecSmrg { 129805b261ecSmrg x = x1; 129905b261ecSmrg x1 = x2; 130005b261ecSmrg x2 = x; 130105b261ecSmrg 130205b261ecSmrg y = y1; 130305b261ecSmrg y1 = y2; 130405b261ecSmrg y2 = y; 130505b261ecSmrg 130605b261ecSmrg x = projectLeft; 130705b261ecSmrg projectLeft = projectRight; 130805b261ecSmrg projectRight = x; 130905b261ecSmrg 131005b261ecSmrg tface = leftFace; 131105b261ecSmrg leftFace = rightFace; 131205b261ecSmrg rightFace = tface; 131305b261ecSmrg } 131405b261ecSmrg 131505b261ecSmrg dy = y2 - y1; 131605b261ecSmrg signdx = 1; 131705b261ecSmrg dx = x2 - x1; 131805b261ecSmrg if (dx < 0) 131905b261ecSmrg signdx = -1; 132005b261ecSmrg 132105b261ecSmrg leftFace->x = x1; 132205b261ecSmrg leftFace->y = y1; 132305b261ecSmrg leftFace->dx = dx; 132405b261ecSmrg leftFace->dy = dy; 132505b261ecSmrg 132605b261ecSmrg rightFace->x = x2; 132705b261ecSmrg rightFace->y = y2; 132805b261ecSmrg rightFace->dx = -dx; 132905b261ecSmrg rightFace->dy = -dy; 133005b261ecSmrg 133105b261ecSmrg if (dy == 0) 133205b261ecSmrg { 133305b261ecSmrg rightFace->xa = 0; 133405b261ecSmrg rightFace->ya = (double) lw / 2.0; 133505b261ecSmrg rightFace->k = -(double) (lw * dx) / 2.0; 133605b261ecSmrg leftFace->xa = 0; 133705b261ecSmrg leftFace->ya = -rightFace->ya; 133805b261ecSmrg leftFace->k = rightFace->k; 133905b261ecSmrg x = x1; 134005b261ecSmrg if (projectLeft) 134105b261ecSmrg x -= (lw >> 1); 134205b261ecSmrg y = y1 - (lw >> 1); 134305b261ecSmrg dx = x2 - x; 134405b261ecSmrg if (projectRight) 134505b261ecSmrg dx += ((lw + 1) >> 1); 134605b261ecSmrg dy = lw; 134705b261ecSmrg miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, 134805b261ecSmrg x, y, dx, dy); 134905b261ecSmrg } 135005b261ecSmrg else if (dx == 0) 135105b261ecSmrg { 135205b261ecSmrg leftFace->xa = (double) lw / 2.0; 135305b261ecSmrg leftFace->ya = 0; 135405b261ecSmrg leftFace->k = (double) (lw * dy) / 2.0; 135505b261ecSmrg rightFace->xa = -leftFace->xa; 135605b261ecSmrg rightFace->ya = 0; 135705b261ecSmrg rightFace->k = leftFace->k; 135805b261ecSmrg y = y1; 135905b261ecSmrg if (projectLeft) 136005b261ecSmrg y -= lw >> 1; 136105b261ecSmrg x = x1 - (lw >> 1); 136205b261ecSmrg dy = y2 - y; 136305b261ecSmrg if (projectRight) 136405b261ecSmrg dy += ((lw + 1) >> 1); 136505b261ecSmrg dx = lw; 136605b261ecSmrg miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, 136705b261ecSmrg x, y, dx, dy); 136805b261ecSmrg } 136905b261ecSmrg else 137005b261ecSmrg { 137105b261ecSmrg l = ((double) lw) / 2.0; 137205b261ecSmrg L = hypot ((double) dx, (double) dy); 137305b261ecSmrg 137405b261ecSmrg if (dx < 0) 137505b261ecSmrg { 137605b261ecSmrg right = &rights[1]; 137705b261ecSmrg left = &lefts[0]; 137805b261ecSmrg top = &rights[0]; 137905b261ecSmrg bottom = &lefts[1]; 138005b261ecSmrg } 138105b261ecSmrg else 138205b261ecSmrg { 138305b261ecSmrg right = &rights[0]; 138405b261ecSmrg left = &lefts[1]; 138505b261ecSmrg top = &lefts[0]; 138605b261ecSmrg bottom = &rights[1]; 138705b261ecSmrg } 138805b261ecSmrg r = l / L; 138905b261ecSmrg 139005b261ecSmrg /* coord of upper bound at integral y */ 139105b261ecSmrg ya = -r * dx; 139205b261ecSmrg xa = r * dy; 139305b261ecSmrg 139405b261ecSmrg if (projectLeft | projectRight) 139505b261ecSmrg { 139605b261ecSmrg projectXoff = -ya; 139705b261ecSmrg projectYoff = xa; 139805b261ecSmrg } 139905b261ecSmrg 140005b261ecSmrg /* xa * dy - ya * dx */ 140105b261ecSmrg k = l * L; 140205b261ecSmrg 140305b261ecSmrg leftFace->xa = xa; 140405b261ecSmrg leftFace->ya = ya; 140505b261ecSmrg leftFace->k = k; 140605b261ecSmrg rightFace->xa = -xa; 140705b261ecSmrg rightFace->ya = -ya; 140805b261ecSmrg rightFace->k = k; 140905b261ecSmrg 141005b261ecSmrg if (projectLeft) 141105b261ecSmrg righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 141205b261ecSmrg k, dx, dy, x1, y1, 0, right); 141305b261ecSmrg else 141405b261ecSmrg righty = miPolyBuildEdge (xa, ya, 141505b261ecSmrg k, dx, dy, x1, y1, 0, right); 141605b261ecSmrg 141705b261ecSmrg /* coord of lower bound at integral y */ 141805b261ecSmrg ya = -ya; 141905b261ecSmrg xa = -xa; 142005b261ecSmrg 142105b261ecSmrg /* xa * dy - ya * dx */ 142205b261ecSmrg k = - k; 142305b261ecSmrg 142405b261ecSmrg if (projectLeft) 142505b261ecSmrg lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, 142605b261ecSmrg k, dx, dy, x1, y1, 1, left); 142705b261ecSmrg else 142805b261ecSmrg lefty = miPolyBuildEdge (xa, ya, 142905b261ecSmrg k, dx, dy, x1, y1, 1, left); 143005b261ecSmrg 143105b261ecSmrg /* coord of top face at integral y */ 143205b261ecSmrg 143305b261ecSmrg if (signdx > 0) 143405b261ecSmrg { 143505b261ecSmrg ya = -ya; 143605b261ecSmrg xa = -xa; 143705b261ecSmrg } 143805b261ecSmrg 143905b261ecSmrg if (projectLeft) 144005b261ecSmrg { 144105b261ecSmrg double xap = xa - projectXoff; 144205b261ecSmrg double yap = ya - projectYoff; 144305b261ecSmrg topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 144405b261ecSmrg -dy, dx, x1, y1, dx > 0, top); 144505b261ecSmrg } 144605b261ecSmrg else 144705b261ecSmrg topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top); 144805b261ecSmrg 144905b261ecSmrg /* coord of bottom face at integral y */ 145005b261ecSmrg 145105b261ecSmrg if (projectRight) 145205b261ecSmrg { 145305b261ecSmrg double xap = xa + projectXoff; 145405b261ecSmrg double yap = ya + projectYoff; 145505b261ecSmrg bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, 145605b261ecSmrg -dy, dx, x2, y2, dx < 0, bottom); 145705b261ecSmrg maxy = -ya + projectYoff; 145805b261ecSmrg } 145905b261ecSmrg else 146005b261ecSmrg { 146105b261ecSmrg bottomy = miPolyBuildEdge (xa, ya, 146205b261ecSmrg 0.0, -dy, dx, x2, y2, dx < 0, bottom); 146305b261ecSmrg maxy = -ya; 146405b261ecSmrg } 146505b261ecSmrg 146605b261ecSmrg finaly = ICEIL (maxy) + y2; 146705b261ecSmrg 146805b261ecSmrg if (dx < 0) 146905b261ecSmrg { 147005b261ecSmrg left->height = bottomy - lefty; 147105b261ecSmrg right->height = finaly - righty; 147205b261ecSmrg top->height = righty - topy; 147305b261ecSmrg } 147405b261ecSmrg else 147505b261ecSmrg { 147605b261ecSmrg right->height = bottomy - righty; 147705b261ecSmrg left->height = finaly - lefty; 147805b261ecSmrg top->height = lefty - topy; 147905b261ecSmrg } 148005b261ecSmrg bottom->height = finaly - bottomy; 148105b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, 148205b261ecSmrg bottom->height + bottomy - topy, lefts, rights, 2, 2); 148305b261ecSmrg } 148405b261ecSmrg} 148505b261ecSmrg 148605b261ecSmrgstatic SpanDataPtr 148705b261ecSmrgmiSetupSpanData (GCPtr pGC, SpanDataPtr spanData, int npt) 148805b261ecSmrg{ 148905b261ecSmrg if ((npt < 3 && pGC->capStyle != CapRound) || miSpansEasyRop(pGC->alu)) 149005b261ecSmrg return (SpanDataPtr) NULL; 149105b261ecSmrg if (pGC->lineStyle == LineDoubleDash) 149205b261ecSmrg miInitSpanGroup (&spanData->bgGroup); 149305b261ecSmrg miInitSpanGroup (&spanData->fgGroup); 149405b261ecSmrg return spanData; 149505b261ecSmrg} 149605b261ecSmrg 149705b261ecSmrgstatic void 149805b261ecSmrgmiCleanupSpanData (DrawablePtr pDrawable, GCPtr pGC, SpanDataPtr spanData) 149905b261ecSmrg{ 150005b261ecSmrg if (pGC->lineStyle == LineDoubleDash) 150105b261ecSmrg { 15026747b715Smrg ChangeGCVal oldPixel, pixel; 15036747b715Smrg pixel.val = pGC->bgPixel; 15046747b715Smrg oldPixel.val = pGC->fgPixel; 15056747b715Smrg if (pixel.val != oldPixel.val) 150605b261ecSmrg { 15076747b715Smrg ChangeGC (NullClient, pGC, GCForeground, &pixel); 150805b261ecSmrg ValidateGC (pDrawable, pGC); 150905b261ecSmrg } 151005b261ecSmrg miFillUniqueSpanGroup (pDrawable, pGC, &spanData->bgGroup); 151105b261ecSmrg miFreeSpanGroup (&spanData->bgGroup); 15126747b715Smrg if (pixel.val != oldPixel.val) 151305b261ecSmrg { 15146747b715Smrg ChangeGC (NullClient, pGC, GCForeground, &oldPixel); 151505b261ecSmrg ValidateGC (pDrawable, pGC); 151605b261ecSmrg } 151705b261ecSmrg } 151805b261ecSmrg miFillUniqueSpanGroup (pDrawable, pGC, &spanData->fgGroup); 151905b261ecSmrg miFreeSpanGroup (&spanData->fgGroup); 152005b261ecSmrg} 152105b261ecSmrg 15226747b715Smrgvoid 15234642e01fSmrgmiWideLine (DrawablePtr pDrawable, GCPtr pGC, 15244642e01fSmrg int mode, int npt, DDXPointPtr pPts) 152505b261ecSmrg{ 15264642e01fSmrg int x1, y1, x2, y2; 152705b261ecSmrg SpanDataRec spanDataRec; 152805b261ecSmrg SpanDataPtr spanData; 152905b261ecSmrg long pixel; 153005b261ecSmrg Bool projectLeft, projectRight; 153105b261ecSmrg LineFaceRec leftFace, rightFace, prevRightFace; 153205b261ecSmrg LineFaceRec firstFace; 153305b261ecSmrg int first; 153405b261ecSmrg Bool somethingDrawn = FALSE; 153505b261ecSmrg Bool selfJoin; 153605b261ecSmrg 153705b261ecSmrg spanData = miSetupSpanData (pGC, &spanDataRec, npt); 153805b261ecSmrg pixel = pGC->fgPixel; 153905b261ecSmrg x2 = pPts->x; 154005b261ecSmrg y2 = pPts->y; 154105b261ecSmrg first = TRUE; 154205b261ecSmrg selfJoin = FALSE; 154305b261ecSmrg if (npt > 1) 154405b261ecSmrg { 154505b261ecSmrg if (mode == CoordModePrevious) 154605b261ecSmrg { 154705b261ecSmrg int nptTmp; 154805b261ecSmrg DDXPointPtr pPtsTmp; 154905b261ecSmrg 155005b261ecSmrg x1 = x2; 155105b261ecSmrg y1 = y2; 155205b261ecSmrg nptTmp = npt; 155305b261ecSmrg pPtsTmp = pPts + 1; 155405b261ecSmrg while (--nptTmp) 155505b261ecSmrg { 155605b261ecSmrg x1 += pPtsTmp->x; 155705b261ecSmrg y1 += pPtsTmp->y; 155805b261ecSmrg ++pPtsTmp; 155905b261ecSmrg } 156005b261ecSmrg if (x2 == x1 && y2 == y1) 156105b261ecSmrg selfJoin = TRUE; 156205b261ecSmrg } 156305b261ecSmrg else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y) 156405b261ecSmrg { 156505b261ecSmrg selfJoin = TRUE; 156605b261ecSmrg } 156705b261ecSmrg } 156805b261ecSmrg projectLeft = pGC->capStyle == CapProjecting && !selfJoin; 156905b261ecSmrg projectRight = FALSE; 157005b261ecSmrg while (--npt) 157105b261ecSmrg { 157205b261ecSmrg x1 = x2; 157305b261ecSmrg y1 = y2; 157405b261ecSmrg ++pPts; 157505b261ecSmrg x2 = pPts->x; 157605b261ecSmrg y2 = pPts->y; 157705b261ecSmrg if (mode == CoordModePrevious) 157805b261ecSmrg { 157905b261ecSmrg x2 += x1; 158005b261ecSmrg y2 += y1; 158105b261ecSmrg } 158205b261ecSmrg if (x1 != x2 || y1 != y2) 158305b261ecSmrg { 158405b261ecSmrg somethingDrawn = TRUE; 158505b261ecSmrg if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin) 158605b261ecSmrg projectRight = TRUE; 158705b261ecSmrg miWideSegment (pDrawable, pGC, pixel, spanData, x1, y1, x2, y2, 158805b261ecSmrg projectLeft, projectRight, &leftFace, &rightFace); 158905b261ecSmrg if (first) 159005b261ecSmrg { 159105b261ecSmrg if (selfJoin) 159205b261ecSmrg firstFace = leftFace; 159305b261ecSmrg else if (pGC->capStyle == CapRound) 159405b261ecSmrg { 159505b261ecSmrg if (pGC->lineWidth == 1 && !spanData) 159605b261ecSmrg miLineOnePoint (pDrawable, pGC, pixel, spanData, x1, y1); 159705b261ecSmrg else 159805b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 159905b261ecSmrg &leftFace, (LineFacePtr) NULL, 160005b261ecSmrg (double)0.0, (double)0.0, 160105b261ecSmrg TRUE); 160205b261ecSmrg } 160305b261ecSmrg } 160405b261ecSmrg else 160505b261ecSmrg { 160605b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace, 160705b261ecSmrg &prevRightFace); 160805b261ecSmrg } 160905b261ecSmrg prevRightFace = rightFace; 161005b261ecSmrg first = FALSE; 161105b261ecSmrg projectLeft = FALSE; 161205b261ecSmrg } 161305b261ecSmrg if (npt == 1 && somethingDrawn) 161405b261ecSmrg { 161505b261ecSmrg if (selfJoin) 161605b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace, 161705b261ecSmrg &rightFace); 161805b261ecSmrg else if (pGC->capStyle == CapRound) 161905b261ecSmrg { 162005b261ecSmrg if (pGC->lineWidth == 1 && !spanData) 162105b261ecSmrg miLineOnePoint (pDrawable, pGC, pixel, spanData, x2, y2); 162205b261ecSmrg else 162305b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 162405b261ecSmrg (LineFacePtr) NULL, &rightFace, 162505b261ecSmrg (double)0.0, (double)0.0, 162605b261ecSmrg TRUE); 162705b261ecSmrg } 162805b261ecSmrg } 162905b261ecSmrg } 163005b261ecSmrg /* handle crock where all points are coincedent */ 163105b261ecSmrg if (!somethingDrawn) 163205b261ecSmrg { 163305b261ecSmrg projectLeft = pGC->capStyle == CapProjecting; 163405b261ecSmrg miWideSegment (pDrawable, pGC, pixel, spanData, 163505b261ecSmrg x2, y2, x2, y2, projectLeft, projectLeft, 163605b261ecSmrg &leftFace, &rightFace); 163705b261ecSmrg if (pGC->capStyle == CapRound) 163805b261ecSmrg { 163905b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 164005b261ecSmrg &leftFace, (LineFacePtr) NULL, 164105b261ecSmrg (double)0.0, (double)0.0, 164205b261ecSmrg TRUE); 164305b261ecSmrg rightFace.dx = -1; /* sleezy hack to make it work */ 164405b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 164505b261ecSmrg (LineFacePtr) NULL, &rightFace, 164605b261ecSmrg (double)0.0, (double)0.0, 164705b261ecSmrg TRUE); 164805b261ecSmrg } 164905b261ecSmrg } 165005b261ecSmrg if (spanData) 165105b261ecSmrg miCleanupSpanData (pDrawable, pGC, spanData); 165205b261ecSmrg} 165305b261ecSmrg 165405b261ecSmrg#define V_TOP 0 165505b261ecSmrg#define V_RIGHT 1 165605b261ecSmrg#define V_BOTTOM 2 165705b261ecSmrg#define V_LEFT 3 165805b261ecSmrg 165905b261ecSmrgstatic void 166005b261ecSmrgmiWideDashSegment ( 166105b261ecSmrg DrawablePtr pDrawable, 166205b261ecSmrg GCPtr pGC, 166305b261ecSmrg SpanDataPtr spanData, 166405b261ecSmrg int *pDashOffset, 166505b261ecSmrg int *pDashIndex, 166605b261ecSmrg int x1, 166705b261ecSmrg int y1, 166805b261ecSmrg int x2, 166905b261ecSmrg int y2, 167005b261ecSmrg Bool projectLeft, 167105b261ecSmrg Bool projectRight, 167205b261ecSmrg LineFacePtr leftFace, 167305b261ecSmrg LineFacePtr rightFace) 167405b261ecSmrg{ 167505b261ecSmrg int dashIndex, dashRemain; 167605b261ecSmrg unsigned char *pDash; 167705b261ecSmrg double L, l; 167805b261ecSmrg double k; 167905b261ecSmrg PolyVertexRec vertices[4]; 168005b261ecSmrg PolyVertexRec saveRight, saveBottom; 168105b261ecSmrg PolySlopeRec slopes[4]; 168205b261ecSmrg PolyEdgeRec left[2], right[2]; 168305b261ecSmrg LineFaceRec lcapFace, rcapFace; 168405b261ecSmrg int nleft, nright; 168505b261ecSmrg int h; 168605b261ecSmrg int y; 168705b261ecSmrg int dy, dx; 168805b261ecSmrg unsigned long pixel; 168905b261ecSmrg double LRemain; 169005b261ecSmrg double r; 169105b261ecSmrg double rdx, rdy; 169205b261ecSmrg double dashDx, dashDy; 169305b261ecSmrg double saveK = 0.0; 169405b261ecSmrg Bool first = TRUE; 169505b261ecSmrg double lcenterx, lcentery, rcenterx = 0.0, rcentery = 0.0; 169605b261ecSmrg unsigned long fgPixel, bgPixel; 169705b261ecSmrg 169805b261ecSmrg dx = x2 - x1; 169905b261ecSmrg dy = y2 - y1; 170005b261ecSmrg dashIndex = *pDashIndex; 170105b261ecSmrg pDash = pGC->dash; 170205b261ecSmrg dashRemain = pDash[dashIndex] - *pDashOffset; 170305b261ecSmrg fgPixel = pGC->fgPixel; 170405b261ecSmrg bgPixel = pGC->bgPixel; 170505b261ecSmrg if (pGC->fillStyle == FillOpaqueStippled || 170605b261ecSmrg pGC->fillStyle == FillTiled) 170705b261ecSmrg { 170805b261ecSmrg bgPixel = fgPixel; 170905b261ecSmrg } 171005b261ecSmrg 171105b261ecSmrg l = ((double) pGC->lineWidth) / 2.0; 171205b261ecSmrg if (dx == 0) 171305b261ecSmrg { 171405b261ecSmrg L = dy; 171505b261ecSmrg rdx = 0; 171605b261ecSmrg rdy = l; 171705b261ecSmrg if (dy < 0) 171805b261ecSmrg { 171905b261ecSmrg L = -dy; 172005b261ecSmrg rdy = -l; 172105b261ecSmrg } 172205b261ecSmrg } 172305b261ecSmrg else if (dy == 0) 172405b261ecSmrg { 172505b261ecSmrg L = dx; 172605b261ecSmrg rdx = l; 172705b261ecSmrg rdy = 0; 172805b261ecSmrg if (dx < 0) 172905b261ecSmrg { 173005b261ecSmrg L = -dx; 173105b261ecSmrg rdx = -l; 173205b261ecSmrg } 173305b261ecSmrg } 173405b261ecSmrg else 173505b261ecSmrg { 173605b261ecSmrg L = hypot ((double) dx, (double) dy); 173705b261ecSmrg r = l / L; 173805b261ecSmrg 173905b261ecSmrg rdx = r * dx; 174005b261ecSmrg rdy = r * dy; 174105b261ecSmrg } 174205b261ecSmrg k = l * L; 174305b261ecSmrg LRemain = L; 174405b261ecSmrg /* All position comments are relative to a line with dx and dy > 0, 174505b261ecSmrg * but the code does not depend on this */ 174605b261ecSmrg /* top */ 174705b261ecSmrg slopes[V_TOP].dx = dx; 174805b261ecSmrg slopes[V_TOP].dy = dy; 174905b261ecSmrg slopes[V_TOP].k = k; 175005b261ecSmrg /* right */ 175105b261ecSmrg slopes[V_RIGHT].dx = -dy; 175205b261ecSmrg slopes[V_RIGHT].dy = dx; 175305b261ecSmrg slopes[V_RIGHT].k = 0; 175405b261ecSmrg /* bottom */ 175505b261ecSmrg slopes[V_BOTTOM].dx = -dx; 175605b261ecSmrg slopes[V_BOTTOM].dy = -dy; 175705b261ecSmrg slopes[V_BOTTOM].k = k; 175805b261ecSmrg /* left */ 175905b261ecSmrg slopes[V_LEFT].dx = dy; 176005b261ecSmrg slopes[V_LEFT].dy = -dx; 176105b261ecSmrg slopes[V_LEFT].k = 0; 176205b261ecSmrg 176305b261ecSmrg /* preload the start coordinates */ 176405b261ecSmrg vertices[V_RIGHT].x = vertices[V_TOP].x = rdy; 176505b261ecSmrg vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx; 176605b261ecSmrg 176705b261ecSmrg vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy; 176805b261ecSmrg vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx; 176905b261ecSmrg 177005b261ecSmrg if (projectLeft) 177105b261ecSmrg { 177205b261ecSmrg vertices[V_TOP].x -= rdx; 177305b261ecSmrg vertices[V_TOP].y -= rdy; 177405b261ecSmrg 177505b261ecSmrg vertices[V_LEFT].x -= rdx; 177605b261ecSmrg vertices[V_LEFT].y -= rdy; 177705b261ecSmrg 177805b261ecSmrg slopes[V_LEFT].k = rdx * dx + rdy * dy; 177905b261ecSmrg } 178005b261ecSmrg 178105b261ecSmrg lcenterx = x1; 178205b261ecSmrg lcentery = y1; 178305b261ecSmrg 178405b261ecSmrg if (pGC->capStyle == CapRound) 178505b261ecSmrg { 178605b261ecSmrg lcapFace.dx = dx; 178705b261ecSmrg lcapFace.dy = dy; 178805b261ecSmrg lcapFace.x = x1; 178905b261ecSmrg lcapFace.y = y1; 179005b261ecSmrg 179105b261ecSmrg rcapFace.dx = -dx; 179205b261ecSmrg rcapFace.dy = -dy; 179305b261ecSmrg rcapFace.x = x1; 179405b261ecSmrg rcapFace.y = y1; 179505b261ecSmrg } 179605b261ecSmrg while (LRemain > dashRemain) 179705b261ecSmrg { 179805b261ecSmrg dashDx = (dashRemain * dx) / L; 179905b261ecSmrg dashDy = (dashRemain * dy) / L; 180005b261ecSmrg 180105b261ecSmrg rcenterx = lcenterx + dashDx; 180205b261ecSmrg rcentery = lcentery + dashDy; 180305b261ecSmrg 180405b261ecSmrg vertices[V_RIGHT].x += dashDx; 180505b261ecSmrg vertices[V_RIGHT].y += dashDy; 180605b261ecSmrg 180705b261ecSmrg vertices[V_BOTTOM].x += dashDx; 180805b261ecSmrg vertices[V_BOTTOM].y += dashDy; 180905b261ecSmrg 181005b261ecSmrg slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy; 181105b261ecSmrg 181205b261ecSmrg if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) 181305b261ecSmrg { 181405b261ecSmrg if (pGC->lineStyle == LineOnOffDash && 181505b261ecSmrg pGC->capStyle == CapProjecting) 181605b261ecSmrg { 181705b261ecSmrg saveRight = vertices[V_RIGHT]; 181805b261ecSmrg saveBottom = vertices[V_BOTTOM]; 181905b261ecSmrg saveK = slopes[V_RIGHT].k; 182005b261ecSmrg 182105b261ecSmrg if (!first) 182205b261ecSmrg { 182305b261ecSmrg vertices[V_TOP].x -= rdx; 182405b261ecSmrg vertices[V_TOP].y -= rdy; 182505b261ecSmrg 182605b261ecSmrg vertices[V_LEFT].x -= rdx; 182705b261ecSmrg vertices[V_LEFT].y -= rdy; 182805b261ecSmrg 182905b261ecSmrg slopes[V_LEFT].k = vertices[V_LEFT].x * 183005b261ecSmrg slopes[V_LEFT].dy - 183105b261ecSmrg vertices[V_LEFT].y * 183205b261ecSmrg slopes[V_LEFT].dx; 183305b261ecSmrg } 183405b261ecSmrg 183505b261ecSmrg vertices[V_RIGHT].x += rdx; 183605b261ecSmrg vertices[V_RIGHT].y += rdy; 183705b261ecSmrg 183805b261ecSmrg vertices[V_BOTTOM].x += rdx; 183905b261ecSmrg vertices[V_BOTTOM].y += rdy; 184005b261ecSmrg 184105b261ecSmrg slopes[V_RIGHT].k = vertices[V_RIGHT].x * 184205b261ecSmrg slopes[V_RIGHT].dy - 184305b261ecSmrg vertices[V_RIGHT].y * 184405b261ecSmrg slopes[V_RIGHT].dx; 184505b261ecSmrg } 184605b261ecSmrg y = miPolyBuildPoly (vertices, slopes, 4, x1, y1, 184705b261ecSmrg left, right, &nleft, &nright, &h); 184805b261ecSmrg pixel = (dashIndex & 1) ? bgPixel : fgPixel; 184905b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright); 185005b261ecSmrg 185105b261ecSmrg if (pGC->lineStyle == LineOnOffDash) 185205b261ecSmrg { 185305b261ecSmrg switch (pGC->capStyle) 185405b261ecSmrg { 185505b261ecSmrg case CapProjecting: 185605b261ecSmrg vertices[V_BOTTOM] = saveBottom; 185705b261ecSmrg vertices[V_RIGHT] = saveRight; 185805b261ecSmrg slopes[V_RIGHT].k = saveK; 185905b261ecSmrg break; 186005b261ecSmrg case CapRound: 186105b261ecSmrg if (!first) 186205b261ecSmrg { 186305b261ecSmrg if (dx < 0) 186405b261ecSmrg { 186505b261ecSmrg lcapFace.xa = -vertices[V_LEFT].x; 186605b261ecSmrg lcapFace.ya = -vertices[V_LEFT].y; 186705b261ecSmrg lcapFace.k = slopes[V_LEFT].k; 186805b261ecSmrg } 186905b261ecSmrg else 187005b261ecSmrg { 187105b261ecSmrg lcapFace.xa = vertices[V_TOP].x; 187205b261ecSmrg lcapFace.ya = vertices[V_TOP].y; 187305b261ecSmrg lcapFace.k = -slopes[V_LEFT].k; 187405b261ecSmrg } 187505b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 187605b261ecSmrg &lcapFace, (LineFacePtr) NULL, 187705b261ecSmrg lcenterx, lcentery, FALSE); 187805b261ecSmrg } 187905b261ecSmrg if (dx < 0) 188005b261ecSmrg { 188105b261ecSmrg rcapFace.xa = vertices[V_BOTTOM].x; 188205b261ecSmrg rcapFace.ya = vertices[V_BOTTOM].y; 188305b261ecSmrg rcapFace.k = slopes[V_RIGHT].k; 188405b261ecSmrg } 188505b261ecSmrg else 188605b261ecSmrg { 188705b261ecSmrg rcapFace.xa = -vertices[V_RIGHT].x; 188805b261ecSmrg rcapFace.ya = -vertices[V_RIGHT].y; 188905b261ecSmrg rcapFace.k = -slopes[V_RIGHT].k; 189005b261ecSmrg } 189105b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 189205b261ecSmrg (LineFacePtr) NULL, &rcapFace, 189305b261ecSmrg rcenterx, rcentery, FALSE); 189405b261ecSmrg break; 189505b261ecSmrg } 189605b261ecSmrg } 189705b261ecSmrg } 189805b261ecSmrg LRemain -= dashRemain; 189905b261ecSmrg ++dashIndex; 190005b261ecSmrg if (dashIndex == pGC->numInDashList) 190105b261ecSmrg dashIndex = 0; 190205b261ecSmrg dashRemain = pDash[dashIndex]; 190305b261ecSmrg 190405b261ecSmrg lcenterx = rcenterx; 190505b261ecSmrg lcentery = rcentery; 190605b261ecSmrg 190705b261ecSmrg vertices[V_TOP] = vertices[V_RIGHT]; 190805b261ecSmrg vertices[V_LEFT] = vertices[V_BOTTOM]; 190905b261ecSmrg slopes[V_LEFT].k = -slopes[V_RIGHT].k; 191005b261ecSmrg first = FALSE; 191105b261ecSmrg } 191205b261ecSmrg 191305b261ecSmrg if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) 191405b261ecSmrg { 191505b261ecSmrg vertices[V_TOP].x -= dx; 191605b261ecSmrg vertices[V_TOP].y -= dy; 191705b261ecSmrg 191805b261ecSmrg vertices[V_LEFT].x -= dx; 191905b261ecSmrg vertices[V_LEFT].y -= dy; 192005b261ecSmrg 192105b261ecSmrg vertices[V_RIGHT].x = rdy; 192205b261ecSmrg vertices[V_RIGHT].y = -rdx; 192305b261ecSmrg 192405b261ecSmrg vertices[V_BOTTOM].x = -rdy; 192505b261ecSmrg vertices[V_BOTTOM].y = rdx; 192605b261ecSmrg 192705b261ecSmrg 192805b261ecSmrg if (projectRight) 192905b261ecSmrg { 193005b261ecSmrg vertices[V_RIGHT].x += rdx; 193105b261ecSmrg vertices[V_RIGHT].y += rdy; 193205b261ecSmrg 193305b261ecSmrg vertices[V_BOTTOM].x += rdx; 193405b261ecSmrg vertices[V_BOTTOM].y += rdy; 193505b261ecSmrg slopes[V_RIGHT].k = vertices[V_RIGHT].x * 193605b261ecSmrg slopes[V_RIGHT].dy - 193705b261ecSmrg vertices[V_RIGHT].y * 193805b261ecSmrg slopes[V_RIGHT].dx; 193905b261ecSmrg } 194005b261ecSmrg else 194105b261ecSmrg slopes[V_RIGHT].k = 0; 194205b261ecSmrg 194305b261ecSmrg if (!first && pGC->lineStyle == LineOnOffDash && 194405b261ecSmrg pGC->capStyle == CapProjecting) 194505b261ecSmrg { 194605b261ecSmrg vertices[V_TOP].x -= rdx; 194705b261ecSmrg vertices[V_TOP].y -= rdy; 194805b261ecSmrg 194905b261ecSmrg vertices[V_LEFT].x -= rdx; 195005b261ecSmrg vertices[V_LEFT].y -= rdy; 195105b261ecSmrg slopes[V_LEFT].k = vertices[V_LEFT].x * 195205b261ecSmrg slopes[V_LEFT].dy - 195305b261ecSmrg vertices[V_LEFT].y * 195405b261ecSmrg slopes[V_LEFT].dx; 195505b261ecSmrg } 195605b261ecSmrg else 195705b261ecSmrg slopes[V_LEFT].k += dx * dx + dy * dy; 195805b261ecSmrg 195905b261ecSmrg 196005b261ecSmrg y = miPolyBuildPoly (vertices, slopes, 4, x2, y2, 196105b261ecSmrg left, right, &nleft, &nright, &h); 196205b261ecSmrg 196305b261ecSmrg pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel; 196405b261ecSmrg miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright); 196505b261ecSmrg if (!first && pGC->lineStyle == LineOnOffDash && 196605b261ecSmrg pGC->capStyle == CapRound) 196705b261ecSmrg { 196805b261ecSmrg lcapFace.x = x2; 196905b261ecSmrg lcapFace.y = y2; 197005b261ecSmrg if (dx < 0) 197105b261ecSmrg { 197205b261ecSmrg lcapFace.xa = -vertices[V_LEFT].x; 197305b261ecSmrg lcapFace.ya = -vertices[V_LEFT].y; 197405b261ecSmrg lcapFace.k = slopes[V_LEFT].k; 197505b261ecSmrg } 197605b261ecSmrg else 197705b261ecSmrg { 197805b261ecSmrg lcapFace.xa = vertices[V_TOP].x; 197905b261ecSmrg lcapFace.ya = vertices[V_TOP].y; 198005b261ecSmrg lcapFace.k = -slopes[V_LEFT].k; 198105b261ecSmrg } 198205b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 198305b261ecSmrg &lcapFace, (LineFacePtr) NULL, 198405b261ecSmrg rcenterx, rcentery, FALSE); 198505b261ecSmrg } 198605b261ecSmrg } 198705b261ecSmrg dashRemain = ((double) dashRemain) - LRemain; 198805b261ecSmrg if (dashRemain == 0) 198905b261ecSmrg { 199005b261ecSmrg dashIndex++; 199105b261ecSmrg if (dashIndex == pGC->numInDashList) 199205b261ecSmrg dashIndex = 0; 199305b261ecSmrg dashRemain = pDash[dashIndex]; 199405b261ecSmrg } 199505b261ecSmrg 199605b261ecSmrg leftFace->x = x1; 199705b261ecSmrg leftFace->y = y1; 199805b261ecSmrg leftFace->dx = dx; 199905b261ecSmrg leftFace->dy = dy; 200005b261ecSmrg leftFace->xa = rdy; 200105b261ecSmrg leftFace->ya = -rdx; 200205b261ecSmrg leftFace->k = k; 200305b261ecSmrg 200405b261ecSmrg rightFace->x = x2; 200505b261ecSmrg rightFace->y = y2; 200605b261ecSmrg rightFace->dx = -dx; 200705b261ecSmrg rightFace->dy = -dy; 200805b261ecSmrg rightFace->xa = -rdy; 200905b261ecSmrg rightFace->ya = rdx; 201005b261ecSmrg rightFace->k = k; 201105b261ecSmrg 201205b261ecSmrg *pDashIndex = dashIndex; 201305b261ecSmrg *pDashOffset = pDash[dashIndex] - dashRemain; 201405b261ecSmrg} 201505b261ecSmrg 20166747b715Smrgvoid 20174642e01fSmrgmiWideDash (DrawablePtr pDrawable, GCPtr pGC, 20184642e01fSmrg int mode, int npt, DDXPointPtr pPts) 201905b261ecSmrg{ 202005b261ecSmrg int x1, y1, x2, y2; 202105b261ecSmrg unsigned long pixel; 202205b261ecSmrg Bool projectLeft, projectRight; 202305b261ecSmrg LineFaceRec leftFace, rightFace, prevRightFace; 202405b261ecSmrg LineFaceRec firstFace; 202505b261ecSmrg int first; 202605b261ecSmrg int dashIndex, dashOffset; 202705b261ecSmrg int prevDashIndex; 202805b261ecSmrg SpanDataRec spanDataRec; 202905b261ecSmrg SpanDataPtr spanData; 203005b261ecSmrg Bool somethingDrawn = FALSE; 203105b261ecSmrg Bool selfJoin; 203205b261ecSmrg Bool endIsFg = FALSE, startIsFg = FALSE; 203305b261ecSmrg Bool firstIsFg = FALSE, prevIsFg = FALSE; 203405b261ecSmrg 203505b261ecSmrg#if 0 203605b261ecSmrg /* XXX backward compatibility */ 203705b261ecSmrg if (pGC->lineWidth == 0) 203805b261ecSmrg { 203905b261ecSmrg miZeroDashLine (pDrawable, pGC, mode, npt, pPts); 204005b261ecSmrg return; 204105b261ecSmrg } 204205b261ecSmrg#endif 204305b261ecSmrg if (pGC->lineStyle == LineDoubleDash && 204405b261ecSmrg (pGC->fillStyle == FillOpaqueStippled || pGC->fillStyle == FillTiled)) 204505b261ecSmrg { 204605b261ecSmrg miWideLine (pDrawable, pGC, mode, npt, pPts); 204705b261ecSmrg return; 204805b261ecSmrg } 204905b261ecSmrg if (npt == 0) 205005b261ecSmrg return; 205105b261ecSmrg spanData = miSetupSpanData (pGC, &spanDataRec, npt); 205205b261ecSmrg x2 = pPts->x; 205305b261ecSmrg y2 = pPts->y; 205405b261ecSmrg first = TRUE; 205505b261ecSmrg selfJoin = FALSE; 205605b261ecSmrg if (mode == CoordModePrevious) 205705b261ecSmrg { 205805b261ecSmrg int nptTmp; 205905b261ecSmrg DDXPointPtr pPtsTmp; 206005b261ecSmrg 206105b261ecSmrg x1 = x2; 206205b261ecSmrg y1 = y2; 206305b261ecSmrg nptTmp = npt; 206405b261ecSmrg pPtsTmp = pPts + 1; 206505b261ecSmrg while (--nptTmp) 206605b261ecSmrg { 206705b261ecSmrg x1 += pPtsTmp->x; 206805b261ecSmrg y1 += pPtsTmp->y; 206905b261ecSmrg ++pPtsTmp; 207005b261ecSmrg } 207105b261ecSmrg if (x2 == x1 && y2 == y1) 207205b261ecSmrg selfJoin = TRUE; 207305b261ecSmrg } 207405b261ecSmrg else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y) 207505b261ecSmrg { 207605b261ecSmrg selfJoin = TRUE; 207705b261ecSmrg } 207805b261ecSmrg projectLeft = pGC->capStyle == CapProjecting && !selfJoin; 207905b261ecSmrg projectRight = FALSE; 208005b261ecSmrg dashIndex = 0; 208105b261ecSmrg dashOffset = 0; 208205b261ecSmrg miStepDash ((int)pGC->dashOffset, &dashIndex, 208305b261ecSmrg pGC->dash, (int)pGC->numInDashList, &dashOffset); 208405b261ecSmrg while (--npt) 208505b261ecSmrg { 208605b261ecSmrg x1 = x2; 208705b261ecSmrg y1 = y2; 208805b261ecSmrg ++pPts; 208905b261ecSmrg x2 = pPts->x; 209005b261ecSmrg y2 = pPts->y; 209105b261ecSmrg if (mode == CoordModePrevious) 209205b261ecSmrg { 209305b261ecSmrg x2 += x1; 209405b261ecSmrg y2 += y1; 209505b261ecSmrg } 209605b261ecSmrg if (x1 != x2 || y1 != y2) 209705b261ecSmrg { 209805b261ecSmrg somethingDrawn = TRUE; 209905b261ecSmrg if (npt == 1 && pGC->capStyle == CapProjecting && 210005b261ecSmrg (!selfJoin || !firstIsFg)) 210105b261ecSmrg projectRight = TRUE; 210205b261ecSmrg prevDashIndex = dashIndex; 210305b261ecSmrg miWideDashSegment (pDrawable, pGC, spanData, &dashOffset, &dashIndex, 210405b261ecSmrg x1, y1, x2, y2, 210505b261ecSmrg projectLeft, projectRight, &leftFace, &rightFace); 210605b261ecSmrg startIsFg = !(prevDashIndex & 1); 210705b261ecSmrg endIsFg = (dashIndex & 1) ^ (dashOffset != 0); 210805b261ecSmrg if (pGC->lineStyle == LineDoubleDash || startIsFg) 210905b261ecSmrg { 211005b261ecSmrg pixel = startIsFg ? pGC->fgPixel : pGC->bgPixel; 211105b261ecSmrg if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg)) 211205b261ecSmrg { 211305b261ecSmrg if (first && selfJoin) 211405b261ecSmrg { 211505b261ecSmrg firstFace = leftFace; 211605b261ecSmrg firstIsFg = startIsFg; 211705b261ecSmrg } 211805b261ecSmrg else if (pGC->capStyle == CapRound) 211905b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 212005b261ecSmrg &leftFace, (LineFacePtr) NULL, 212105b261ecSmrg (double)0.0, (double)0.0, TRUE); 212205b261ecSmrg } 212305b261ecSmrg else 212405b261ecSmrg { 212505b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace, 212605b261ecSmrg &prevRightFace); 212705b261ecSmrg } 212805b261ecSmrg } 212905b261ecSmrg prevRightFace = rightFace; 213005b261ecSmrg prevIsFg = endIsFg; 213105b261ecSmrg first = FALSE; 213205b261ecSmrg projectLeft = FALSE; 213305b261ecSmrg } 213405b261ecSmrg if (npt == 1 && somethingDrawn) 213505b261ecSmrg { 213605b261ecSmrg if (pGC->lineStyle == LineDoubleDash || endIsFg) 213705b261ecSmrg { 213805b261ecSmrg pixel = endIsFg ? pGC->fgPixel : pGC->bgPixel; 213905b261ecSmrg if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg)) 214005b261ecSmrg { 214105b261ecSmrg miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace, 214205b261ecSmrg &rightFace); 214305b261ecSmrg } 214405b261ecSmrg else 214505b261ecSmrg { 214605b261ecSmrg if (pGC->capStyle == CapRound) 214705b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 214805b261ecSmrg (LineFacePtr) NULL, &rightFace, 214905b261ecSmrg (double)0.0, (double)0.0, TRUE); 215005b261ecSmrg } 215105b261ecSmrg } 215205b261ecSmrg else 215305b261ecSmrg { 215405b261ecSmrg /* glue a cap to the start of the line if 215505b261ecSmrg * we're OnOffDash and ended on odd dash 215605b261ecSmrg */ 215705b261ecSmrg if (selfJoin && firstIsFg) 215805b261ecSmrg { 215905b261ecSmrg pixel = pGC->fgPixel; 216005b261ecSmrg if (pGC->capStyle == CapProjecting) 216105b261ecSmrg miLineProjectingCap (pDrawable, pGC, pixel, spanData, 216205b261ecSmrg &firstFace, TRUE, 216305b261ecSmrg (double)0.0, (double)0.0, TRUE); 216405b261ecSmrg else if (pGC->capStyle == CapRound) 216505b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 216605b261ecSmrg &firstFace, (LineFacePtr) NULL, 216705b261ecSmrg (double)0.0, (double)0.0, TRUE); 216805b261ecSmrg } 216905b261ecSmrg } 217005b261ecSmrg } 217105b261ecSmrg } 217205b261ecSmrg /* handle crock where all points are coincident */ 217305b261ecSmrg if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))) 217405b261ecSmrg { 217505b261ecSmrg /* not the same as endIsFg computation above */ 217605b261ecSmrg pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel; 217705b261ecSmrg switch (pGC->capStyle) { 217805b261ecSmrg case CapRound: 217905b261ecSmrg miLineArc (pDrawable, pGC, pixel, spanData, 218005b261ecSmrg (LineFacePtr) NULL, (LineFacePtr) NULL, 218105b261ecSmrg (double)x2, (double)y2, 218205b261ecSmrg FALSE); 218305b261ecSmrg break; 218405b261ecSmrg case CapProjecting: 218505b261ecSmrg x1 = pGC->lineWidth; 218605b261ecSmrg miFillRectPolyHelper (pDrawable, pGC, pixel, spanData, 218705b261ecSmrg x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1); 218805b261ecSmrg break; 218905b261ecSmrg } 219005b261ecSmrg } 219105b261ecSmrg if (spanData) 219205b261ecSmrg miCleanupSpanData (pDrawable, pGC, spanData); 219305b261ecSmrg} 2194