diff options
author | keith <empty> | 1989-10-25 15:15:59 +0000 |
---|---|---|
committer | keith <empty> | 1989-10-25 15:15:59 +0000 |
commit | 2fba0e777228430682b844cf4eac972dd6600ba7 (patch) | |
tree | cc8ba873b6b1b272648ded8f0aebda7951bb2f18 /xc/programs | |
parent | 9b025cd1a24467dba3095fc9a6d2f225583643fe (diff) |
Initial revision
Diffstat (limited to 'xc/programs')
-rw-r--r-- | xc/programs/Xserver/mi/miwideline.c | 756 | ||||
-rw-r--r-- | xc/programs/Xserver/mi/miwideline.h | 115 |
2 files changed, 871 insertions, 0 deletions
diff --git a/xc/programs/Xserver/mi/miwideline.c b/xc/programs/Xserver/mi/miwideline.c new file mode 100644 index 000000000..d0a7dfdbd --- /dev/null +++ b/xc/programs/Xserver/mi/miwideline.c @@ -0,0 +1,756 @@ +/* + * $XConsortium: Exp $ + * + * Copyright 1988 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* + * Mostly integer wideline code. Uses a technique similar to + * bresenham zero-width lines, except walks an X edge + */ + +#include <stdio.h> +#include <math.h> +#include "X.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "miscstruct.h" +#include "miwideline.h" + +#ifdef ICEILTEMPDECL +ICEILTEMPDECL +#endif + +/* + * spans-based polygon filler + */ + +void +miFillPolyHelper (pDrawable, pGC, pixel, y, overall_height, + left, right, left_count, right_count) + DrawablePtr pDrawable; + GCPtr pGC; + unsigned long pixel; + int y; /* start y coordinate */ + int overall_height; /* height of entire segment */ + PolyEdgePtr left, right; + int left_count, right_count; +{ + int left_x; + int left_stepx; + int left_signdx; + int left_e, left_dy, left_dx; + + int right_x; + int right_stepx; + int right_signdx; + int right_e, right_dy, right_dx; + + int height; + int left_height, right_height; + + DDXPointPtr ppt, pptInit; + int nspans; + int *pwidth, *pwidthInit; + int oldPixel; + int xorg; + + left_height = 0; + right_height = 0; + + ppt = pptInit = (DDXPointPtr) ALLOCATE_LOCAL (overall_height * sizeof *ppt); + pwidth = pwidthInit = (int *) ALLOCATE_LOCAL (overall_height * sizeof *pwidth); + if (!ppt || !pwidth) + { + DEALLOCATE_LOCAL ((pointer) ppt); + DEALLOCATE_LOCAL ((pointer) pwidth); + return; + } + + oldPixel = pGC->fgPixel; + if (pixel != oldPixel) + { + XID pix; + + pix = pixel; + DoChangeGC (pGC, GCForeground, &pix, FALSE); + } + + if (pGC->miTranslate) + { + y += pDrawable->y; + xorg = pDrawable->x; + } + nspans = 0; + while ((left_count || left_height) && + (right_count || right_height)) + { + MIPOLYRELOADLEFT + MIPOLYRELOADRIGHT + + height = left_height; + if (height > right_height) + height = right_height; + + left_height -= height; + right_height -= height; + + while (height-- > 0) + { + if (right_x >= left_x) + { + ppt->y = y; + ppt->x = left_x + xorg; + ++ppt; + *pwidth = right_x - left_x + 1; + ++pwidth; + ++nspans; + } + y++; + + MIPOLYSTEPLEFT + + MIPOLYSTEPRIGHT + } + } + (*pGC->ops->FillSpans) (pDrawable, pGC, nspans, pptInit, pwidthInit, TRUE); + DEALLOCATE_LOCAL ((pointer) pptInit); + DEALLOCATE_LOCAL ((pointer) pwidthInit); + if (pixel != oldPixel) + { + XID pix; + + pix = oldPixel; + DoChangeGC (pGC, GCForeground, &pix, FALSE); + } +} + +int +miPolyBuildEdge (x0, y0, k, dx, dy, xi, yi, left, edge) + double x0, y0; + double k; /* x0 * dy - y0 * dx */ + int dx, dy; + int xi, yi; + int left; + PolyEdgePtr edge; +{ + int x, y, e; + int signdx; + int xady; + int t; + + if (dy < 0) + { + dy = -dy; + dx = -dx; + k = -k; + } + signdx = 1; + if (dx < 0) + signdx = -1; + + y = ICEIL (y0); + xady = ICEIL (k) + y * dx; + if (left) + { + if (xady <= 0) + x = xady / dy; + else + x = (xady - 1) / dy + 1; + if (dx < 0) + e = x * dy - xady; + else + e = xady - x * dy - 1; + } + else + { + if (xady <= 0) + x = xady / dy - 1; + else + x = (xady - 1) / dy; + if (dx < 0) + e = x * dy - xady - 1; + else + e = xady - x * dy; + } + + if (e < 0) + e += dy; + + edge->stepx = dx / dy; + if ((edge->signdx = signdx) == 1) + edge->dx = dx % dy; + else + edge->dx = (-dx) % dy; + edge->dy = dy; + edge->x = x + xi; + edge->e = e; + return y + yi; +} + +#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr))) + +int +miPolyBuildPoly (vertices, slopes, count, xi, yi, left, right, pnleft, pnright, h) + PolyVertexPtr vertices; + PolySlopePtr slopes; + int count; + int xi, yi; + PolyEdgePtr left, right; + int *pnleft, *pnright; + int *h; +{ + int top, bottom; + double miny, maxy; + int i, j; + int clockwise; + int slopeoff; + int s; + int nleft, nright; + int y, lasty, bottomy, topy; + int idy, jdy; + + /* find the top of the polygon */ + maxy = miny = vertices[0].y; + bottom = top = 0; + for (i = 1; i < count; i++) + { + if (vertices[i].y < miny) + { + top = i; + miny = vertices[i].y; + } + if (vertices[i].y >= maxy) + { + bottom = i; + maxy = vertices[i].y; + } + } + clockwise = 1; + slopeoff = 0; + + i = top; + j = StepAround (top, -1, count); + + if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx) + { + clockwise = -1; + slopeoff = -1; + } + + bottomy = ICEIL (maxy) + yi; + + nright = 0; + + s = StepAround (top, slopeoff, count); + i = top; + while (i != bottom) + { + if (slopes[s].dy != 0) + { + y = miPolyBuildEdge (vertices[i].x, vertices[i].y, + vertices[i].x * slopes[s].dy - + vertices[i].y * slopes[s].dx, + slopes[s].dx, slopes[s].dy, + xi, yi, 0, + &right[nright]); + if (nright != 0) + right[nright-1].height = y - lasty; + else + topy = y; + nright++; + lasty = y; + } + + i = StepAround (i, clockwise, count); + s = StepAround (s, clockwise, count); + } + if (nright != 0) + right[nright-1].height = bottomy - lasty; + + if (slopeoff == 0) + slopeoff = -1; + else + slopeoff = 0; + + nleft = 0; + s = StepAround (top, slopeoff, count); + i = top; + while (i != bottom) + { + if (slopes[s].dy != 0) + { + y = miPolyBuildEdge (vertices[i].x, vertices[i].y, + vertices[i].x * slopes[s].dy - + vertices[i].y * slopes[s].dx, + slopes[s].dx, slopes[s].dy, xi, yi, 1, + &left[nleft]); + + if (nleft != 0) + left[nleft-1].height = y - lasty; + nleft++; + lasty = y; + } + i = StepAround (i, -clockwise, count); + s = StepAround (s, -clockwise, count); + } + if (nleft != 0) + left[nleft-1].height = bottomy - lasty; + *pnleft = nleft; + *pnright = nright; + *h = bottomy - topy; + return topy; +} + +miLineJoin (pDrawable, pGC, pixel, FillPoly, pLeft, pRight) + DrawablePtr pDrawable; + GCPtr pGC; + unsigned long pixel; + void (*FillPoly)(); + LineFacePtr pLeft, pRight; +{ + double mx, my; + int denom; + PolyVertexRec vertices[4]; + PolySlopeRec slopes[4]; + int edgecount; + PolyEdgeRec left[4], right[4]; + int nleft, nright; + int y, height; + int swapslopes; + int joinStyle = pGC->joinStyle; + int lw = pGC->lineWidth; + + denom = - pLeft->dx * pRight->dy + pRight->dx * pLeft->dy; + if (denom == 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; + + vertices[1].x = 0; + vertices[1].y = 0; + slopes[1].dx = pLeft->dy; + slopes[1].dy = -pLeft->dx; + + vertices[2].x = pLeft->xa; + vertices[2].y = pLeft->ya; + + if (joinStyle == JoinMiter) + { + slopes[2].dx = -pLeft->dx; + slopes[2].dy = -pLeft->dy; + + my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) - + pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx )) / + (double) 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; + } + + switch (joinStyle) + { + case JoinRound: + return; + case JoinMiter: + slopes[2].dx = pLeft->dx; + slopes[2].dy = pLeft->dy; + if (swapslopes) + { + slopes[2].dx = -slopes[2].dx; + slopes[2].dy = -slopes[2].dy; + } + vertices[3].x = mx; + vertices[3].y = my; + slopes[3].dx = pRight->dx; + slopes[3].dy = pRight->dy; + if (swapslopes) + { + slopes[3].dx = -slopes[3].dx; + slopes[3].dy = -slopes[3].dy; + } + edgecount = 4; + break; + case JoinBevel: + { + 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; + edgecount = 3; + } + break; + } + + y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y, + left, right, &nleft, &nright, &height); + (*FillPoly) (pDrawable, pGC, pixel, y, height, left, right, nleft, nright); +} + +miLineCapRound (pDrawable, pGC, pixel, face, left) + DrawablePtr pDrawable; + GCPtr pGC; + unsigned long pixel; + LineFacePtr face; + Bool left; +{ +} + +void +miWideSegment (pDrawable, pGC, pixel, FillPoly, + x1, y1, x2, y2, projectLeft, projectRight, leftFace, rightFace) + DrawablePtr pDrawable; + GCPtr pGC; + unsigned long pixel; + void (*FillPoly)(); + int x1, y1, x2, y2; + Bool projectLeft, projectRight; + LineFacePtr leftFace, rightFace; +{ + double l, L, r; + double xa, ya; + double projectXoff, projectYoff; + double k; + int x, y; + int e; + int dx, dy; + PolyEdgeRec left, right; + PolyEdgeRec top, bottom; + int lefty, righty, topy, bottomy; + int signdx; + 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 == 0) + { + leftFace->xa = 0; + leftFace->ya = -(double) lw / 2.0; + rightFace->xa = 0; + rightFace->ya = (double) lw / 2.0; + lefts[0].height = lw; + lefts[0].x = x1; + if (projectLeft) + lefts[0].x -= lw / 2; + lefts[0].stepx = 0; + lefts[0].signdx = 1; + lefts[0].e = 0; + lefts[0].dx = 0; + lefts[0].dy = lw; + rights[0].height = lw; + rights[0].x = x2 - 1; + if (projectRight) + rights[0].x += lw / 2; + rights[0].stepx = 0; + rights[0].signdx = 1; + rights[0].e = 0; + rights[0].dx = 0; + rights[0].dy = lw; + (*FillPoly) (pDrawable, pGC, pixel, y1 - ((lw + 1) / 2), lw, + lefts, rights, 1, 1); + } + else if (dx == 0) + { + leftFace->xa = (double) lw / 2.0; + leftFace->ya = 0; + rightFace->xa = -(double) lw / 2.0; + rightFace->ya = 0; + topy = y1; + bottomy = y1 + dy; + if (projectLeft) + topy -= lw / 2; + if (projectRight) + bottomy += lw/2; + lefts[0].height = bottomy - topy; + lefts[0].x = x1 - ((lw + 1) / 2); + lefts[0].stepx = 0; + lefts[0].signdx = 1; + lefts[0].e = 0; + lefts[0].dx = dx; + lefts[0].dy = dy; + + rights[0].height = bottomy - topy; + rights[0].x = lefts[0].x + (lw-1); + rights[0].stepx = 0; + rights[0].signdx = 1; + rights[0].e = 0; + rights[0].dx = dx; + rights[0].dy = dy; + (*FillPoly) (pDrawable, pGC, pixel, topy, bottomy - topy, lefts, rights, 1, 1); + } + else + { + l = ((double) lw) / 2.0; + L = hypot ((double) dx, (double) dy); + + if (projectLeft) + { + projectXoff = dx / L * l; + projectYoff = dy / L * l; + } + else + { + projectXoff = 0; + projectYoff = 0; + } + + r = l / L; + + /* coord of upper bound at integral y */ + ya = -r * dx; + xa = r * dy; + + /* xa * dy - ya * dx */ + k = l * L; + + leftFace->xa = xa; + leftFace->ya = ya; + rightFace->xa = -xa; + rightFace->ya = -ya; + + righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, + k, dx, dy, x1, y1, 0, &right); + + /* coord of lower bound at integral y */ + ya = -ya; + xa = -xa; + + /* xa * dy - ya * dx */ + k = - k; + + lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, + k, dx, dy, x1, y1, 1, &left); + + /* coord of top face at integral y */ + + ya = -r * dx * signdx; + xa = r * dy * signdx; + + k = 0; + if (projectLeft) + { + k = (xa - projectXoff) * dx + (ya - projectYoff) * dy; + xa -= projectXoff; + ya -= projectYoff; + } + + topy = miPolyBuildEdge (xa, ya, k, -dy, dx, x1, y1, dx > 0, &top); + + /* coord of bottom face at integral y */ + ya = -r * dx * signdx; + xa = r * dy * signdx; + + k = 0; + if (projectRight) + { + projectXoff = dx / L * l; + projectYoff = dy / L * l; + k = (xa + projectXoff) * dx + (ya + projectYoff) * dy; + xa += projectXoff; + ya += projectYoff; + } + + bottomy = miPolyBuildEdge (xa, ya, + k, -dy, dx, x2, y2, dx < 0, &bottom); + + if (dx < 0) + { + left.height = bottomy - lefty; + right.height = bottomy - lefty; + top.height = righty - topy; + bottom.height = righty - topy; + lefts[0] = left; + lefts[1] = bottom; + rights[0] = top; + rights[1] = right; + } + else + { + left.height = bottomy - righty; + right.height = bottomy - righty; + top.height = lefty - topy; + bottom.height = lefty - topy; + lefts[0] = top; + lefts[1] = left; + rights[0] = right; + rights[1] = bottom; + } + (*FillPoly) (pDrawable, pGC, pixel, topy, bottom.height + bottomy, + lefts, rights, 2, 2); + } +} + +miWideLine (pDrawable, pGC, mode, npt, pPts) + DrawablePtr pDrawable; + GCPtr pGC; + int mode; + int npt; + DDXPointPtr pPts; +{ + int x1, y1, x2, y2; + void (*FillPoly)(); + unsigned long pixel; + Bool projectLeft, projectRight, doJoin; + LineFaceRec leftFace, rightFace, prevRightFace; + int first; + + if (npt == 0) + return; + FillPoly = pGC->ops->LineHelper; + pixel = pGC->fgPixel; + x2 = pPts->x; + y2 = pPts->y; + first = TRUE; + doJoin = 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) + continue; + projectLeft = FALSE; + if (first) + { + } + if (npt == 1) + { + if (pGC->capStyle == CapProjecting) + projectRight = TRUE; + } + miWideSegment (pDrawable, pGC, pixel, FillPoly, x1, y1, x2, y2, + projectLeft, projectRight, &leftFace, &rightFace); + if (first) + { + if (pGC->capStyle == CapRound) + miLineCapRound (pDrawable, pGC, pixel, &leftFace, TRUE); + } + else + { + miLineJoin (pDrawable, pGC, pixel, FillPoly, &leftFace, + &prevRightFace); + if (npt == 1 && pGC->capStyle == CapRound) + miLineCapRound (pDrawable, pGC, pixel, &rightFace, FALSE); + } + prevRightFace = rightFace; + first = FALSE; + } +} + +miMiter() +{ +} + +miNotMiter () +{ +} + +miGetPts () +{ +} + +miRoundCap() +{ +} + +miOneSegWide() +{ +} + +miExtendSegment () +{ +} diff --git a/xc/programs/Xserver/mi/miwideline.h b/xc/programs/Xserver/mi/miwideline.h new file mode 100644 index 000000000..5a84030f0 --- /dev/null +++ b/xc/programs/Xserver/mi/miwideline.h @@ -0,0 +1,115 @@ +/* + * $XConsortium: Exp $ + * + * Copyright 1988 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* + * Polygon edge description for integer wide-line routines + */ + +typedef struct _PolyEdge { + int height; /* number of scanlines to process */ + int x; /* starting x coordinate */ + int stepx; /* fixed integral dx */ + int signdx; /* variable dx sign */ + int e; /* initial error term */ + int dy; + int dx; +} PolyEdgeRec, *PolyEdgePtr; + +#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - for 11o miter cutoff */ + +/* + * types for general polygon routines + */ + +typedef struct _PolyVertex { + double x, y; +} PolyVertexRec, *PolyVertexPtr; + +typedef struct _PolySlope { + int dx, dy; +} PolySlopeRec, *PolySlopePtr; + +/* + * Line face description for caps/joins + */ + +typedef struct _LineFace { + double xa, ya; + int dx, dy; + int x, y; +} LineFaceRec, *LineFacePtr; + +/* + * macros for polygon fillers + */ + +#define MIPOLYRELOADLEFT if (!left_height && left_count) { \ + left_height = left->height; \ + left_x = left->x; \ + left_stepx = left->stepx; \ + left_signdx = left->signdx; \ + left_e = left->e; \ + left_dy = left->dy; \ + left_dx = left->dx; \ + --left_count; \ + ++left; \ + } + +#define MIPOLYRELOADRIGHT if (!right_height && right_count) { \ + right_height = right->height; \ + right_x = right->x; \ + right_stepx = right->stepx; \ + right_signdx = right->signdx; \ + right_e = right->e; \ + right_dy = right->dy; \ + right_dx = right->dx; \ + --right_count; \ + ++right; \ + } + +#define MIPOLYSTEPLEFT left_x += left_stepx; \ + left_e += left_dx; \ + if (left_e >= left_dy) \ + { \ + left_x += left_signdx; \ + left_e -= left_dy; \ + } + +#define MIPOLYSTEPRIGHT right_x += right_stepx; \ + right_e += right_dx; \ + if (right_e >= right_dy) \ + { \ + right_x += right_signdx; \ + right_e -= right_dy; \ + } + +#ifdef NOINLINEICEIL +#define ICEIL(x) ((int)ceil(x)) +#else +#ifdef __GNUC__ +static inline int ICEIL(x) + double x; +{ + int _cTmp = x; + return ((x == _cTmp) || (x < 0.0)) ? _cTmp : _cTmp+1; +} +#else +#define ICEIL(x) ((((x) == (_cTmp = (x))) || ((x) < 0.0)) ? _cTmp : _cTmp+1) +#define ICEILTEMPDECL static int _cTmp; +#endif +#endif |