summaryrefslogtreecommitdiff
path: root/src/ffb_wline.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
commit68c56916d79bf06e26e01c3e84206edc928d9b51 (patch)
treed39c13092dc680721e163e448a57df847a6fad62 /src/ffb_wline.c
Initial revision
Diffstat (limited to 'src/ffb_wline.c')
-rw-r--r--src/ffb_wline.c896
1 files changed, 896 insertions, 0 deletions
diff --git a/src/ffb_wline.c b/src/ffb_wline.c
new file mode 100644
index 0000000..feb8034
--- /dev/null
+++ b/src/ffb_wline.c
@@ -0,0 +1,896 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Wide line rops.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_wline.c,v 1.3 2001/03/03 22:41:34 tsi Exp $ */
+
+#define PSZ 32
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#include "cfb.h"
+
+#include "miwideline.h"
+
+#error If we start using this again, need to fixup FFB_WRITE_ATTRIBUTES for wids -DaveM
+
+/* Wheee, wide lines... */
+extern int miPolyBuildEdge();
+
+static int LeftClip, RightClip, TopClip, BottomClip;
+
+#define Y_IN_BOX(y) (((y) >= TopClip) && ((y) <= BottomClip))
+#define CLIPSTEPEDGE(edgey,edge,edgeleft) \
+if (ybase == edgey) { \
+ if (edgeleft) { \
+ if (edge->x > xcl) \
+ xcl = edge->x; \
+ } else { \
+ if (edge->x < xcr) \
+ xcr = edge->x; \
+ } \
+ edgey++; \
+ edge->x += edge->stepx; \
+ edge->e += edge->dx; \
+ if (edge->e > 0) { \
+ edge->x += edge->signdx; \
+ edge->e -= edge->dy; \
+ } \
+}
+
+#define CreatorPointHelper(pFfb, x, y) \
+do { \
+ ffb_fbcPtr ffb = (pFfb)->regs; \
+ FFB_WRITE_DRAWOP((pFfb), ffb, FFB_DRAWOP_DOT); \
+ FFBFifo(pFfb, 2); \
+ FFB_WRITE64(&ffb->bh, (y), (x)); \
+} while (0)
+
+static void CreatorFillRectHelper(FFBPtr pFfb,
+ int x, int y, int dx, int dy)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+ int x2 = x + dx - 1;
+ int y2 = y + dy - 1;
+
+ if(x < LeftClip)
+ x = LeftClip;
+ if(x2 > RightClip)
+ x2 = RightClip;
+ if(y < TopClip)
+ y = TopClip;
+ if(y2 > BottomClip)
+ y2 = BottomClip;
+
+ dx = x2 - x + 1;
+ dy = y2 - y + 1;
+
+ if((dx > 0) && (dy > 0)) {
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, dy, dx);
+ }
+}
+
+/* The span helper does not check for y being clipped, caller beware */
+static void CreatorSpanHelper(FFBPtr pFfb,
+ int x1, int y, int width)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+ int x2 = x1 + width - 1;
+
+ if(x1 < LeftClip)
+ x1 = LeftClip;
+ if(x2 > RightClip)
+ x2 = RightClip;
+ width = x2 - x1 + 1;
+
+ if(width > 0) {
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x1);
+ FFB_WRITE64_2(&ffb->bh, 1, width);
+ }
+}
+
+#define FixError(x, dx, dy, e, sign, step, h) { \
+ e += (h) * dx; \
+ x += (h) * step; \
+ if(e > 0) { \
+ x += e * sign/dy; \
+ e %= dy; \
+ if(e) { \
+ x += sign; \
+ e -= dy; \
+ } \
+ } \
+}
+
+static void
+CreatorFillPolyHelper (DrawablePtr pDrawable, GCPtr pGC,
+ int y, int overall_height,
+ PolyEdgePtr left, PolyEdgePtr right,
+ int left_count, int right_count)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ int left_x, left_e, left_stepx, left_signdx, left_dy, left_dx;
+ int right_x, right_e, right_stepx, right_signdx, right_dy, right_dx, height;
+ int left_height = 0;
+ int right_height = 0;
+ int xorg = 0;
+
+ if (pGC->miTranslate) {
+ y += pDrawable->y;
+ xorg = pDrawable->x;
+ }
+
+ while ((left_count || left_height) && (right_count || right_height)) {
+ if (!left_height && left_count) {
+ left_height = left->height;
+ left_x = left->x + xorg;
+ left_stepx = left->stepx;
+ left_signdx = left->signdx;
+ left_e = left->e;
+ left_dy = left->dy;
+ left_dx = left->dx;
+ left_count--;
+ left++;
+ }
+ if (!right_height && right_count) {
+ right_height = right->height;
+ right_x = right->x + xorg + 1;
+ right_stepx = right->stepx;
+ right_signdx = right->signdx;
+ right_e = right->e;
+ right_dy = right->dy;
+ right_dx = right->dx;
+ right_count--;
+ right++;
+ }
+
+ height = (left_height > right_height) ? right_height : left_height;
+
+ left_height -= height;
+ right_height -= height;
+ while (height--) {
+ if((right_x > left_x) && Y_IN_BOX(y))
+ CreatorSpanHelper(pFfb, left_x, y, right_x - left_x);
+
+ y++;
+
+ left_x += left_stepx;
+ left_e += left_dx;
+ if (left_e > 0) {
+ left_x += left_signdx;
+ left_e -= left_dy;
+ }
+ right_x += right_stepx;
+ right_e += right_dx;
+ if (right_e > 0) {
+ right_x += right_signdx;
+ right_e -= right_dy;
+ }
+ }
+ }
+}
+
+static void
+CreatorWideSegment (DrawablePtr pDrawable, GCPtr pGC,
+ int x1, int y1, int x2, int y2,
+ Bool projectLeft, Bool projectRight,
+ LineFacePtr leftFace, LineFacePtr rightFace)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ double l, L, r, xa, ya, projectXoff, projectYoff, k, maxy;
+ int x, y, dx, dy, finaly, lefty, righty, topy, bottomy, signdx;
+ PolyEdgePtr left, right, top, bottom;
+ PolyEdgeRec lefts[2], rights[2];
+ LineFacePtr tface;
+ int lw = pGC->lineWidth;
+
+ /* draw top-to-bottom always */
+ if (y2 < y1 || y2 == y1 && x2 < x1) {
+ x = x1;
+ x1 = x2;
+ x2 = x;
+
+ y = y1;
+ y1 = y2;
+ y2 = y;
+
+ x = projectLeft;
+ projectLeft = projectRight;
+ projectRight = x;
+
+ tface = leftFace;
+ leftFace = rightFace;
+ rightFace = tface;
+ }
+
+ dy = y2 - y1;
+ signdx = 1;
+ dx = x2 - x1;
+ if (dx < 0)
+ signdx = -1;
+
+ leftFace->x = x1;
+ leftFace->y = y1;
+ leftFace->dx = dx;
+ leftFace->dy = dy;
+
+ rightFace->x = x2;
+ rightFace->y = y2;
+ rightFace->dx = -dx;
+ rightFace->dy = -dy;
+
+ if (!dy) {
+ rightFace->xa = 0;
+ rightFace->ya = (double) lw / 2.0;
+ rightFace->k = -(double) (lw * dx) / 2.0;
+ leftFace->xa = 0;
+ leftFace->ya = -rightFace->ya;
+ leftFace->k = rightFace->k;
+ x = x1;
+ if (projectLeft)
+ x -= (lw >> 1);
+ y = y1 - (lw >> 1);
+ dx = x2 - x;
+ if (projectRight)
+ dx += (lw + 1 >> 1);
+ dy = lw;
+ if(pGC->miTranslate) {
+ x += pDrawable->x;
+ y += pDrawable->y;
+ }
+ CreatorFillRectHelper(pFfb, x, y, dx, dy);
+ } else if (!dx) {
+ leftFace->xa = (double) lw / 2.0;
+ leftFace->ya = 0;
+ leftFace->k = (double) (lw * dy) / 2.0;
+ rightFace->xa = -leftFace->xa;
+ rightFace->ya = 0;
+ rightFace->k = leftFace->k;
+ y = y1;
+ if (projectLeft)
+ y -= lw >> 1;
+ x = x1 - (lw >> 1);
+ dy = y2 - y;
+ if (projectRight)
+ dy += (lw + 1 >> 1);
+ dx = lw;
+ if(pGC->miTranslate) {
+ x += pDrawable->x;
+ y += pDrawable->y;
+ }
+ CreatorFillRectHelper(pFfb, x, y, dx, dy);
+ } else {
+ l = ((double) lw) / 2.0;
+ L = sqrt((double)(dx*dx + dy*dy));
+
+ if (dx < 0) {
+ right = &rights[1];
+ left = &lefts[0];
+ top = &rights[0];
+ bottom = &lefts[1];
+ } else {
+ right = &rights[0];
+ left = &lefts[1];
+ top = &lefts[0];
+ bottom = &rights[1];
+ }
+ r = l / L;
+
+ /* coord of upper bound at integral y */
+ ya = -r * dx;
+ xa = r * dy;
+
+ if (projectLeft | projectRight) {
+ projectXoff = -ya;
+ projectYoff = xa;
+ }
+
+ /* xa * dy - ya * dx */
+ k = l * L;
+
+ leftFace->xa = xa;
+ leftFace->ya = ya;
+ leftFace->k = k;
+ rightFace->xa = -xa;
+ rightFace->ya = -ya;
+ rightFace->k = k;
+
+ if (projectLeft)
+ righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
+ k, dx, dy, x1, y1, 0, right);
+ else
+ righty = miPolyBuildEdge (xa, ya,
+ k, dx, dy, x1, y1, 0, right);
+
+ /* coord of lower bound at integral y */
+ ya = -ya;
+ xa = -xa;
+
+ /* xa * dy - ya * dx */
+ k = - k;
+
+ if (projectLeft)
+ lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
+ k, dx, dy, x1, y1, 1, left);
+ else
+ lefty = miPolyBuildEdge (xa, ya,
+ k, dx, dy, x1, y1, 1, left);
+
+ /* coord of top face at integral y */
+ if (signdx > 0) {
+ ya = -ya;
+ xa = -xa;
+ }
+
+ if (projectLeft) {
+ double xap = xa - projectXoff;
+ double yap = ya - projectYoff;
+ topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
+ -dy, dx, x1, y1, dx > 0, top);
+ }
+ else
+ topy = miPolyBuildEdge(xa, ya, 0.0,
+ -dy, dx, x1, y1, dx > 0, top);
+
+ /* coord of bottom face at integral y */
+ if (projectRight) {
+ double xap = xa + projectXoff;
+ double yap = ya + projectYoff;
+ bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
+ -dy, dx, x2, y2, dx < 0, bottom);
+ maxy = -ya + projectYoff;
+ } else {
+ bottomy = miPolyBuildEdge (xa, ya, 0.0,
+ -dy, dx, x2, y2, dx < 0, bottom);
+ maxy = -ya;
+ }
+
+ finaly = ICEIL (maxy) + y2;
+
+ if (dx < 0) {
+ left->height = bottomy - lefty;
+ right->height = finaly - righty;
+ top->height = righty - topy;
+ } else {
+ right->height = bottomy - righty;
+ left->height = finaly - lefty;
+ top->height = lefty - topy;
+ }
+ bottom->height = finaly - bottomy;
+ CreatorFillPolyHelper (pDrawable, pGC, topy,
+ bottom->height + bottomy - topy, lefts, rights, 2, 2);
+ }
+}
+
+static void
+CreatorLineArcI (DrawablePtr pDraw, GCPtr pGC, int xorg, int yorg)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDraw->pScreen);
+ int x, y, e, ex, slw;
+
+ if (pGC->miTranslate) {
+ xorg += pDraw->x;
+ yorg += pDraw->y;
+ }
+
+ slw = pGC->lineWidth;
+ if (slw == 1) {
+ CreatorPointHelper(pFfb, xorg, yorg);
+ return;
+ }
+
+ y = (slw >> 1) + 1;
+ if (slw & 1)
+ e = - ((y << 2) + 3);
+ else
+ e = - (y << 3);
+ ex = -4;
+ x = 0;
+ while (y) {
+ e += (y << 3) - 4;
+ while (e >= 0) {
+ x++;
+ e += (ex = -((x << 3) + 4));
+ }
+ y--;
+ slw = (x << 1) + 1;
+ if ((e == ex) && (slw > 1))
+ slw--;
+
+ if(Y_IN_BOX(yorg - y))
+ CreatorSpanHelper(pFfb, xorg - x, yorg - y, slw);
+
+ if ((y != 0) && ((slw > 1) || (e != ex)) && Y_IN_BOX(yorg + y))
+ CreatorSpanHelper(pFfb, xorg - x, yorg + y, slw);
+ }
+}
+
+static void
+CreatorLineArcD (DrawablePtr pDraw, GCPtr pGC,
+ double xorg, double yorg,
+ PolyEdgePtr edge1, int edgey1, Bool edgeleft1,
+ PolyEdgePtr edge2, int edgey2, Bool edgeleft2)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDraw->pScreen);
+ double radius, x0, y0, el, er, yk, xlk, xrk, k;
+ int xbase, ybase, y, boty, xl, xr, xcl, xcr, ymin, ymax, ymin1, ymin2;
+ Bool edge1IsMin, edge2IsMin;
+
+ xbase = floor(xorg);
+ x0 = xorg - xbase;
+ ybase = ICEIL (yorg);
+ y0 = yorg - ybase;
+ if (pGC->miTranslate) {
+ xbase += pDraw->x;
+ ybase += pDraw->y;
+ edge1->x += pDraw->x;
+ edge2->x += pDraw->x;
+ edgey1 += pDraw->y;
+ edgey2 += pDraw->y;
+ }
+
+ xlk = x0 + x0 + 1.0;
+ xrk = x0 + x0 - 1.0;
+ yk = y0 + y0 - 1.0;
+ radius = ((double)pGC->lineWidth) / 2.0;
+ y = floor(radius - y0 + 1.0);
+ ybase -= y;
+ ymin = ybase;
+ ymax = 65536;
+ edge1IsMin = FALSE;
+ ymin1 = edgey1;
+ if (edge1->dy >= 0) {
+ if (!edge1->dy) {
+ if (edgeleft1)
+ edge1IsMin = TRUE;
+ else
+ ymax = edgey1;
+ edgey1 = 65536;
+ } else if ((edge1->signdx < 0) == edgeleft1)
+ edge1IsMin = TRUE;
+ }
+ edge2IsMin = FALSE;
+ ymin2 = edgey2;
+ if (edge2->dy >= 0) {
+ if (!edge2->dy) {
+ if (edgeleft2)
+ edge2IsMin = TRUE;
+ else
+ ymax = edgey2;
+ edgey2 = 65536;
+ } else if ((edge2->signdx < 0) == edgeleft2)
+ edge2IsMin = TRUE;
+ }
+ if (edge1IsMin) {
+ ymin = ymin1;
+ if (edge2IsMin && (ymin1 > ymin2))
+ ymin = ymin2;
+ } else if (edge2IsMin)
+ ymin = ymin2;
+ el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0);
+ er = el + xrk;
+ xl = 1;
+ xr = 0;
+ if (x0 < 0.5) {
+ xl = 0;
+ el -= xlk;
+ }
+ boty = (y0 < -0.5) ? 1 : 0;
+ if (ybase + y - boty > ymax)
+ boty = ymax - ybase - y;
+ while (y > boty) {
+ k = (y << 1) + yk;
+ er += k;
+ while (er > 0.0) {
+ xr++;
+ er += xrk - (xr << 1);
+ }
+ el += k;
+ while (el >= 0.0) {
+ xl--;
+ el += (xl << 1) - xlk;
+ }
+ y--;
+ ybase++;
+ if (ybase < ymin)
+ continue;
+ xcl = xl + xbase;
+ xcr = xr + xbase;
+ CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
+ CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
+ if((xcr >= xcl) && Y_IN_BOX(ybase))
+ CreatorSpanHelper(pFfb, xcl, ybase, xcr - xcl + 1);
+ }
+ er = xrk - (xr << 1) - er;
+ el = (xl << 1) - xlk - el;
+ boty = floor(-y0 - radius + 1.0);
+ if (ybase + y - boty > ymax)
+ boty = ymax - ybase - y;
+ while (y > boty) {
+ k = (y << 1) + yk;
+ er -= k;
+ while ((er >= 0.0) && (xr >= 0)) {
+ xr--;
+ er += xrk - (xr << 1);
+ }
+ el -= k;
+ while ((el > 0.0) && (xl <= 0)) {
+ xl++;
+ el += (xl << 1) - xlk;
+ }
+ y--;
+ ybase++;
+ if (ybase < ymin)
+ continue;
+ xcl = xl + xbase;
+ xcr = xr + xbase;
+ CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
+ CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
+ if((xcr >= xcl) && Y_IN_BOX(ybase))
+ CreatorSpanHelper(pFfb, xcl, ybase, xcr - xcl + 1);
+ }
+}
+
+
+static void
+CreatorLineArc (DrawablePtr pDraw, GCPtr pGC,
+ LineFacePtr leftFace, LineFacePtr rightFace,
+ double xorg, double yorg,
+ Bool isInt)
+{
+ int xorgi, yorgi, edgey1, edgey2;
+ PolyEdgeRec edge1, edge2;
+ Bool edgeleft1, edgeleft2;
+
+ if (isInt) {
+ xorgi = leftFace ? leftFace->x : rightFace->x;
+ yorgi = leftFace ? leftFace->y : rightFace->y;
+ }
+ edgey1 = 65536;
+ edgey2 = 65536;
+ edge1.x = 0; /* not used, keep memory checkers happy */
+ edge1.dy = -1;
+ edge2.x = 0; /* not used, keep memory checkers happy */
+ edge2.dy = -1;
+ edgeleft1 = FALSE;
+ edgeleft2 = FALSE;
+
+ if ((pGC->lineWidth > 2) &&
+ (pGC->capStyle == CapRound && pGC->joinStyle != JoinRound ||
+ pGC->joinStyle == JoinRound && pGC->capStyle == CapButt)) {
+ if (isInt) {
+ xorg = (double) xorgi;
+ yorg = (double) yorgi;
+ }
+
+ if (leftFace && rightFace) {
+ miRoundJoinClip (leftFace, rightFace, &edge1, &edge2,
+ &edgey1, &edgey2, &edgeleft1, &edgeleft2);
+ } else if (leftFace) {
+ edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1);
+ } else if (rightFace) {
+ edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2);
+ }
+
+ isInt = FALSE;
+ }
+
+ if (isInt)
+ CreatorLineArcI(pDraw, pGC, xorgi, yorgi);
+ else
+ CreatorLineArcD(pDraw, pGC, xorg, yorg,
+ &edge1, edgey1, edgeleft1,
+ &edge2, edgey2, edgeleft2);
+}
+
+static void
+CreatorLineJoin (DrawablePtr pDrawable, GCPtr pGC, LineFacePtr pLeft, LineFacePtr pRight)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ double mx, my, denom;
+ PolyVertexRec vertices[4];
+ PolySlopeRec slopes[4];
+ PolyEdgeRec left[4], right[4];
+ int edgecount, nleft, nright, y, height, swapslopes;
+ int joinStyle = pGC->joinStyle;
+ int lw = pGC->lineWidth;
+
+ if (lw == 1) {
+ /* Lines going in the same direction have no join */
+ if ((pLeft->dx >= 0) == (pRight->dx <= 0))
+ return;
+ if (joinStyle != JoinRound) {
+ denom = - pLeft->dx * (double)pRight->dy + pRight->dx *
+ (double)pLeft->dy;
+ if (denom == 0.0)
+ return; /* no join to draw */
+ }
+ if (joinStyle != JoinMiter) {
+ if(pGC->miTranslate)
+ CreatorPointHelper(pFfb,
+ pLeft->x + pDrawable->x,
+ pLeft->y + pDrawable->y);
+ else
+ CreatorPointHelper(pFfb, pLeft->x, pLeft->y);
+ return;
+ }
+ } else {
+ if (joinStyle == JoinRound) {
+ CreatorLineArc(pDrawable, pGC, pLeft, pRight,
+ (double)0.0, (double)0.0, TRUE);
+ return;
+ }
+ denom = - pLeft->dx * (double)pRight->dy + pRight->dx *
+ (double)pLeft->dy;
+ if (denom == 0.0)
+ return; /* no join to draw */
+ }
+
+ swapslopes = 0;
+ if (denom > 0) {
+ pLeft->xa = -pLeft->xa;
+ pLeft->ya = -pLeft->ya;
+ pLeft->dx = -pLeft->dx;
+ pLeft->dy = -pLeft->dy;
+ } else {
+ swapslopes = 1;
+ pRight->xa = -pRight->xa;
+ pRight->ya = -pRight->ya;
+ pRight->dx = -pRight->dx;
+ pRight->dy = -pRight->dy;
+ }
+
+ vertices[0].x = pRight->xa;
+ vertices[0].y = pRight->ya;
+ slopes[0].dx = -pRight->dy;
+ slopes[0].dy = pRight->dx;
+ slopes[0].k = 0;
+
+ vertices[1].x = 0;
+ vertices[1].y = 0;
+ slopes[1].dx = pLeft->dy;
+ slopes[1].dy = -pLeft->dx;
+ slopes[1].k = 0;
+
+ vertices[2].x = pLeft->xa;
+ vertices[2].y = pLeft->ya;
+
+ if (joinStyle == JoinMiter) {
+ my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) -
+ pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx ))/
+ denom;
+ if (pLeft->dy != 0)
+ mx = pLeft->xa + (my - pLeft->ya) *
+ (double) pLeft->dx / (double) pLeft->dy;
+ else
+ mx = pRight->xa + (my - pRight->ya) *
+ (double) pRight->dx / (double) pRight->dy;
+
+ /* check miter limit */
+ if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw)
+ joinStyle = JoinBevel;
+ }
+
+ if (joinStyle == JoinMiter) {
+ slopes[2].dx = pLeft->dx;
+ slopes[2].dy = pLeft->dy;
+ slopes[2].k = pLeft->k;
+ if (swapslopes) {
+ slopes[2].dx = -slopes[2].dx;
+ slopes[2].dy = -slopes[2].dy;
+ slopes[2].k = -slopes[2].k;
+ }
+ vertices[3].x = mx;
+ vertices[3].y = my;
+ slopes[3].dx = pRight->dx;
+ slopes[3].dy = pRight->dy;
+ slopes[3].k = pRight->k;
+ if (swapslopes) {
+ slopes[3].dx = -slopes[3].dx;
+ slopes[3].dy = -slopes[3].dy;
+ slopes[3].k = -slopes[3].k;
+ }
+ edgecount = 4;
+ } else {
+ double scale, dx, dy, adx, ady;
+
+ adx = dx = pRight->xa - pLeft->xa;
+ ady = dy = pRight->ya - pLeft->ya;
+ if (adx < 0)
+ adx = -adx;
+ if (ady < 0)
+ ady = -ady;
+ scale = ady;
+ if (adx > ady)
+ scale = adx;
+ slopes[2].dx = (dx * 65536) / scale;
+ slopes[2].dy = (dy * 65536) / scale;
+ slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy -
+ (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0;
+ edgecount = 3;
+ }
+
+ y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y,
+ left, right, &nleft, &nright, &height);
+ CreatorFillPolyHelper(pDrawable, pGC, y, height, left, right, nleft, nright);
+}
+
+void
+CreatorWideLineSolid (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr pPts)
+{
+ int x1, y1, x2, y2, first = TRUE;
+ Bool projectLeft, projectRight, somethingDrawn = FALSE, selfJoin = FALSE;
+ LineFaceRec leftFace, rightFace, prevRightFace, firstFace;
+ cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ RegionPtr clip;
+ int numRects;
+ unsigned int ppc;
+ BoxPtr pbox;
+
+ clip = ((cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr))->pCompositeClip;
+ numRects = REGION_NUM_RECTS(clip);
+ if (!numRects)
+ return;
+ if (!(ppc = FFBSetClip(pFfb, ffb, clip, numRects))) {
+ miWideLine(pDrawable, pGC, mode, npt, pPts);
+ return;
+ }
+
+ LeftClip = 2048; TopClip = 2048;
+ RightClip = 0; BottomClip = 0;
+ for (pbox = REGION_RECTS(clip); numRects; numRects--, pbox++) {
+ if (pbox->x1 < LeftClip) LeftClip = pbox->x1;
+ if (pbox->x2 > RightClip) RightClip = pbox->x2 - 1;
+ if (pbox->y1 < TopClip) TopClip = pbox->y1;
+ if (pbox->y2 > BottomClip) BottomClip = pbox->y2 - 1;
+ }
+
+ FFB_WRITE_ATTRIBUTES(pFfb,
+ ppc|FFB_PPC_APE_DISABLE|FFB_PPC_TBE_OPAQUE|
+ FFB_PPC_XS_CONST|FFB_PPC_YS_CONST|FFB_PPC_ZS_CONST|FFB_PPC_CS_CONST,
+ FFB_PPC_VCE_MASK|FFB_PPC_ACE_MASK|FFB_PPC_APE_MASK|FFB_PPC_TBE_MASK|
+ FFB_PPC_XS_MASK|FFB_PPC_YS_MASK|FFB_PPC_ZS_MASK|FFB_PPC_CS_MASK,
+ pGC->planemask,
+ FFB_ROP_EDIT_BIT|pGC->alu,
+ -1, pGC->fgPixel,
+ FFB_FBC_DEFAULT);
+
+ x2 = pPts->x;
+ y2 = pPts->y;
+ if (npt > 1) {
+ if (mode == CoordModePrevious) {
+ int nptTmp;
+ register DDXPointPtr pPtsTmp;
+
+ x1 = x2;
+ y1 = y2;
+ nptTmp = npt;
+ pPtsTmp = pPts + 1;
+ while (--nptTmp) {
+ x1 += pPtsTmp->x;
+ y1 += pPtsTmp->y;
+ ++pPtsTmp;
+ }
+ if ((x2 == x1) && (y2 == y1))
+ selfJoin = TRUE;
+ } else if ((x2 == pPts[npt-1].x) && (y2 == pPts[npt-1].y))
+ selfJoin = TRUE;
+ }
+
+ projectLeft = ((pGC->capStyle == CapProjecting) && !selfJoin);
+ projectRight = FALSE;
+
+ while (--npt) {
+ x1 = x2;
+ y1 = y2;
+ ++pPts;
+ x2 = pPts->x;
+ y2 = pPts->y;
+ if (mode == CoordModePrevious) {
+ x2 += x1;
+ y2 += y1;
+ }
+ if ((x1 != x2) || (y1 != y2)) {
+ somethingDrawn = TRUE;
+ if ((npt == 1) && (pGC->capStyle == CapProjecting) && !selfJoin)
+ projectRight = TRUE;
+ CreatorWideSegment(pDrawable, pGC, x1, y1, x2, y2,
+ projectLeft, projectRight, &leftFace, &rightFace);
+ if (first) {
+ if (selfJoin)
+ firstFace = leftFace;
+ else if (pGC->capStyle == CapRound) {
+ if (pGC->lineWidth == 1) {
+ if(pGC->miTranslate)
+ CreatorPointHelper(pFfb,
+ x1 + pDrawable->x,
+ y1 + pDrawable->y);
+ else
+ CreatorPointHelper(pFfb, x1, y1);
+ } else
+ CreatorLineArc(pDrawable, pGC,
+ &leftFace, (LineFacePtr) NULL,
+ (double)0.0, (double)0.0,
+ TRUE);
+ }
+ } else
+ CreatorLineJoin (pDrawable, pGC, &leftFace, &prevRightFace);
+
+ prevRightFace = rightFace;
+ first = FALSE;
+ projectLeft = FALSE;
+ }
+ if (npt == 1 && somethingDrawn) {
+ if (selfJoin)
+ CreatorLineJoin (pDrawable, pGC, &firstFace, &rightFace);
+ else if (pGC->capStyle == CapRound) {
+ if (pGC->lineWidth == 1) {
+ if(pGC->miTranslate)
+ CreatorPointHelper(pFfb,
+ x2 + pDrawable->x,
+ y2 + pDrawable->y);
+ else
+ CreatorPointHelper(pFfb, x2, y2);
+ } else
+ CreatorLineArc (pDrawable, pGC,
+ (LineFacePtr) NULL, &rightFace,
+ (double)0.0, (double)0.0,
+ TRUE);
+ }
+ }
+ }
+
+ /* handle crock where all points are coincedent */
+ if (!somethingDrawn) {
+ projectLeft = (pGC->capStyle == CapProjecting);
+ CreatorWideSegment (pDrawable, pGC,
+ x2, y2, x2, y2, projectLeft, projectLeft,
+ &leftFace, &rightFace);
+ if (pGC->capStyle == CapRound) {
+ CreatorLineArc (pDrawable, pGC,
+ &leftFace, (LineFacePtr) NULL,
+ (double)0.0, (double)0.0,
+ TRUE);
+ rightFace.dx = -1; /* sleezy hack to make it work */
+ CreatorLineArc (pDrawable, pGC,
+ (LineFacePtr) NULL, &rightFace,
+ (double)0.0, (double)0.0,
+ TRUE);
+ }
+ }
+ pFfb->rp_active = 1;
+}