BasicStrokepublic class BasicStroke extends Object implements StrokeThe BasicStroke class specifies a set of rendering attributes for the
outlines of graphics primitives. The BasicStroke attributes describe the
shape of the pen which draws the outline of a Shape and the decorations
applied at the ends and joins of path segments of the Shape. The BasicStroke
has the following rendering attributes:
- line width -the pen width which draws the outlines.
- end caps - indicates the decoration applied to the ends of unclosed
subpaths and dash segments. The BasicStroke defines three different
decorations: CAP_BUTT, CAP_ROUND, and CAP_SQUARE.
- line joins - indicates the decoration applied at the intersection of two
path segments and at the intersection of the endpoints of a subpath. The
BasicStroke defines three decorations: JOIN_BEVEL, JOIN_MITER, and
JOIN_ROUND.
- miter limit - the limit to trim a line join that has a JOIN_MITER
decoration.
- dash attributes - the definition of how to make a dash pattern by
alternating between opaque and transparent sections
|
Fields Summary |
---|
public static final int | CAP_BUTTThe Constant CAP_BUTT indicates the ends of unclosed subpaths and dash
segments have no added decoration. | public static final int | CAP_ROUNDThe Constant CAP_ROUND indicates the ends of unclosed subpaths and dash
segments have a round decoration. | public static final int | CAP_SQUAREThe Constant CAP_SQUARE indicates the ends of unclosed subpaths and dash
segments have a square projection. | public static final int | JOIN_MITERThe Constant JOIN_MITER indicates that path segments are joined by
extending their outside edges until they meet. | public static final int | JOIN_ROUNDThe Constant JOIN_ROUND indicates that path segments are joined by
rounding off the corner at a radius of half the line width. | public static final int | JOIN_BEVELThe Constant JOIN_BEVEL indicates that path segments are joined by
connecting the outer corners of their wide outlines with a straight
segment. | static final int | MAX_LEVELConstants for calculating. | static final double | CURVE_DELTAThe Constant CURVE_DELTA. | static final double | CORNER_ANGLEThe Constant CORNER_ANGLE. | static final double | CORNER_ZEROThe Constant CORNER_ZERO. | static final double | CUBIC_ARCThe Constant CUBIC_ARC. | float | widthStroke width. | int | capStroke cap type. | int | joinStroke join type. | float | miterLimitStroke miter limit. | float[] | dashStroke dashes array. | float | dashPhaseStroke dash phase. | double | curveDeltaThe temporary pre-calculated values. | double | cornerDeltaThe corner delta. | double | zeroDeltaThe zero delta. | double | w2The w2. | double | fmxThe fmy. | double | fmy | double | scxThe smy. | double | scy | double | smx | double | smy | double | mxThe cy. | double | my | double | cx | double | cy | boolean | isMoveThe temporary indicators. | boolean | isFirstThe is first. | boolean | checkMoveThe check move. | BufferedPath | dstThe temporary and destination work paths. | BufferedPath | lp | BufferedPath | rp | BufferedPath | sp | Dasher | dasherStroke dasher class. |
Constructors Summary |
---|
public BasicStroke()Instantiates a new BasicStroke with default width, cap, join, limit, dash
attributes parameters. The default parameters are a solid line of width
1.0, CAP_SQUARE, JOIN_MITER, a miter limit of 10.0, null dash attributes,
and a dash phase of 0.0f.
this(1.0f, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
| public BasicStroke(float width, int cap, int join, float miterLimit, float[] dash, float dashPhase)Instantiates a new BasicStroke with the specified width, caps, joins,
limit, dash attributes, dash phase parameters.
if (width < 0.0f) {
// awt.133=Negative width
throw new IllegalArgumentException(Messages.getString("awt.133")); //$NON-NLS-1$
}
if (cap != CAP_BUTT && cap != CAP_ROUND && cap != CAP_SQUARE) {
// awt.134=Illegal cap
throw new IllegalArgumentException(Messages.getString("awt.134")); //$NON-NLS-1$
}
if (join != JOIN_MITER && join != JOIN_ROUND && join != JOIN_BEVEL) {
// awt.135=Illegal join
throw new IllegalArgumentException(Messages.getString("awt.135")); //$NON-NLS-1$
}
if (join == JOIN_MITER && miterLimit < 1.0f) {
// awt.136=miterLimit less than 1.0f
throw new IllegalArgumentException(Messages.getString("awt.136")); //$NON-NLS-1$
}
if (dash != null) {
if (dashPhase < 0.0f) {
// awt.137=Negative dashPhase
throw new IllegalArgumentException(Messages.getString("awt.137")); //$NON-NLS-1$
}
if (dash.length == 0) {
// awt.138=Zero dash length
throw new IllegalArgumentException(Messages.getString("awt.138")); //$NON-NLS-1$
}
ZERO: {
for (int i = 0; i < dash.length; i++) {
if (dash[i] < 0.0) {
// awt.139=Negative dash[{0}]
throw new IllegalArgumentException(Messages.getString("awt.139", i)); //$NON-NLS-1$
}
if (dash[i] > 0.0) {
break ZERO;
}
}
// awt.13A=All dash lengths zero
throw new IllegalArgumentException(Messages.getString("awt.13A")); //$NON-NLS-1$
}
}
this.width = width;
this.cap = cap;
this.join = join;
this.miterLimit = miterLimit;
this.dash = dash;
this.dashPhase = dashPhase;
| public BasicStroke(float width, int cap, int join, float miterLimit)Instantiates a new BasicStroke with specified width, cap, join, limit and
default dash attributes parameters.
this(width, cap, join, miterLimit, null, 0.0f);
| public BasicStroke(float width, int cap, int join)Instantiates a new BasicStroke with specified width, cap, join and
default limit and dash attributes parameters.
this(width, cap, join, 10.0f, null, 0.0f);
| public BasicStroke(float width)Instantiates a new BasicStroke with specified width and default cap,
join, limit, dash attributes parameters.
this(width, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
|
Methods Summary |
---|
void | addCap(java.awt.BasicStroke$BufferedPath p, double x0, double y0, double x2, double y2)Adds cap to the work path.
double x1 = p.xLast;
double y1 = p.yLast;
double x10 = x1 - x0;
double y10 = y1 - y0;
double x20 = x2 - x0;
double y20 = y2 - y0;
switch (cap) {
case CAP_BUTT:
p.lineTo(x2, y2);
break;
case CAP_ROUND:
double mx = x10 * CUBIC_ARC;
double my = y10 * CUBIC_ARC;
double x3 = x0 + y10;
double y3 = y0 - x10;
x10 *= CUBIC_ARC;
y10 *= CUBIC_ARC;
x20 *= CUBIC_ARC;
y20 *= CUBIC_ARC;
p.cubicTo(x1 + y10, y1 - x10, x3 + mx, y3 + my, x3, y3);
p.cubicTo(x3 - mx, y3 - my, x2 - y20, y2 + x20, x2, y2);
break;
case CAP_SQUARE:
p.lineTo(x1 + y10, y1 - x10);
p.lineTo(x2 - y20, y2 + x20);
p.lineTo(x2, y2);
break;
}
| void | addCubic(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)Adds solid cubic segment to the work path.
double x12 = x1 - x2;
double y12 = y1 - y2;
double x23 = x2 - x3;
double y23 = y2 - y3;
double x34 = x3 - x4;
double y34 = y3 - y4;
double l12 = Math.sqrt(x12 * x12 + y12 * y12);
double l23 = Math.sqrt(x23 * x23 + y23 * y23);
double l34 = Math.sqrt(x34 * x34 + y34 * y34);
// All edges are zero
if (l12 == 0.0 && l23 == 0.0 && l34 == 0.0) {
addLine(x1, y1, x4, y4, false);
return;
}
// One zero edge
if (l12 == 0.0 && l23 == 0.0) {
addLine(x3, y3, x4, y4, false);
return;
}
if (l23 == 0.0 && l34 == 0.0) {
addLine(x1, y1, x2, y2, false);
return;
}
if (l12 == 0.0 && l34 == 0.0) {
addLine(x2, y2, x3, y3, false);
return;
}
double w, mx1, my1, mx4, my4;
boolean onLine;
if (l12 == 0.0) {
w = w2 / l23;
mx1 = y23 * w;
my1 = -x23 * w;
w = w2 / l34;
mx4 = y34 * w;
my4 = -x34 * w;
onLine = -x23 * y34 + y23 * x34 == 0.0; // sin3
} else if (l34 == 0.0) {
w = w2 / l12;
mx1 = y12 * w;
my1 = -x12 * w;
w = w2 / l23;
mx4 = y23 * w;
my4 = -x23 * w;
onLine = -x12 * y23 + y12 * x23 == 0.0; // sin2
} else {
w = w2 / l12;
mx1 = y12 * w;
my1 = -x12 * w;
w = w2 / l34;
mx4 = y34 * w;
my4 = -x34 * w;
if (l23 == 0.0) {
onLine = -x12 * y34 + y12 * x34 == 0.0;
} else {
onLine = -x12 * y34 + y12 * x34 == 0.0 && -x12 * y23 + y12 * x23 == 0.0 && // sin2
-x23 * y34 + y23 * x34 == 0.0; // sin3
}
}
double lx1 = x1 + mx1;
double ly1 = y1 + my1;
double rx1 = x1 - mx1;
double ry1 = y1 - my1;
if (checkMove) {
if (isMove) {
isMove = false;
lp.moveTo(lx1, ly1);
rp.moveTo(rx1, ry1);
} else {
addJoin(lp, x1, y1, lx1, ly1, true);
addJoin(rp, x1, y1, rx1, ry1, false);
}
}
if (onLine) {
if ((x1 == x2 && y1 < y2) || x1 < x2) {
l12 = -l12;
}
if ((x2 == x3 && y2 < y3) || x2 < x3) {
l23 = -l23;
}
if ((x3 == x4 && y3 < y4) || x3 < x4) {
l34 = -l34;
}
double d = l23 * l23 - l12 * l34;
double roots[] = new double[3];
int rc = 0;
if (d == 0.0) {
double t = (l12 - l23) / (l12 + l34 - l23 - l23);
if (0.0 < t && t < 1.0) {
roots[rc++] = t;
}
} else if (d > 0.0) {
d = Math.sqrt(d);
double z = l12 + l34 - l23 - l23;
double t;
t = (l12 - l23 + d) / z;
if (0.0 < t && t < 1.0) {
roots[rc++] = t;
}
t = (l12 - l23 - d) / z;
if (0.0 < t && t < 1.0) {
roots[rc++] = t;
}
}
if (rc > 0) {
// Sort roots
if (rc == 2 && roots[0] > roots[1]) {
double tmp = roots[0];
roots[0] = roots[1];
roots[1] = tmp;
}
roots[rc++] = 1.0;
double ax = -x34 - x12 + x23 + x23;
double ay = -y34 - y12 + y23 + y23;
double bx = 3.0 * (-x23 + x12);
double by = 3.0 * (-y23 + y12);
double cx = 3.0 * (-x12);
double cy = 3.0 * (-y12);
double xPrev = x1;
double yPrev = y1;
for (int i = 0; i < rc; i++) {
double t = roots[i];
double px = t * (t * (t * ax + bx) + cx) + x1;
double py = t * (t * (t * ay + by) + cy) + y1;
double px1 = (xPrev + px) / 2.0;
double py1 = (yPrev + py) / 2.0;
lp.cubicTo(px1 + mx1, py1 + my1, px1 + mx1, py1 + my1, px + mx1, py + my1);
rp.cubicTo(px1 - mx1, py1 - my1, px1 - mx1, py1 - my1, px - mx1, py - my1);
if (i < rc - 1) {
lp.lineTo(px - mx1, py - my1);
rp.lineTo(px + mx1, py + my1);
}
xPrev = px;
yPrev = py;
mx1 = -mx1;
my1 = -my1;
}
} else {
lp.cubicTo(x2 + mx1, y2 + my1, x3 + mx4, y3 + my4, x4 + mx4, y4 + my4);
rp.cubicTo(x2 - mx1, y2 - my1, x3 - mx4, y3 - my4, x4 - mx4, y4 - my4);
}
} else {
addSubCubic(x1, y1, x2, y2, x3, y3, x4, y4, 0);
}
| void | addDashCubic(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)Adds dashed cubic segment to the work path.
double x12 = x1 - x2;
double y12 = y1 - y2;
double x23 = x2 - x3;
double y23 = y2 - y3;
double x34 = x3 - x4;
double y34 = y3 - y4;
double l12 = Math.sqrt(x12 * x12 + y12 * y12);
double l23 = Math.sqrt(x23 * x23 + y23 * y23);
double l34 = Math.sqrt(x34 * x34 + y34 * y34);
// All edges are zero
if (l12 == 0.0 && l23 == 0.0 && l34 == 0.0) {
// NOTHING
return;
}
// One zero edge
if (l12 == 0.0 && l23 == 0.0) {
addDashLine(x3, y3, x4, y4);
return;
}
if (l23 == 0.0 && l34 == 0.0) {
addDashLine(x1, y1, x2, y2);
return;
}
if (l12 == 0.0 && l34 == 0.0) {
addDashLine(x2, y2, x3, y3);
return;
}
double ax = x4 - x1 + 3.0 * (x2 - x3);
double ay = y4 - y1 + 3.0 * (y2 - y3);
double bx = 3.0 * (x1 + x3 - x2 - x2);
double by = 3.0 * (y1 + y3 - y2 - y2);
double cx = 3.0 * (x2 - x1);
double cy = 3.0 * (y2 - y1);
double dx = x1;
double dy = y1;
double px1 = 0.0;
double py1 = 0.0;
double prev = 0.0;
dasher.init(new DashIterator.Cubic(x1, y1, x2, y2, x3, y3, x4, y4));
while (!dasher.eof()) {
double t = dasher.getValue();
scx = t * (t * (t * ax + bx) + cx) + dx;
scy = t * (t * (t * ay + by) + cy) + dy;
if (dasher.isOpen()) {
px1 = scx;
py1 = scy;
double dx1 = t * (t * (ax + ax + ax) + bx + bx) + cx;
double dy1 = t * (t * (ay + ay + ay) + by + by) + cy;
double w = w2 / Math.sqrt(dx1 * dx1 + dy1 * dy1);
double mx1 = -dy1 * w;
double my1 = dx1 * w;
double lx1 = px1 + mx1;
double ly1 = py1 + my1;
double rx1 = px1 - mx1;
double ry1 = py1 - my1;
if (isMove) {
isMove = false;
smx = px1;
smy = py1;
rp.clean();
lp.moveTo(lx1, ly1);
rp.moveTo(rx1, ry1);
} else {
addJoin(lp, x1, y1, lx1, ly1, true);
addJoin(rp, x1, y1, rx1, ry1, false);
}
} else if (dasher.isContinue()) {
double sx1 = x2 - x23 * prev;
double sy1 = y2 - y23 * prev;
double sx2 = x3 - x34 * prev;
double sy2 = y3 - y34 * prev;
double sx3 = sx1 + (sx2 - sx1) * prev;
double sy3 = sy1 + (sy2 - sy1) * prev;
double t2 = (t - prev) / (1 - prev);
double sx4 = sx3 + (sx2 - sx3) * t2;
double sy4 = sy3 + (sy2 - sy3) * t2;
double px4 = scx;
double py4 = scy;
double px2 = px1 + (sx3 - px1) * t2;
double py2 = py1 + (sy3 - py1) * t2;
double px3 = px2 + (sx4 - px2) * t2;
double py3 = py2 + (sy4 - py2) * t2;
addCubic(px1, py1, px2, py2, px3, py3, px4, py4);
if (dasher.isClosed()) {
addCap(lp, px4, py4, rp.xLast, rp.yLast);
lp.combine(rp);
if (isFirst) {
isFirst = false;
fmx = smx;
fmy = smy;
sp = lp;
lp = new BufferedPath();
} else {
addCap(lp, smx, smy, lp.xMove, lp.yMove);
lp.closePath();
}
isMove = true;
}
}
prev = t;
dasher.next();
}
| void | addDashLine(double x1, double y1, double x2, double y2)Adds dashed line segment to the work path.
double x21 = x2 - x1;
double y21 = y2 - y1;
double l21 = Math.sqrt(x21 * x21 + y21 * y21);
if (l21 == 0.0) {
return;
}
double px1, py1;
px1 = py1 = 0.0;
double w = w2 / l21;
double mx = -y21 * w;
double my = x21 * w;
dasher.init(new DashIterator.Line(l21));
while (!dasher.eof()) {
double t = dasher.getValue();
scx = x1 + t * x21;
scy = y1 + t * y21;
if (dasher.isOpen()) {
px1 = scx;
py1 = scy;
double lx1 = px1 + mx;
double ly1 = py1 + my;
double rx1 = px1 - mx;
double ry1 = py1 - my;
if (isMove) {
isMove = false;
smx = px1;
smy = py1;
rp.clean();
lp.moveTo(lx1, ly1);
rp.moveTo(rx1, ry1);
} else {
addJoin(lp, x1, y1, lx1, ly1, true);
addJoin(rp, x1, y1, rx1, ry1, false);
}
} else if (dasher.isContinue()) {
double px2 = scx;
double py2 = scy;
lp.lineTo(px2 + mx, py2 + my);
rp.lineTo(px2 - mx, py2 - my);
if (dasher.close) {
addCap(lp, px2, py2, rp.xLast, rp.yLast);
lp.combine(rp);
if (isFirst) {
isFirst = false;
fmx = smx;
fmy = smy;
sp = lp;
lp = new BufferedPath();
} else {
addCap(lp, smx, smy, lp.xMove, lp.yMove);
lp.closePath();
}
isMove = true;
}
}
dasher.next();
}
| void | addDashQuad(double x1, double y1, double x2, double y2, double x3, double y3)Adds dashed quad segment to the work path.
double x21 = x2 - x1;
double y21 = y2 - y1;
double x23 = x2 - x3;
double y23 = y2 - y3;
double l21 = Math.sqrt(x21 * x21 + y21 * y21);
double l23 = Math.sqrt(x23 * x23 + y23 * y23);
if (l21 == 0.0 && l23 == 0.0) {
return;
}
if (l21 == 0.0) {
addDashLine(x2, y2, x3, y3);
return;
}
if (l23 == 0.0) {
addDashLine(x1, y1, x2, y2);
return;
}
double ax = x1 + x3 - x2 - x2;
double ay = y1 + y3 - y2 - y2;
double bx = x2 - x1;
double by = y2 - y1;
double cx = x1;
double cy = y1;
double px1, py1, dx1, dy1;
px1 = py1 = dx1 = dy1 = 0.0;
double prev = 0.0;
dasher.init(new DashIterator.Quad(x1, y1, x2, y2, x3, y3));
while (!dasher.eof()) {
double t = dasher.getValue();
double dx = t * ax + bx;
double dy = t * ay + by;
scx = t * (dx + bx) + cx; // t^2 * ax + 2.0 * t * bx + cx
scy = t * (dy + by) + cy; // t^2 * ay + 2.0 * t * by + cy
if (dasher.isOpen()) {
px1 = scx;
py1 = scy;
dx1 = dx;
dy1 = dy;
double w = w2 / Math.sqrt(dx1 * dx1 + dy1 * dy1);
double mx1 = -dy1 * w;
double my1 = dx1 * w;
double lx1 = px1 + mx1;
double ly1 = py1 + my1;
double rx1 = px1 - mx1;
double ry1 = py1 - my1;
if (isMove) {
isMove = false;
smx = px1;
smy = py1;
rp.clean();
lp.moveTo(lx1, ly1);
rp.moveTo(rx1, ry1);
} else {
addJoin(lp, x1, y1, lx1, ly1, true);
addJoin(rp, x1, y1, rx1, ry1, false);
}
} else if (dasher.isContinue()) {
double px3 = scx;
double py3 = scy;
double sx = x2 - x23 * prev;
double sy = y2 - y23 * prev;
double t2 = (t - prev) / (1 - prev);
double px2 = px1 + (sx - px1) * t2;
double py2 = py1 + (sy - py1) * t2;
addQuad(px1, py1, px2, py2, px3, py3);
if (dasher.isClosed()) {
addCap(lp, px3, py3, rp.xLast, rp.yLast);
lp.combine(rp);
if (isFirst) {
isFirst = false;
fmx = smx;
fmy = smy;
sp = lp;
lp = new BufferedPath();
} else {
addCap(lp, smx, smy, lp.xMove, lp.yMove);
lp.closePath();
}
isMove = true;
}
}
prev = t;
dasher.next();
}
| void | addJoin(java.awt.BasicStroke$BufferedPath p, double x0, double y0, double x2, double y2, boolean isLeft)Adds bevel and miter join to the work path.
double x1 = p.xLast;
double y1 = p.yLast;
double x10 = x1 - x0;
double y10 = y1 - y0;
double x20 = x2 - x0;
double y20 = y2 - y0;
double sin0 = x10 * y20 - y10 * x20;
// Small corner
if (-cornerDelta < sin0 && sin0 < cornerDelta) {
double cos0 = x10 * x20 + y10 * y20;
if (cos0 > 0.0) {
// if zero corner do nothing
if (-zeroDelta > sin0 || sin0 > zeroDelta) {
double x3 = x0 + w2 * w2 * (y20 - y10) / sin0;
double y3 = y0 + w2 * w2 * (x10 - x20) / sin0;
p.setLast(x3, y3);
}
return;
}
// Zero corner
if (-zeroDelta < sin0 && sin0 < zeroDelta) {
p.lineTo(x2, y2);
}
return;
}
if (isLeft ^ (sin0 < 0.0)) {
// Twisted corner
p.lineTo(x0, y0);
p.lineTo(x2, y2);
} else {
switch (join) {
case JOIN_BEVEL:
p.lineTo(x2, y2);
break;
case JOIN_MITER:
double s1 = x1 * x10 + y1 * y10;
double s2 = x2 * x20 + y2 * y20;
double x3 = (s1 * y20 - s2 * y10) / sin0;
double y3 = (s2 * x10 - s1 * x20) / sin0;
double x30 = x3 - x0;
double y30 = y3 - y0;
double miterLength = Math.sqrt(x30 * x30 + y30 * y30);
if (miterLength < miterLimit * w2) {
p.lineTo(x3, y3);
}
p.lineTo(x2, y2);
break;
case JOIN_ROUND:
addRoundJoin(p, x0, y0, x2, y2, isLeft);
break;
}
}
| void | addLine(double x1, double y1, double x2, double y2, boolean zero)Adds solid line segment to the work path.
double dx = x2 - x1;
double dy = y2 - y1;
if (dx == 0.0 && dy == 0.0) {
if (!zero) {
return;
}
dx = w2;
dy = 0;
} else {
double w = w2 / Math.sqrt(dx * dx + dy * dy);
dx *= w;
dy *= w;
}
double lx1 = x1 - dy;
double ly1 = y1 + dx;
double rx1 = x1 + dy;
double ry1 = y1 - dx;
if (checkMove) {
if (isMove) {
isMove = false;
lp.moveTo(lx1, ly1);
rp.moveTo(rx1, ry1);
} else {
addJoin(lp, x1, y1, lx1, ly1, true);
addJoin(rp, x1, y1, rx1, ry1, false);
}
}
lp.lineTo(x2 - dy, y2 + dx);
rp.lineTo(x2 + dy, y2 - dx);
| void | addQuad(double x1, double y1, double x2, double y2, double x3, double y3)Adds solid quad segment to the work path.
double x21 = x2 - x1;
double y21 = y2 - y1;
double x23 = x2 - x3;
double y23 = y2 - y3;
double l21 = Math.sqrt(x21 * x21 + y21 * y21);
double l23 = Math.sqrt(x23 * x23 + y23 * y23);
if (l21 == 0.0 && l23 == 0.0) {
addLine(x1, y1, x3, y3, false);
return;
}
if (l21 == 0.0) {
addLine(x2, y2, x3, y3, false);
return;
}
if (l23 == 0.0) {
addLine(x1, y1, x2, y2, false);
return;
}
double w;
w = w2 / l21;
double mx1 = -y21 * w;
double my1 = x21 * w;
w = w2 / l23;
double mx3 = y23 * w;
double my3 = -x23 * w;
double lx1 = x1 + mx1;
double ly1 = y1 + my1;
double rx1 = x1 - mx1;
double ry1 = y1 - my1;
if (checkMove) {
if (isMove) {
isMove = false;
lp.moveTo(lx1, ly1);
rp.moveTo(rx1, ry1);
} else {
addJoin(lp, x1, y1, lx1, ly1, true);
addJoin(rp, x1, y1, rx1, ry1, false);
}
}
if (x21 * y23 - y21 * x23 == 0.0) {
// On line curve
if (x21 * x23 + y21 * y23 > 0.0) {
// Twisted curve
if (l21 == l23) {
double px = x1 + (x21 + x23) / 4.0;
double py = y1 + (y21 + y23) / 4.0;
lp.lineTo(px + mx1, py + my1);
rp.lineTo(px - mx1, py - my1);
lp.lineTo(px - mx1, py - my1);
rp.lineTo(px + mx1, py + my1);
lp.lineTo(x3 - mx1, y3 - my1);
rp.lineTo(x3 + mx1, y3 + my1);
} else {
double px1, py1;
double k = l21 / (l21 + l23);
double px = x1 + (x21 + x23) * k * k;
double py = y1 + (y21 + y23) * k * k;
px1 = (x1 + px) / 2.0;
py1 = (y1 + py) / 2.0;
lp.quadTo(px1 + mx1, py1 + my1, px + mx1, py + my1);
rp.quadTo(px1 - mx1, py1 - my1, px - mx1, py - my1);
lp.lineTo(px - mx1, py - my1);
rp.lineTo(px + mx1, py + my1);
px1 = (x3 + px) / 2.0;
py1 = (y3 + py) / 2.0;
lp.quadTo(px1 - mx1, py1 - my1, x3 - mx1, y3 - my1);
rp.quadTo(px1 + mx1, py1 + my1, x3 + mx1, y3 + my1);
}
} else {
// Simple curve
lp.quadTo(x2 + mx1, y2 + my1, x3 + mx3, y3 + my3);
rp.quadTo(x2 - mx1, y2 - my1, x3 - mx3, y3 - my3);
}
} else {
addSubQuad(x1, y1, x2, y2, x3, y3, 0);
}
| void | addRoundJoin(java.awt.BasicStroke$BufferedPath p, double x0, double y0, double x2, double y2, boolean isLeft)Adds round join to the work path.
double x1 = p.xLast;
double y1 = p.yLast;
double x10 = x1 - x0;
double y10 = y1 - y0;
double x20 = x2 - x0;
double y20 = y2 - y0;
double x30 = x10 + x20;
double y30 = y10 + y20;
double l30 = Math.sqrt(x30 * x30 + y30 * y30);
if (l30 < 1E-5) {
p.lineTo(x2, y2);
return;
}
double w = w2 / l30;
x30 *= w;
y30 *= w;
double x3 = x0 + x30;
double y3 = y0 + y30;
double cos = x10 * x20 + y10 * y20;
double a = Math.acos(cos / (w2 * w2));
if (cos >= 0.0) {
double k = 4.0 / 3.0 * Math.tan(a / 4.0);
if (isLeft) {
k = -k;
}
x10 *= k;
y10 *= k;
x20 *= k;
y20 *= k;
p.cubicTo(x1 - y10, y1 + x10, x2 + y20, y2 - x20, x2, y2);
} else {
double k = 4.0 / 3.0 * Math.tan(a / 8.0);
if (isLeft) {
k = -k;
}
x10 *= k;
y10 *= k;
x20 *= k;
y20 *= k;
x30 *= k;
y30 *= k;
p.cubicTo(x1 - y10, y1 + x10, x3 + y30, y3 - x30, x3, y3);
p.cubicTo(x3 - y30, y3 + x30, x2 + y20, y2 - x20, x2, y2);
}
| void | addSubCubic(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, int level)Subdivides solid cubic curve to make outline for source quad segment and
adds it to work path.
double x12 = x1 - x2;
double y12 = y1 - y2;
double x23 = x2 - x3;
double y23 = y2 - y3;
double x34 = x3 - x4;
double y34 = y3 - y4;
double cos2 = -x12 * x23 - y12 * y23;
double cos3 = -x23 * x34 - y23 * y34;
double sin2 = -x12 * y23 + y12 * x23;
double sin3 = -x23 * y34 + y23 * x34;
double sin0 = -x12 * y34 + y12 * x34;
double cos0 = -x12 * x34 - y12 * y34;
if (level < MAX_LEVEL
&& (sin2 != 0.0 || sin3 != 0.0 || sin0 != 0.0)
&& (cos2 >= 0.0 || cos3 >= 0.0 || cos0 >= 0.0
|| (Math.abs(sin2 / cos2) > curveDelta)
|| (Math.abs(sin3 / cos3) > curveDelta) || (Math.abs(sin0 / cos0) > curveDelta))) {
double cx = (x2 + x3) / 2.0;
double cy = (y2 + y3) / 2.0;
double lx2 = (x2 + x1) / 2.0;
double ly2 = (y2 + y1) / 2.0;
double rx3 = (x3 + x4) / 2.0;
double ry3 = (y3 + y4) / 2.0;
double lx3 = (cx + lx2) / 2.0;
double ly3 = (cy + ly2) / 2.0;
double rx2 = (cx + rx3) / 2.0;
double ry2 = (cy + ry3) / 2.0;
cx = (lx3 + rx2) / 2.0;
cy = (ly3 + ry2) / 2.0;
addSubCubic(x1, y1, lx2, ly2, lx3, ly3, cx, cy, level + 1);
addSubCubic(cx, cy, rx2, ry2, rx3, ry3, x4, y4, level + 1);
} else {
double w, mx1, my1, mx2, my2, mx3, my3, mx4, my4;
double l12 = Math.sqrt(x12 * x12 + y12 * y12);
double l23 = Math.sqrt(x23 * x23 + y23 * y23);
double l34 = Math.sqrt(x34 * x34 + y34 * y34);
if (l12 == 0.0) {
w = w2 / l23;
mx1 = y23 * w;
my1 = -x23 * w;
w = w2 / l34;
mx4 = y34 * w;
my4 = -x34 * w;
} else if (l34 == 0.0) {
w = w2 / l12;
mx1 = y12 * w;
my1 = -x12 * w;
w = w2 / l23;
mx4 = y23 * w;
my4 = -x23 * w;
} else {
// Common case
w = w2 / l12;
mx1 = y12 * w;
my1 = -x12 * w;
w = w2 / l34;
mx4 = y34 * w;
my4 = -x34 * w;
}
if (sin2 == 0.0) {
mx2 = mx1;
my2 = my1;
} else {
w = w2 / sin2;
mx2 = -(x12 * l23 - x23 * l12) * w;
my2 = -(y12 * l23 - y23 * l12) * w;
}
if (sin3 == 0.0) {
mx3 = mx4;
my3 = my4;
} else {
w = w2 / sin3;
mx3 = -(x23 * l34 - x34 * l23) * w;
my3 = -(y23 * l34 - y34 * l23) * w;
}
lp.cubicTo(x2 + mx2, y2 + my2, x3 + mx3, y3 + my3, x4 + mx4, y4 + my4);
rp.cubicTo(x2 - mx2, y2 - my2, x3 - mx3, y3 - my3, x4 - mx4, y4 - my4);
}
| void | addSubQuad(double x1, double y1, double x2, double y2, double x3, double y3, int level)Subdivides solid quad curve to make outline for source quad segment and
adds it to work path.
double x21 = x2 - x1;
double y21 = y2 - y1;
double x23 = x2 - x3;
double y23 = y2 - y3;
double cos = x21 * x23 + y21 * y23;
double sin = x21 * y23 - y21 * x23;
if (level < MAX_LEVEL && (cos >= 0.0 || (Math.abs(sin / cos) > curveDelta))) {
double c1x = (x2 + x1) / 2.0;
double c1y = (y2 + y1) / 2.0;
double c2x = (x2 + x3) / 2.0;
double c2y = (y2 + y3) / 2.0;
double c3x = (c1x + c2x) / 2.0;
double c3y = (c1y + c2y) / 2.0;
addSubQuad(x1, y1, c1x, c1y, c3x, c3y, level + 1);
addSubQuad(c3x, c3y, c2x, c2y, x3, y3, level + 1);
} else {
double w;
double l21 = Math.sqrt(x21 * x21 + y21 * y21);
double l23 = Math.sqrt(x23 * x23 + y23 * y23);
w = w2 / sin;
double mx2 = (x21 * l23 + x23 * l21) * w;
double my2 = (y21 * l23 + y23 * l21) * w;
w = w2 / l23;
double mx3 = y23 * w;
double my3 = -x23 * w;
lp.quadTo(x2 + mx2, y2 + my2, x3 + mx3, y3 + my3);
rp.quadTo(x2 - mx2, y2 - my2, x3 - mx3, y3 - my3);
}
| void | closeDashedShape()Closes dashed shape path.
// Add head segment
if (sp != null) {
addCap(sp, fmx, fmy, sp.xMove, sp.yMove);
sp.closePath();
dst.append(sp);
}
if (lp.typeSize > 0) {
// Close current segment
if (!dasher.isClosed()) {
addCap(lp, scx, scy, rp.xLast, rp.yLast);
lp.combine(rp);
addCap(lp, smx, smy, lp.xMove, lp.yMove);
lp.closePath();
}
dst.append(lp);
}
| void | closeSolidShape()Closes solid shape path.
addCap(lp, cx, cy, rp.xLast, rp.yLast);
lp.combine(rp);
addCap(lp, mx, my, lp.xMove, lp.yMove);
lp.closePath();
| void | createDashedShape(java.awt.geom.PathIterator p)Generates dashed stroked shape.
double coords[] = new double[6];
mx = my = cx = cy = 0.0;
smx = smy = scx = scy = 0.0;
isMove = false;
checkMove = false;
boolean isClosed = true;
while (!p.isDone()) {
switch (p.currentSegment(coords)) {
case PathIterator.SEG_MOVETO:
if (!isClosed) {
closeDashedShape();
}
dasher = new Dasher(dash, dashPhase);
lp.clean();
rp.clean();
sp = null;
isFirst = true;
isMove = true;
isClosed = false;
mx = cx = coords[0];
my = cy = coords[1];
break;
case PathIterator.SEG_LINETO:
addDashLine(cx, cy, cx = coords[0], cy = coords[1]);
break;
case PathIterator.SEG_QUADTO:
addDashQuad(cx, cy, coords[0], coords[1], cx = coords[2], cy = coords[3]);
break;
case PathIterator.SEG_CUBICTO:
addDashCubic(cx, cy, coords[0], coords[1], coords[2], coords[3],
cx = coords[4], cy = coords[5]);
break;
case PathIterator.SEG_CLOSE:
addDashLine(cx, cy, cx = mx, cy = my);
if (dasher.isConnected()) {
// Connect current and head segments
addJoin(lp, fmx, fmy, sp.xMove, sp.yMove, true);
lp.join(sp);
addJoin(lp, fmx, fmy, rp.xLast, rp.yLast, true);
lp.combine(rp);
addCap(lp, smx, smy, lp.xMove, lp.yMove);
lp.closePath();
dst.append(lp);
sp = null;
} else {
closeDashedShape();
}
isClosed = true;
break;
}
p.next();
}
if (!isClosed) {
closeDashedShape();
}
| void | createSolidShape(java.awt.geom.PathIterator p)Generates a shape with a solid (not dashed) outline.
double coords[] = new double[6];
mx = my = cx = cy = 0.0;
isMove = false;
isFirst = false;
checkMove = true;
boolean isClosed = true;
while (!p.isDone()) {
switch (p.currentSegment(coords)) {
case PathIterator.SEG_MOVETO:
if (!isClosed) {
closeSolidShape();
}
rp.clean();
mx = cx = coords[0];
my = cy = coords[1];
isMove = true;
isClosed = false;
break;
case PathIterator.SEG_LINETO:
addLine(cx, cy, cx = coords[0], cy = coords[1], true);
break;
case PathIterator.SEG_QUADTO:
addQuad(cx, cy, coords[0], coords[1], cx = coords[2], cy = coords[3]);
break;
case PathIterator.SEG_CUBICTO:
addCubic(cx, cy, coords[0], coords[1], coords[2], coords[3], cx = coords[4],
cy = coords[5]);
break;
case PathIterator.SEG_CLOSE:
addLine(cx, cy, mx, my, false);
addJoin(lp, mx, my, lp.xMove, lp.yMove, true);
addJoin(rp, mx, my, rp.xMove, rp.yMove, false);
lp.closePath();
rp.closePath();
lp.appendReverse(rp);
isClosed = true;
break;
}
p.next();
}
if (!isClosed) {
closeSolidShape();
}
dst = lp;
| public java.awt.Shape | createStrokedShape(java.awt.Shape s)Creates a Shape from the outline of the specified shape drawn with this
BasicStroke.
w2 = width / 2.0;
curveDelta = getCurveDelta(w2);
cornerDelta = getCornerDelta(w2);
zeroDelta = getZeroDelta(w2);
dst = new BufferedPath();
lp = new BufferedPath();
rp = new BufferedPath();
if (dash == null) {
createSolidShape(s.getPathIterator(null));
} else {
createDashedShape(s.getPathIterator(null));
}
return dst.createGeneralPath();
| public boolean | equals(java.lang.Object obj)Compares this BasicStroke object with the specified Object.
if (obj == this) {
return true;
}
if (obj instanceof BasicStroke) {
BasicStroke bs = (BasicStroke)obj;
return bs.width == width && bs.cap == cap && bs.join == join
&& bs.miterLimit == miterLimit && bs.dashPhase == dashPhase
&& java.util.Arrays.equals(bs.dash, dash);
}
return false;
| double | getCornerDelta(double width)Calculates the value to detect a small angle.
return width * width * Math.sin(Math.PI * CORNER_ANGLE / 180.0);
| double | getCurveDelta(double width)Calculates allowable curve derivation.
double a = width + CURVE_DELTA;
double cos = 1.0 - 2.0 * width * width / (a * a);
double sin = Math.sqrt(1.0 - cos * cos);
return Math.abs(sin / cos);
| public float[] | getDashArray()Gets the dash attributes array of the BasicStroke.
return dash;
| public float | getDashPhase()Gets the dash phase of the BasicStroke.
return dashPhase;
| public int | getEndCap()Gets the end cap style of the BasicStroke.
return cap;
| public int | getLineJoin()Gets the line join style of the BasicStroke.
return join;
| public float | getLineWidth()Gets the line width of the BasicStroke.
return width;
| public float | getMiterLimit()Gets the miter limit of the BasicStroke (the limit to trim the miter
join).
return miterLimit;
| double | getZeroDelta(double width)Calculates value to detect a zero angle.
return width * width * Math.sin(Math.PI * CORNER_ZERO / 180.0);
| public int | hashCode()Returns hash code of this BasicStroke.
HashCode hash = new HashCode();
hash.append(width);
hash.append(cap);
hash.append(join);
hash.append(miterLimit);
if (dash != null) {
hash.append(dashPhase);
for (float element : dash) {
hash.append(element);
}
}
return hash.hashCode();
|
|