1
/* This file is part of the GNU libxmi package.
3
Copyright (C) 1985, 1986, 1987, 1988, 1989, X Consortium. For an
4
associated permission notice, see the accompanying file README-X.
6
GNU enhancements Copyright (C) 1998, 1999, 2000, 2005, Free Software
9
The GNU libxmi package is free software. You may redistribute it
10
and/or modify it under the terms of the GNU General Public License as
11
published by the Free Software foundation; either version 2, or (at your
12
option) any later version.
14
The GNU libxmi package is distributed in the hope that it will be
15
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
General Public License for more details.
19
You should have received a copy of the GNU General Public License along
20
with the GNU plotutils package; see the file COPYING. If not, write to
21
the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
22
Boston, MA 02110-1301, USA. */
1
24
#include "sys-defines.h"
26
49
#define hypot(x, y) sqrt((x)*(x) + (y)*(y))
28
51
/* internal functions that do painting of pixels */
29
static void miFillPolyHelper ____P((miPaintedSet *paintedSet, miPixel pixel, int y, unsigned int overall_height, PolyEdge *left, PolyEdge *right, int left_count, int right_count));
30
static void miFillRectPolyHelper ____P((miPaintedSet *paintedSet, miPixel pixel, int x, int y, unsigned int w, unsigned int h));
31
static void miLineArc ____P((miPaintedSet *paintedSet, miPixel pixel, const miGC *pGC, LineFace *leftFace, LineFace *rightFace, double xorg, double yorg, bool isInt));
32
static void miLineJoin ____P((miPaintedSet *paintedSet, miPixel pixel, const miGC *pGC, LineFace *pLeft, LineFace *pRight));
33
static void miLineProjectingCap ____P((miPaintedSet *paintedSet, miPixel pixel, const miGC *pGC, const LineFace *face, bool isLeft, bool isInt));
34
static void miWideDashSegment ____P((miPaintedSet *paintedSet, const miGC *pGC, int *pDashNum, int *pDashIndex, int *pDashOffset, int x1, int y1, int x2, int y2, bool projectLeft, bool projectRight, LineFace *leftFace, LineFace *rightFace));
35
static void miWideSegment ____P((miPaintedSet *paintedSet, miPixel pixel, const miGC *pGC, int x1, int y1, int x2, int y2, bool projectLeft, bool projectRight, LineFace *leftFace, LineFace *rightFace));
52
static void miFillPolyHelper (miPaintedSet *paintedSet, miPixel pixel, int y, unsigned int overall_height, PolyEdge *left, PolyEdge *right, int left_count, int right_count);
53
static void miFillRectPolyHelper (miPaintedSet *paintedSet, miPixel pixel, int x, int y, unsigned int w, unsigned int h);
54
static void miLineArc (miPaintedSet *paintedSet, miPixel pixel, const miGC *pGC, LineFace *leftFace, LineFace *rightFace, double xorg, double yorg, bool isInt);
55
static void miLineJoin (miPaintedSet *paintedSet, miPixel pixel, const miGC *pGC, LineFace *pLeft, LineFace *pRight);
56
static void miLineProjectingCap (miPaintedSet *paintedSet, miPixel pixel, const miGC *pGC, const LineFace *face, bool isLeft, bool isInt);
57
static void miWideDashSegment (miPaintedSet *paintedSet, const miGC *pGC, int *pDashNum, int *pDashIndex, int *pDashOffset, int x1, int y1, int x2, int y2, bool projectLeft, bool projectRight, LineFace *leftFace, LineFace *rightFace);
58
static void miWideSegment (miPaintedSet *paintedSet, miPixel pixel, const miGC *pGC, int x1, int y1, int x2, int y2, bool projectLeft, bool projectRight, LineFace *leftFace, LineFace *rightFace);
37
60
/* internal functions that don't do painting of pixels */
38
static int miLineArcD ____P((const miGC *pGC, double xorg, double yorg, miPoint *points, unsigned int *widths, PolyEdge *edge1, int edgey1, bool edgeleft1, PolyEdge *edge2, int edgey2, bool edgeleft2));
39
static int miLineArcI ____P((const miGC *pGC, int xorg, int yorg, miPoint *points, unsigned int *widths));
40
static int miPolyBuildEdge ____P((double x0, double y0, double k, int dx, int dy, int xi, int yi, bool left, PolyEdge *edge));
41
static int miPolyBuildPoly ____P((const PolyVertex *vertices, const PolySlope *slopes, int count, int xi, int yi, PolyEdge *left, PolyEdge *right, int *pnleft, int *pnright, unsigned int *h));
42
static int miRoundCapClip ____P((const LineFace *face, bool isInt, PolyEdge *edge, bool *leftEdge));
43
static int miRoundJoinFace ____P((const LineFace *face, PolyEdge *edge, bool *leftEdge));
44
static void miRoundJoinClip ____P((LineFace *pLeft, LineFace *pRight, PolyEdge *edge1, PolyEdge *edge2, int *y1, int *y2, bool *left1, bool *left2));
61
static int miLineArcD (const miGC *pGC, double xorg, double yorg, miPoint *points, unsigned int *widths, PolyEdge *edge1, int edgey1, bool edgeleft1, PolyEdge *edge2, int edgey2, bool edgeleft2);
62
static int miLineArcI (const miGC *pGC, int xorg, int yorg, miPoint *points, unsigned int *widths);
63
static int miPolyBuildEdge (double x0, double y0, double k, int dx, int dy, int xi, int yi, bool left, PolyEdge *edge);
64
static int miPolyBuildPoly (const PolyVertex *vertices, const PolySlope *slopes, int count, int xi, int yi, PolyEdge *left, PolyEdge *right, int *pnleft, int *pnright, unsigned int *h);
65
static int miRoundCapClip (const LineFace *face, bool isInt, PolyEdge *edge, bool *leftEdge);
66
static int miRoundJoinFace (const LineFace *face, PolyEdge *edge, bool *leftEdge);
67
static void miRoundJoinClip (LineFace *pLeft, LineFace *pRight, PolyEdge *edge1, PolyEdge *edge2, int *y1, int *y2, bool *left1, bool *left2);
46
69
/* Spans-based convex polygon filler. Paints a convex polygon, supplied as
47
70
lists of `left' and `right' edges. Used for painting polygonal line
168
174
/* The integer edge data that are computed do not include the `height'
169
175
field, i.e. the number of scanlines to process. */
177
/* ARGS: x0,y0 = starting point of edge (rel. to x1,y1)
178
k = x0 * dy - y0 * dx
179
dx,dy specify rational slope dy/dx
180
xi,yi = integer offsets for coor system
181
left = left edge, not right edge?
182
edge = integer edge data, to be filled in */
173
185
miPolyBuildEdge (double x0, double y0, double k, int dx, int dy, int xi, int yi, bool left, PolyEdge *edge)
175
miPolyBuildEdge (x0, y0, k, dx, dy, xi, yi, left, edge)
176
double x0, y0; /* starting point of edge (rel. to (xi,yi)) */
177
double k; /* x0 * dy - y0 * dx */
178
int dx, dy; /* edge has rational slope dy/dx */
179
int xi, yi; /* integer offset for coordinate system */
180
bool left; /* left edge, not right edge? */
181
PolyEdge *edge; /* integer edge data, to be filled in */
1541
1456
dash will be given a round cap if lines are drawn in the rounded cap
1542
1457
style, and a projecting cap if lines are drawn in the projecting cap
1460
/* ARGS: pDashNum = absolute number of dash
1461
pDashIndex = index into array (i.e. dashNum % length)
1462
pDashOffset = offset into selected dash */
1546
1464
miWideDashSegment (miPaintedSet *paintedSet, const miGC *pGC, int *pDashNum, int *pDashIndex, int *pDashOffset, int x1, int y1, int x2, int y2, bool projectLeft, bool projectRight, LineFace *leftFace, LineFace *rightFace)
1548
miWideDashSegment (paintedSet, pGC, pDashNum, pDashIndex, pDashOffset, x1, y1, x2, y2, projectLeft, projectRight, leftFace, rightFace)
1549
miPaintedSet *paintedSet;
1551
int *pDashNum; /* absolute number of dash */
1552
int *pDashIndex; /* index into array (i.e. dashNum % length) */
1553
int *pDashOffset; /* offset into selected dash */
1555
bool projectLeft, projectRight;
1556
LineFace *leftFace, *rightFace;
1559
1466
int dashNum, dashIndex, dashRemain;
1560
1467
unsigned int *pDash;
1960
1867
/* FIXME: a negative offset is not supported, and if it is, then some
1961
1868
places elsewhere in the code, which assume dashNum>=0, may need to be
1871
/* ARGS: dist = add'l offset (assumed >= 0)
1872
pDashNum = dash number
1873
pDashIndex = current dash
1875
numInDashList = dashlist length
1876
pDashOffset = offset into current dash */
1965
1878
miStepDash (int dist, int *pDashNum, int *pDashIndex, const unsigned int *pDash, int numInDashList, int *pDashOffset)
1967
miStepDash (dist, pDashNum, pDashIndex, pDash, numInDashList, pDashOffset)
1968
int dist; /* additional offset (assumed >= 0) */
1969
int *pDashNum; /* dash number */
1970
int *pDashIndex; /* current dash */
1971
const unsigned int *pDash; /* dash list */
1972
int numInDashList; /* dashlist length */
1973
int *pDashOffset; /* offset into current dash */
1976
1880
int dashNum, dashIndex, dashOffset;
2183
2078
round caps. Also pass back left and right faces for the line segment,
2184
2079
for possible use in adding caps or joins. */
2187
2081
miWideSegment (miPaintedSet *paintedSet, miPixel pixel, const miGC *pGC, int x1, int y1, int x2, int y2, bool projectLeft, bool projectRight, LineFace *leftFace, LineFace *rightFace)
2189
miWideSegment (paintedSet, pixel, pGC, x1, y1, x2, y2, projectLeft, projectRight, leftFace, rightFace)
2190
miPaintedSet *paintedSet;
2194
bool projectLeft, projectRight;
2195
LineFace *leftFace, *rightFace;
2200
double projectXoff = 0.0, projectYoff = 0.0;
2206
PolyEdge *left, *right;
2207
PolyEdge *top, *bottom;
2208
int lefty, righty, topy, bottomy;
2210
PolyEdge lefts[2], rights[2];
2211
2086
int lw = (int)(pGC->lineWidth);
2213
2088
if (y2 < y1 || (y2 == y1 && x2 < x1))