< prev index next >
modules/javafx.graphics/src/main/java/com/sun/marlin/DStroker.java
Print this page
@@ -25,16 +25,16 @@
package com.sun.marlin;
import java.util.Arrays;
-import com.sun.javafx.geom.PathConsumer2D;
+
// TODO: some of the arithmetic here is too verbose and prone to hard to
// debug typos. We should consider making a small Point/Vector class that
// has methods like plus(Point), minus(Point), dot(Point), cross(Point)and such
-public final class Stroker implements PathConsumer2D, MarlinConst {
+public final class DStroker implements DPathConsumer2D, MarlinConst {
private static final int MOVE_TO = 0;
private static final int DRAWING_OP_TO = 1; // ie. curve, line, or quad
private static final int CLOSE = 2;
@@ -68,99 +68,99 @@
*/
public static final int CAP_SQUARE = 2;
// pisces used to use fixed point arithmetic with 16 decimal digits. I
// didn't want to change the values of the constant below when I converted
- // it to floating point, so that's why the divisions by 2^16 are there.
- private static final float ROUND_JOIN_THRESHOLD = 1000/65536f;
+ // it to doubleing point, so that's why the divisions by 2^16 are there.
+ private static final double ROUND_JOIN_THRESHOLD = 1000/65536D;
- private static final float C = 0.5522847498307933f;
+ private static final double C = 0.5522847498307933D;
private static final int MAX_N_CURVES = 11;
- private PathConsumer2D out;
+ private DPathConsumer2D out;
private int capStyle;
private int joinStyle;
- private float lineWidth2;
- private float invHalfLineWidth2Sq;
+ private double lineWidth2;
+ private double invHalfLineWidth2Sq;
- private final float[] offset0 = new float[2];
- private final float[] offset1 = new float[2];
- private final float[] offset2 = new float[2];
- private final float[] miter = new float[2];
- private float miterLimitSq;
+ private final double[] offset0 = new double[2];
+ private final double[] offset1 = new double[2];
+ private final double[] offset2 = new double[2];
+ private final double[] miter = new double[2];
+ private double miterLimitSq;
private int prev;
// The starting point of the path, and the slope there.
- private float sx0, sy0, sdx, sdy;
+ private double sx0, sy0, sdx, sdy;
// the current point and the slope there.
- private float cx0, cy0, cdx, cdy; // c stands for current
+ private double cx0, cy0, cdx, cdy; // c stands for current
// vectors that when added to (sx0,sy0) and (cx0,cy0) respectively yield the
// first and last points on the left parallel path. Since this path is
// parallel, it's slope at any point is parallel to the slope of the
// original path (thought they may have different directions), so these
// could be computed from sdx,sdy and cdx,cdy (and vice versa), but that
// would be error prone and hard to read, so we keep these anyway.
- private float smx, smy, cmx, cmy;
+ private double smx, smy, cmx, cmy;
private final PolyStack reverse;
// This is where the curve to be processed is put. We give it
// enough room to store all curves.
- private final float[] middle = new float[MAX_N_CURVES * 8];
- private final float[] lp = new float[8];
- private final float[] rp = new float[8];
- private final float[] subdivTs = new float[MAX_N_CURVES - 1];
+ private final double[] middle = new double[MAX_N_CURVES * 8];
+ private final double[] lp = new double[8];
+ private final double[] rp = new double[8];
+ private final double[] subdivTs = new double[MAX_N_CURVES - 1];
// per-thread renderer context
- final RendererContext rdrCtx;
+ final DRendererContext rdrCtx;
// dirty curve
- final Curve curve;
+ final DCurve curve;
/**
- * Constructs a <code>Stroker</code>.
+ * Constructs a <code>DStroker</code>.
* @param rdrCtx per-thread renderer context
*/
- Stroker(final RendererContext rdrCtx) {
+ DStroker(final DRendererContext rdrCtx) {
this.rdrCtx = rdrCtx;
this.reverse = new PolyStack(rdrCtx);
this.curve = rdrCtx.curve;
}
/**
- * Inits the <code>Stroker</code>.
+ * Inits the <code>DStroker</code>.
*
- * @param pc2d an output <code>PathConsumer2D</code>.
+ * @param pc2d an output <code>DPathConsumer2D</code>.
* @param lineWidth the desired line width in pixels
* @param capStyle the desired end cap style, one of
* <code>CAP_BUTT</code>, <code>CAP_ROUND</code> or
* <code>CAP_SQUARE</code>.
* @param joinStyle the desired line join style, one of
* <code>JOIN_MITER</code>, <code>JOIN_ROUND</code> or
* <code>JOIN_BEVEL</code>.
* @param miterLimit the desired miter limit
* @return this instance
*/
- public Stroker init(PathConsumer2D pc2d,
- float lineWidth,
+ public DStroker init(DPathConsumer2D pc2d,
+ double lineWidth,
int capStyle,
int joinStyle,
- float miterLimit)
+ double miterLimit)
{
this.out = pc2d;
- this.lineWidth2 = lineWidth / 2f;
- this.invHalfLineWidth2Sq = 1f / (2f * lineWidth2 * lineWidth2);
+ this.lineWidth2 = lineWidth / 2D;
+ this.invHalfLineWidth2Sq = 1D / (2D * lineWidth2 * lineWidth2);
this.capStyle = capStyle;
this.joinStyle = joinStyle;
- float limit = miterLimit * lineWidth2;
+ double limit = miterLimit * lineWidth2;
this.miterLimitSq = limit * limit;
this.prev = CLOSE;
rdrCtx.stroking = 1;
@@ -175,30 +175,30 @@
void dispose() {
reverse.dispose();
if (DO_CLEAN_DIRTY) {
// Force zero-fill dirty arrays:
- Arrays.fill(offset0, 0f);
- Arrays.fill(offset1, 0f);
- Arrays.fill(offset2, 0f);
- Arrays.fill(miter, 0f);
- Arrays.fill(middle, 0f);
- Arrays.fill(lp, 0f);
- Arrays.fill(rp, 0f);
- Arrays.fill(subdivTs, 0f);
+ Arrays.fill(offset0, 0D);
+ Arrays.fill(offset1, 0D);
+ Arrays.fill(offset2, 0D);
+ Arrays.fill(miter, 0D);
+ Arrays.fill(middle, 0D);
+ Arrays.fill(lp, 0D);
+ Arrays.fill(rp, 0D);
+ Arrays.fill(subdivTs, 0D);
}
}
- private static void computeOffset(final float lx, final float ly,
- final float w, final float[] m)
- {
- float len = lx*lx + ly*ly;
- if (len == 0f) {
- m[0] = 0f;
- m[1] = 0f;
+ private static void computeOffset(final double lx, final double ly,
+ final double w, final double[] m)
+ {
+ double len = lx*lx + ly*ly;
+ if (len == 0D) {
+ m[0] = 0D;
+ m[1] = 0D;
} else {
- len = (float) Math.sqrt(len);
+ len = Math.sqrt(len);
m[0] = (ly * w) / len;
m[1] = -(lx * w) / len;
}
}
@@ -208,28 +208,28 @@
// This is equivalent to detecting whether a point q is on the right side
// of a line passing through points p1, p2 where p2 = p1+(dx1,dy1) and
// q = p2+(dx2,dy2), which is the same as saying p1, p2, q are in a
// clockwise order.
// NOTE: "clockwise" here assumes coordinates with 0,0 at the bottom left.
- private static boolean isCW(final float dx1, final float dy1,
- final float dx2, final float dy2)
+ private static boolean isCW(final double dx1, final double dy1,
+ final double dx2, final double dy2)
{
return dx1 * dy2 <= dy1 * dx2;
}
- private void drawRoundJoin(float x, float y,
- float omx, float omy, float mx, float my,
+ private void drawRoundJoin(double x, double y,
+ double omx, double omy, double mx, double my,
boolean rev,
- float threshold)
+ double threshold)
{
- if ((omx == 0f && omy == 0f) || (mx == 0f && my == 0f)) {
+ if ((omx == 0D && omy == 0D) || (mx == 0D && my == 0D)) {
return;
}
- float domx = omx - mx;
- float domy = omy - my;
- float len = domx*domx + domy*domy;
+ double domx = omx - mx;
+ double domy = omy - my;
+ double len = domx*domx + domy*domy;
if (len < threshold) {
return;
}
if (rev) {
@@ -239,25 +239,25 @@
my = -my;
}
drawRoundJoin(x, y, omx, omy, mx, my, rev);
}
- private void drawRoundJoin(float cx, float cy,
- float omx, float omy,
- float mx, float my,
+ private void drawRoundJoin(double cx, double cy,
+ double omx, double omy,
+ double mx, double my,
boolean rev)
{
// The sign of the dot product of mx,my and omx,omy is equal to the
// the sign of the cosine of ext
// (ext is the angle between omx,omy and mx,my).
- final float cosext = omx * mx + omy * my;
+ final double cosext = omx * mx + omy * my;
// If it is >=0, we know that abs(ext) is <= 90 degrees, so we only
// need 1 curve to approximate the circle section that joins omx,omy
// and mx,my.
- final int numCurves = (cosext >= 0f) ? 1 : 2;
+ final int numDCurves = (cosext >= 0D) ? 1 : 2;
- switch (numCurves) {
+ switch (numDCurves) {
case 1:
drawBezApproxForArc(cx, cy, omx, omy, mx, my, rev);
break;
case 2:
// we need to split the arc into 2 arcs spanning the same angle.
@@ -272,14 +272,14 @@
// this vector that its length is lineWidth2 (this works because the
// perpendicular bisector goes through the origin). This scaling doesn't
// have numerical problems because we know that lineWidth2 divided by
// this normal's length is at least 0.5 and at most sqrt(2)/2 (because
// we know the angle of the arc is > 90 degrees).
- float nx = my - omy, ny = omx - mx;
- float nlen = (float) Math.sqrt(nx*nx + ny*ny);
- float scale = lineWidth2/nlen;
- float mmx = nx * scale, mmy = ny * scale;
+ double nx = my - omy, ny = omx - mx;
+ double nlen = Math.sqrt(nx*nx + ny*ny);
+ double scale = lineWidth2/nlen;
+ double mmx = nx * scale, mmy = ny * scale;
// if (isCW(omx, omy, mx, my) != isCW(mmx, mmy, mx, my)) then we've
// computed the wrong intersection so we get the other one.
// The test above is equivalent to if (rev).
if (rev) {
@@ -292,131 +292,131 @@
default:
}
}
// the input arc defined by omx,omy and mx,my must span <= 90 degrees.
- private void drawBezApproxForArc(final float cx, final float cy,
- final float omx, final float omy,
- final float mx, final float my,
+ private void drawBezApproxForArc(final double cx, final double cy,
+ final double omx, final double omy,
+ final double mx, final double my,
boolean rev)
{
- final float cosext2 = (omx * mx + omy * my) * invHalfLineWidth2Sq;
+ final double cosext2 = (omx * mx + omy * my) * invHalfLineWidth2Sq;
// check round off errors producing cos(ext) > 1 and a NaN below
// cos(ext) == 1 implies colinear segments and an empty join anyway
- if (cosext2 >= 0.5f) {
+ if (cosext2 >= 0.5D) {
// just return to avoid generating a flat curve:
return;
}
// cv is the length of P1-P0 and P2-P3 divided by the radius of the arc
// (so, cv assumes the arc has radius 1). P0, P1, P2, P3 are the points that
// define the bezier curve we're computing.
// It is computed using the constraints that P1-P0 and P3-P2 are parallel
// to the arc tangents at the endpoints, and that |P1-P0|=|P3-P2|.
- float cv = (float) ((4.0 / 3.0) * Math.sqrt(0.5 - cosext2) /
+ double cv = ((4.0 / 3.0) * Math.sqrt(0.5 - cosext2) /
(1.0 + Math.sqrt(cosext2 + 0.5)));
// if clockwise, we need to negate cv.
if (rev) { // rev is equivalent to isCW(omx, omy, mx, my)
cv = -cv;
}
- final float x1 = cx + omx;
- final float y1 = cy + omy;
- final float x2 = x1 - cv * omy;
- final float y2 = y1 + cv * omx;
-
- final float x4 = cx + mx;
- final float y4 = cy + my;
- final float x3 = x4 + cv * my;
- final float y3 = y4 - cv * mx;
-
- emitCurveTo(x1, y1, x2, y2, x3, y3, x4, y4, rev);
- }
-
- private void drawRoundCap(float cx, float cy, float mx, float my) {
- final float Cmx = C * mx;
- final float Cmy = C * my;
- emitCurveTo(cx + mx - Cmy, cy + my + Cmx,
+ final double x1 = cx + omx;
+ final double y1 = cy + omy;
+ final double x2 = x1 - cv * omy;
+ final double y2 = y1 + cv * omx;
+
+ final double x4 = cx + mx;
+ final double y4 = cy + my;
+ final double x3 = x4 + cv * my;
+ final double y3 = y4 - cv * mx;
+
+ emitDCurveTo(x1, y1, x2, y2, x3, y3, x4, y4, rev);
+ }
+
+ private void drawRoundCap(double cx, double cy, double mx, double my) {
+ final double Cmx = C * mx;
+ final double Cmy = C * my;
+ emitDCurveTo(cx + mx - Cmy, cy + my + Cmx,
cx - my + Cmx, cy + mx + Cmy,
cx - my, cy + mx);
- emitCurveTo(cx - my - Cmx, cy + mx - Cmy,
+ emitDCurveTo(cx - my - Cmx, cy + mx - Cmy,
cx - mx - Cmy, cy - my + Cmx,
cx - mx, cy - my);
}
// Return the intersection point of the lines (x0, y0) -> (x1, y1)
// and (x0p, y0p) -> (x1p, y1p) in m[0] and m[1]
- private static void computeMiter(final float x0, final float y0,
- final float x1, final float y1,
- final float x0p, final float y0p,
- final float x1p, final float y1p,
- final float[] m, int off)
- {
- float x10 = x1 - x0;
- float y10 = y1 - y0;
- float x10p = x1p - x0p;
- float y10p = y1p - y0p;
+ private static void computeMiter(final double x0, final double y0,
+ final double x1, final double y1,
+ final double x0p, final double y0p,
+ final double x1p, final double y1p,
+ final double[] m, int off)
+ {
+ double x10 = x1 - x0;
+ double y10 = y1 - y0;
+ double x10p = x1p - x0p;
+ double y10p = y1p - y0p;
// if this is 0, the lines are parallel. If they go in the
// same direction, there is no intersection so m[off] and
// m[off+1] will contain infinity, so no miter will be drawn.
// If they go in the same direction that means that the start of the
// current segment and the end of the previous segment have the same
// tangent, in which case this method won't even be involved in
// miter drawing because it won't be called by drawMiter (because
// (mx == omx && my == omy) will be true, and drawMiter will return
// immediately).
- float den = x10*y10p - x10p*y10;
- float t = x10p*(y0-y0p) - y10p*(x0-x0p);
+ double den = x10*y10p - x10p*y10;
+ double t = x10p*(y0-y0p) - y10p*(x0-x0p);
t /= den;
m[off++] = x0 + t*x10;
m[off] = y0 + t*y10;
}
// Return the intersection point of the lines (x0, y0) -> (x1, y1)
// and (x0p, y0p) -> (x1p, y1p) in m[0] and m[1]
- private static void safecomputeMiter(final float x0, final float y0,
- final float x1, final float y1,
- final float x0p, final float y0p,
- final float x1p, final float y1p,
- final float[] m, int off)
- {
- float x10 = x1 - x0;
- float y10 = y1 - y0;
- float x10p = x1p - x0p;
- float y10p = y1p - y0p;
+ private static void safecomputeMiter(final double x0, final double y0,
+ final double x1, final double y1,
+ final double x0p, final double y0p,
+ final double x1p, final double y1p,
+ final double[] m, int off)
+ {
+ double x10 = x1 - x0;
+ double y10 = y1 - y0;
+ double x10p = x1p - x0p;
+ double y10p = y1p - y0p;
// if this is 0, the lines are parallel. If they go in the
// same direction, there is no intersection so m[off] and
// m[off+1] will contain infinity, so no miter will be drawn.
// If they go in the same direction that means that the start of the
// current segment and the end of the previous segment have the same
// tangent, in which case this method won't even be involved in
// miter drawing because it won't be called by drawMiter (because
// (mx == omx && my == omy) will be true, and drawMiter will return
// immediately).
- float den = x10*y10p - x10p*y10;
- if (den == 0f) {
- m[off++] = (x0 + x0p) / 2f;
- m[off] = (y0 + y0p) / 2f;
+ double den = x10*y10p - x10p*y10;
+ if (den == 0D) {
+ m[off++] = (x0 + x0p) / 2D;
+ m[off] = (y0 + y0p) / 2D;
return;
}
- float t = x10p*(y0-y0p) - y10p*(x0-x0p);
+ double t = x10p*(y0-y0p) - y10p*(x0-x0p);
t /= den;
m[off++] = x0 + t*x10;
m[off] = y0 + t*y10;
}
- private void drawMiter(final float pdx, final float pdy,
- final float x0, final float y0,
- final float dx, final float dy,
- float omx, float omy, float mx, float my,
+ private void drawMiter(final double pdx, final double pdy,
+ final double x0, final double y0,
+ final double dx, final double dy,
+ double omx, double omy, double mx, double my,
boolean rev)
{
if ((mx == omx && my == omy) ||
- (pdx == 0f && pdy == 0f) ||
- (dx == 0f && dy == 0f))
+ (pdx == 0D && pdy == 0D) ||
+ (dx == 0D && dy == 0D))
{
return;
}
if (rev) {
@@ -428,13 +428,13 @@
computeMiter((x0 - pdx) + omx, (y0 - pdy) + omy, x0 + omx, y0 + omy,
(dx + x0) + mx, (dy + y0) + my, x0 + mx, y0 + my,
miter, 0);
- final float miterX = miter[0];
- final float miterY = miter[1];
- float lenSq = (miterX-x0)*(miterX-x0) + (miterY-y0)*(miterY-y0);
+ final double miterX = miter[0];
+ final double miterY = miter[1];
+ double lenSq = (miterX-x0)*(miterX-x0) + (miterY-y0)*(miterY-y0);
// If the lines are parallel, lenSq will be either NaN or +inf
// (actually, I'm not sure if the latter is possible. The important
// thing is that -inf is not possible, because lenSq is a square).
// For both of those values, the comparison below will fail and
@@ -443,31 +443,31 @@
emitLineTo(miterX, miterY, rev);
}
}
@Override
- public void moveTo(float x0, float y0) {
+ public void moveTo(double x0, double y0) {
if (prev == DRAWING_OP_TO) {
finish();
}
this.sx0 = this.cx0 = x0;
this.sy0 = this.cy0 = y0;
- this.cdx = this.sdx = 1f;
- this.cdy = this.sdy = 0f;
+ this.cdx = this.sdx = 1D;
+ this.cdy = this.sdy = 0D;
this.prev = MOVE_TO;
}
@Override
- public void lineTo(float x1, float y1) {
- float dx = x1 - cx0;
- float dy = y1 - cy0;
- if (dx == 0f && dy == 0f) {
- dx = 1f;
+ public void lineTo(double x1, double y1) {
+ double dx = x1 - cx0;
+ double dy = y1 - cy0;
+ if (dx == 0D && dy == 0D) {
+ dx = 1D;
}
computeOffset(dx, dy, lineWidth2, offset0);
- final float mx = offset0[0];
- final float my = offset0[1];
+ final double mx = offset0[0];
+ final double my = offset0[1];
drawJoin(cdx, cdy, cx0, cy0, dx, dy, cmx, cmy, mx, my);
emitLineTo(cx0 + mx, cy0 + my);
emitLineTo( x1 + mx, y1 + my);
@@ -489,14 +489,14 @@
if (prev != DRAWING_OP_TO) {
if (prev == CLOSE) {
return;
}
emitMoveTo(cx0, cy0 - lineWidth2);
- this.cmx = this.smx = 0f;
+ this.cmx = this.smx = 0D;
this.cmy = this.smy = -lineWidth2;
- this.cdx = this.sdx = 1f;
- this.cdy = this.sdy = 0f;
+ this.cdx = this.sdx = 1D;
+ this.cdy = this.sdy = 0D;
finish();
return;
}
if (cx0 != sx0 || cy0 != sy0) {
@@ -552,62 +552,62 @@
}
emitClose();
}
- private void emitMoveTo(final float x0, final float y0) {
+ private void emitMoveTo(final double x0, final double y0) {
out.moveTo(x0, y0);
}
- private void emitLineTo(final float x1, final float y1) {
+ private void emitLineTo(final double x1, final double y1) {
out.lineTo(x1, y1);
}
- private void emitLineToRev(final float x1, final float y1) {
+ private void emitLineToRev(final double x1, final double y1) {
reverse.pushLine(x1, y1);
}
- private void emitLineTo(final float x1, final float y1,
+ private void emitLineTo(final double x1, final double y1,
final boolean rev)
{
if (rev) {
emitLineToRev(x1, y1);
} else {
emitLineTo(x1, y1);
}
}
- private void emitQuadTo(final float x1, final float y1,
- final float x2, final float y2)
+ private void emitQuadTo(final double x1, final double y1,
+ final double x2, final double y2)
{
out.quadTo(x1, y1, x2, y2);
}
- private void emitQuadToRev(final float x0, final float y0,
- final float x1, final float y1)
+ private void emitQuadToRev(final double x0, final double y0,
+ final double x1, final double y1)
{
reverse.pushQuad(x0, y0, x1, y1);
}
- private void emitCurveTo(final float x1, final float y1,
- final float x2, final float y2,
- final float x3, final float y3)
+ private void emitDCurveTo(final double x1, final double y1,
+ final double x2, final double y2,
+ final double x3, final double y3)
{
out.curveTo(x1, y1, x2, y2, x3, y3);
}
- private void emitCurveToRev(final float x0, final float y0,
- final float x1, final float y1,
- final float x2, final float y2)
+ private void emitDCurveToRev(final double x0, final double y0,
+ final double x1, final double y1,
+ final double x2, final double y2)
{
reverse.pushCubic(x0, y0, x1, y1, x2, y2);
}
- private void emitCurveTo(final float x0, final float y0,
- final float x1, final float y1,
- final float x2, final float y2,
- final float x3, final float y3, final boolean rev)
+ private void emitDCurveTo(final double x0, final double y0,
+ final double x1, final double y1,
+ final double x2, final double y2,
+ final double x3, final double y3, final boolean rev)
{
if (rev) {
reverse.pushCubic(x0, y0, x1, y1, x2, y2);
} else {
out.curveTo(x1, y1, x2, y2, x3, y3);
@@ -616,15 +616,15 @@
private void emitClose() {
out.closePath();
}
- private void drawJoin(float pdx, float pdy,
- float x0, float y0,
- float dx, float dy,
- float omx, float omy,
- float mx, float my)
+ private void drawJoin(double pdx, double pdy,
+ double x0, double y0,
+ double dx, double dy,
+ double omx, double omy,
+ double mx, double my)
{
if (prev != DRAWING_OP_TO) {
emitMoveTo(x0 + mx, y0 + my);
this.sdx = dx;
this.sdy = dy;
@@ -643,61 +643,61 @@
emitLineTo(x0, y0, !cw);
}
prev = DRAWING_OP_TO;
}
- private static boolean within(final float x1, final float y1,
- final float x2, final float y2,
- final float ERR)
+ private static boolean within(final double x1, final double y1,
+ final double x2, final double y2,
+ final double ERR)
{
assert ERR > 0 : "";
// compare taxicab distance. ERR will always be small, so using
// true distance won't give much benefit
- return (Helpers.within(x1, x2, ERR) && // we want to avoid calling Math.abs
- Helpers.within(y1, y2, ERR)); // this is just as good.
+ return (DHelpers.within(x1, x2, ERR) && // we want to avoid calling Math.abs
+ DHelpers.within(y1, y2, ERR)); // this is just as good.
}
- private void getLineOffsets(float x1, float y1,
- float x2, float y2,
- float[] left, float[] right) {
+ private void getLineOffsets(double x1, double y1,
+ double x2, double y2,
+ double[] left, double[] right) {
computeOffset(x2 - x1, y2 - y1, lineWidth2, offset0);
- final float mx = offset0[0];
- final float my = offset0[1];
+ final double mx = offset0[0];
+ final double my = offset0[1];
left[0] = x1 + mx;
left[1] = y1 + my;
left[2] = x2 + mx;
left[3] = y2 + my;
right[0] = x1 - mx;
right[1] = y1 - my;
right[2] = x2 - mx;
right[3] = y2 - my;
}
- private int computeOffsetCubic(float[] pts, final int off,
- float[] leftOff, float[] rightOff)
+ private int computeOffsetCubic(double[] pts, final int off,
+ double[] leftOff, double[] rightOff)
{
// if p1=p2 or p3=p4 it means that the derivative at the endpoint
// vanishes, which creates problems with computeOffset. Usually
// this happens when this stroker object is trying to winden
// a curve with a cusp. What happens is that curveTo splits
// the input curve at the cusp, and passes it to this function.
// because of inaccuracies in the splitting, we consider points
// equal if they're very close to each other.
- final float x1 = pts[off + 0], y1 = pts[off + 1];
- final float x2 = pts[off + 2], y2 = pts[off + 3];
- final float x3 = pts[off + 4], y3 = pts[off + 5];
- final float x4 = pts[off + 6], y4 = pts[off + 7];
-
- float dx4 = x4 - x3;
- float dy4 = y4 - y3;
- float dx1 = x2 - x1;
- float dy1 = y2 - y1;
+ final double x1 = pts[off + 0], y1 = pts[off + 1];
+ final double x2 = pts[off + 2], y2 = pts[off + 3];
+ final double x3 = pts[off + 4], y3 = pts[off + 5];
+ final double x4 = pts[off + 6], y4 = pts[off + 7];
+
+ double dx4 = x4 - x3;
+ double dy4 = y4 - y3;
+ double dx1 = x2 - x1;
+ double dy1 = y2 - y1;
// if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
// in which case ignore if p1 == p2
- final boolean p1eqp2 = within(x1,y1,x2,y2, 6f * Math.ulp(y2));
- final boolean p3eqp4 = within(x3,y3,x4,y4, 6f * Math.ulp(y4));
+ final boolean p1eqp2 = within(x1,y1,x2,y2, 6D * Math.ulp(y2));
+ final boolean p3eqp4 = within(x3,y3,x4,y4, 6D * Math.ulp(y4));
if (p1eqp2 && p3eqp4) {
getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
return 4;
} else if (p1eqp2) {
dx1 = x3 - x1;
@@ -706,14 +706,14 @@
dx4 = x4 - x2;
dy4 = y4 - y2;
}
// if p2-p1 and p4-p3 are parallel, that must mean this curve is a line
- float dotsq = (dx1 * dx4 + dy1 * dy4);
+ double dotsq = (dx1 * dx4 + dy1 * dy4);
dotsq *= dotsq;
- float l1sq = dx1 * dx1 + dy1 * dy1, l4sq = dx4 * dx4 + dy4 * dy4;
- if (Helpers.within(dotsq, l1sq * l4sq, 4f * Math.ulp(dotsq))) {
+ double l1sq = dx1 * dx1 + dy1 * dy1, l4sq = dx4 * dx4 + dy4 * dy4;
+ if (DHelpers.within(dotsq, l1sq * l4sq, 4D * Math.ulp(dotsq))) {
getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
return 4;
}
// What we're trying to do in this function is to approximate an ideal
@@ -761,37 +761,37 @@
// [dy1, dy4][c2]
// At this point we are left with a simple linear system and we solve it by
// getting the inverse of the matrix above. Then we use [c1,c2] to compute
// p2p and p3p.
- float x = (x1 + 3f * (x2 + x3) + x4) / 8f;
- float y = (y1 + 3f * (y2 + y3) + y4) / 8f;
+ double x = (x1 + 3D * (x2 + x3) + x4) / 8D;
+ double y = (y1 + 3D * (y2 + y3) + y4) / 8D;
// (dxm,dym) is some tangent of B at t=0.5. This means it's equal to
// c*B'(0.5) for some constant c.
- float dxm = x3 + x4 - x1 - x2, dym = y3 + y4 - y1 - y2;
+ double dxm = x3 + x4 - x1 - x2, dym = y3 + y4 - y1 - y2;
// this computes the offsets at t=0, 0.5, 1, using the property that
// for any bezier curve the vectors p2-p1 and p4-p3 are parallel to
// the (dx/dt, dy/dt) vectors at the endpoints.
computeOffset(dx1, dy1, lineWidth2, offset0);
computeOffset(dxm, dym, lineWidth2, offset1);
computeOffset(dx4, dy4, lineWidth2, offset2);
- float x1p = x1 + offset0[0]; // start
- float y1p = y1 + offset0[1]; // point
- float xi = x + offset1[0]; // interpolation
- float yi = y + offset1[1]; // point
- float x4p = x4 + offset2[0]; // end
- float y4p = y4 + offset2[1]; // point
-
- float invdet43 = 4f / (3f * (dx1 * dy4 - dy1 * dx4));
-
- float two_pi_m_p1_m_p4x = 2f * xi - x1p - x4p;
- float two_pi_m_p1_m_p4y = 2f * yi - y1p - y4p;
- float c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
- float c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
+ double x1p = x1 + offset0[0]; // start
+ double y1p = y1 + offset0[1]; // point
+ double xi = x + offset1[0]; // interpolation
+ double yi = y + offset1[1]; // point
+ double x4p = x4 + offset2[0]; // end
+ double y4p = y4 + offset2[1]; // point
+
+ double invdet43 = 4D / (3D * (dx1 * dy4 - dy1 * dx4));
+
+ double two_pi_m_p1_m_p4x = 2D * xi - x1p - x4p;
+ double two_pi_m_p1_m_p4y = 2D * yi - y1p - y4p;
+ double c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
+ double c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
- float x2p, y2p, x3p, y3p;
+ double x2p, y2p, x3p, y3p;
x2p = x1p + c1*dx1;
y2p = y1p + c1*dy1;
x3p = x4p + c2*dx4;
y3p = y4p + c2*dy4;
@@ -799,15 +799,15 @@
leftOff[2] = x2p; leftOff[3] = y2p;
leftOff[4] = x3p; leftOff[5] = y3p;
leftOff[6] = x4p; leftOff[7] = y4p;
x1p = x1 - offset0[0]; y1p = y1 - offset0[1];
- xi = xi - 2f * offset1[0]; yi = yi - 2f * offset1[1];
+ xi = xi - 2D * offset1[0]; yi = yi - 2D * offset1[1];
x4p = x4 - offset2[0]; y4p = y4 - offset2[1];
- two_pi_m_p1_m_p4x = 2f * xi - x1p - x4p;
- two_pi_m_p1_m_p4y = 2f * yi - y1p - y4p;
+ two_pi_m_p1_m_p4x = 2D * xi - x1p - x4p;
+ two_pi_m_p1_m_p4y = 2D * yi - y1p - y4p;
c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
x2p = x1p + c1*dx1;
y2p = y1p + c1*dy1;
@@ -820,23 +820,23 @@
rightOff[6] = x4p; rightOff[7] = y4p;
return 8;
}
// compute offset curves using bezier spline through t=0.5 (i.e.
- // ComputedCurve(0.5) == IdealParallelCurve(0.5))
+ // ComputedDCurve(0.5) == IdealParallelDCurve(0.5))
// return the kind of curve in the right and left arrays.
- private int computeOffsetQuad(float[] pts, final int off,
- float[] leftOff, float[] rightOff)
+ private int computeOffsetQuad(double[] pts, final int off,
+ double[] leftOff, double[] rightOff)
{
- final float x1 = pts[off + 0], y1 = pts[off + 1];
- final float x2 = pts[off + 2], y2 = pts[off + 3];
- final float x3 = pts[off + 4], y3 = pts[off + 5];
-
- final float dx3 = x3 - x2;
- final float dy3 = y3 - y2;
- final float dx1 = x2 - x1;
- final float dy1 = y2 - y1;
+ final double x1 = pts[off + 0], y1 = pts[off + 1];
+ final double x2 = pts[off + 2], y2 = pts[off + 3];
+ final double x3 = pts[off + 4], y3 = pts[off + 5];
+
+ final double dx3 = x3 - x2;
+ final double dy3 = y3 - y2;
+ final double dx1 = x2 - x1;
+ final double dy1 = y2 - y1;
// if p1=p2 or p3=p4 it means that the derivative at the endpoint
// vanishes, which creates problems with computeOffset. Usually
// this happens when this stroker object is trying to winden
// a curve with a cusp. What happens is that curveTo splits
@@ -844,36 +844,36 @@
// because of inaccuracies in the splitting, we consider points
// equal if they're very close to each other.
// if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
// in which case ignore.
- final boolean p1eqp2 = within(x1,y1,x2,y2, 6f * Math.ulp(y2));
- final boolean p2eqp3 = within(x2,y2,x3,y3, 6f * Math.ulp(y3));
+ final boolean p1eqp2 = within(x1,y1,x2,y2, 6D * Math.ulp(y2));
+ final boolean p2eqp3 = within(x2,y2,x3,y3, 6D * Math.ulp(y3));
if (p1eqp2 || p2eqp3) {
getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
return 4;
}
// if p2-p1 and p4-p3 are parallel, that must mean this curve is a line
- float dotsq = (dx1 * dx3 + dy1 * dy3);
+ double dotsq = (dx1 * dx3 + dy1 * dy3);
dotsq *= dotsq;
- float l1sq = dx1 * dx1 + dy1 * dy1, l3sq = dx3 * dx3 + dy3 * dy3;
- if (Helpers.within(dotsq, l1sq * l3sq, 4f * Math.ulp(dotsq))) {
+ double l1sq = dx1 * dx1 + dy1 * dy1, l3sq = dx3 * dx3 + dy3 * dy3;
+ if (DHelpers.within(dotsq, l1sq * l3sq, 4D * Math.ulp(dotsq))) {
getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
return 4;
}
// this computes the offsets at t=0, 0.5, 1, using the property that
// for any bezier curve the vectors p2-p1 and p4-p3 are parallel to
// the (dx/dt, dy/dt) vectors at the endpoints.
computeOffset(dx1, dy1, lineWidth2, offset0);
computeOffset(dx3, dy3, lineWidth2, offset1);
- float x1p = x1 + offset0[0]; // start
- float y1p = y1 + offset0[1]; // point
- float x3p = x3 + offset1[0]; // end
- float y3p = y3 + offset1[1]; // point
+ double x1p = x1 + offset0[0]; // start
+ double y1p = y1 + offset0[1]; // point
+ double x3p = x3 + offset1[0]; // end
+ double y3p = y3 + offset1[1]; // point
safecomputeMiter(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, leftOff, 2);
leftOff[0] = x1p; leftOff[1] = y1p;
leftOff[4] = x3p; leftOff[5] = y3p;
x1p = x1 - offset0[0]; y1p = y1 - offset0[1];
@@ -889,86 +889,86 @@
// TODO: until those are fixed, we should work around that by
// manually inlining this into curveTo and quadTo.
/******************************* WORKAROUND **********************************
private void somethingTo(final int type) {
// need these so we can update the state at the end of this method
- final float xf = middle[type-2], yf = middle[type-1];
- float dxs = middle[2] - middle[0];
- float dys = middle[3] - middle[1];
- float dxf = middle[type - 2] - middle[type - 4];
- float dyf = middle[type - 1] - middle[type - 3];
+ final double xf = middle[type-2], yf = middle[type-1];
+ double dxs = middle[2] - middle[0];
+ double dys = middle[3] - middle[1];
+ double dxf = middle[type - 2] - middle[type - 4];
+ double dyf = middle[type - 1] - middle[type - 3];
switch(type) {
case 6:
- if ((dxs == 0f && dys == 0f) ||
- (dxf == 0f && dyf == 0f)) {
+ if ((dxs == 0D && dys == 0D) ||
+ (dxf == 0D && dyf == 0D)) {
dxs = dxf = middle[4] - middle[0];
dys = dyf = middle[5] - middle[1];
}
break;
case 8:
- boolean p1eqp2 = (dxs == 0f && dys == 0f);
- boolean p3eqp4 = (dxf == 0f && dyf == 0f);
+ boolean p1eqp2 = (dxs == 0D && dys == 0D);
+ boolean p3eqp4 = (dxf == 0D && dyf == 0D);
if (p1eqp2) {
dxs = middle[4] - middle[0];
dys = middle[5] - middle[1];
- if (dxs == 0f && dys == 0f) {
+ if (dxs == 0D && dys == 0D) {
dxs = middle[6] - middle[0];
dys = middle[7] - middle[1];
}
}
if (p3eqp4) {
dxf = middle[6] - middle[2];
dyf = middle[7] - middle[3];
- if (dxf == 0f && dyf == 0f) {
+ if (dxf == 0D && dyf == 0D) {
dxf = middle[6] - middle[0];
dyf = middle[7] - middle[1];
}
}
}
- if (dxs == 0f && dys == 0f) {
+ if (dxs == 0D && dys == 0D) {
// this happens iff the "curve" is just a point
lineTo(middle[0], middle[1]);
return;
}
// if these vectors are too small, normalize them, to avoid future
// precision problems.
- if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
- float len = (float) Math.sqrt(dxs*dxs + dys*dys);
+ if (Math.abs(dxs) < 0.1D && Math.abs(dys) < 0.1D) {
+ double len = Math.sqrt(dxs*dxs + dys*dys);
dxs /= len;
dys /= len;
}
- if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
- float len = (float) Math.sqrt(dxf*dxf + dyf*dyf);
+ if (Math.abs(dxf) < 0.1D && Math.abs(dyf) < 0.1D) {
+ double len = Math.sqrt(dxf*dxf + dyf*dyf);
dxf /= len;
dyf /= len;
}
computeOffset(dxs, dys, lineWidth2, offset0);
- final float mx = offset0[0];
- final float my = offset0[1];
+ final double mx = offset0[0];
+ final double my = offset0[1];
drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my);
int nSplits = findSubdivPoints(curve, middle, subdivTs, type, lineWidth2);
int kind = 0;
BreakPtrIterator it = curve.breakPtsAtTs(middle, type, subdivTs, nSplits);
while(it.hasNext()) {
- int curCurveOff = it.next();
+ int curDCurveOff = it.next();
switch (type) {
case 8:
- kind = computeOffsetCubic(middle, curCurveOff, lp, rp);
+ kind = computeOffsetCubic(middle, curDCurveOff, lp, rp);
break;
case 6:
- kind = computeOffsetQuad(middle, curCurveOff, lp, rp);
+ kind = computeOffsetQuad(middle, curDCurveOff, lp, rp);
break;
}
emitLineTo(lp[0], lp[1]);
switch(kind) {
case 8:
- emitCurveTo(lp[2], lp[3], lp[4], lp[5], lp[6], lp[7]);
- emitCurveToRev(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5]);
+ emitDCurveTo(lp[2], lp[3], lp[4], lp[5], lp[6], lp[7]);
+ emitDCurveToRev(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5]);
break;
case 6:
emitQuadTo(lp[2], lp[3], lp[4], lp[5]);
emitQuadToRev(rp[0], rp[1], rp[2], rp[3]);
break;
@@ -991,35 +991,35 @@
****************************** END WORKAROUND *******************************/
// finds values of t where the curve in pts should be subdivided in order
// to get good offset curves a distance of w away from the middle curve.
// Stores the points in ts, and returns how many of them there were.
- private static int findSubdivPoints(final Curve c, float[] pts, float[] ts,
- final int type, final float w)
+ private static int findSubdivPoints(final DCurve c, double[] pts, double[] ts,
+ final int type, final double w)
{
- final float x12 = pts[2] - pts[0];
- final float y12 = pts[3] - pts[1];
+ final double x12 = pts[2] - pts[0];
+ final double y12 = pts[3] - pts[1];
// if the curve is already parallel to either axis we gain nothing
// from rotating it.
- if (y12 != 0f && x12 != 0f) {
+ if (y12 != 0D && x12 != 0D) {
// we rotate it so that the first vector in the control polygon is
// parallel to the x-axis. This will ensure that rotated quarter
// circles won't be subdivided.
- final float hypot = (float) Math.sqrt(x12 * x12 + y12 * y12);
- final float cos = x12 / hypot;
- final float sin = y12 / hypot;
- final float x1 = cos * pts[0] + sin * pts[1];
- final float y1 = cos * pts[1] - sin * pts[0];
- final float x2 = cos * pts[2] + sin * pts[3];
- final float y2 = cos * pts[3] - sin * pts[2];
- final float x3 = cos * pts[4] + sin * pts[5];
- final float y3 = cos * pts[5] - sin * pts[4];
+ final double hypot = Math.sqrt(x12 * x12 + y12 * y12);
+ final double cos = x12 / hypot;
+ final double sin = y12 / hypot;
+ final double x1 = cos * pts[0] + sin * pts[1];
+ final double y1 = cos * pts[1] - sin * pts[0];
+ final double x2 = cos * pts[2] + sin * pts[3];
+ final double y2 = cos * pts[3] - sin * pts[2];
+ final double x3 = cos * pts[4] + sin * pts[5];
+ final double y3 = cos * pts[5] - sin * pts[4];
switch(type) {
case 8:
- final float x4 = cos * pts[6] + sin * pts[7];
- final float y4 = cos * pts[7] - sin * pts[6];
+ final double x4 = cos * pts[6] + sin * pts[7];
+ final double y4 = cos * pts[7] - sin * pts[6];
c.set(x1, y1, x2, y2, x3, y3, x4, y4);
break;
case 6:
c.set(x1, y1, x2, y2, x3, y3);
break;
@@ -1040,173 +1040,173 @@
ret += c.infPoints(ts, ret);
}
// now we must subdivide at points where one of the offset curves will have
// a cusp. This happens at ts where the radius of curvature is equal to w.
- ret += c.rootsOfROCMinusW(ts, ret, w, 0.0001f);
+ ret += c.rootsOfROCMinusW(ts, ret, w, 0.0001D);
- ret = Helpers.filterOutNotInAB(ts, 0, ret, 0.0001f, 0.9999f);
- Helpers.isort(ts, 0, ret);
+ ret = DHelpers.filterOutNotInAB(ts, 0, ret, 0.0001D, 0.9999D);
+ DHelpers.isort(ts, 0, ret);
return ret;
}
- @Override public void curveTo(float x1, float y1,
- float x2, float y2,
- float x3, float y3)
+ @Override public void curveTo(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
{
- final float[] mid = middle;
+ final double[] mid = middle;
mid[0] = cx0; mid[1] = cy0;
mid[2] = x1; mid[3] = y1;
mid[4] = x2; mid[5] = y2;
mid[6] = x3; mid[7] = y3;
// inlined version of somethingTo(8);
// See the TODO on somethingTo
// need these so we can update the state at the end of this method
- final float xf = mid[6], yf = mid[7];
- float dxs = mid[2] - mid[0];
- float dys = mid[3] - mid[1];
- float dxf = mid[6] - mid[4];
- float dyf = mid[7] - mid[5];
+ final double xf = mid[6], yf = mid[7];
+ double dxs = mid[2] - mid[0];
+ double dys = mid[3] - mid[1];
+ double dxf = mid[6] - mid[4];
+ double dyf = mid[7] - mid[5];
- boolean p1eqp2 = (dxs == 0f && dys == 0f);
- boolean p3eqp4 = (dxf == 0f && dyf == 0f);
+ boolean p1eqp2 = (dxs == 0D && dys == 0D);
+ boolean p3eqp4 = (dxf == 0D && dyf == 0D);
if (p1eqp2) {
dxs = mid[4] - mid[0];
dys = mid[5] - mid[1];
- if (dxs == 0f && dys == 0f) {
+ if (dxs == 0D && dys == 0D) {
dxs = mid[6] - mid[0];
dys = mid[7] - mid[1];
}
}
if (p3eqp4) {
dxf = mid[6] - mid[2];
dyf = mid[7] - mid[3];
- if (dxf == 0f && dyf == 0f) {
+ if (dxf == 0D && dyf == 0D) {
dxf = mid[6] - mid[0];
dyf = mid[7] - mid[1];
}
}
- if (dxs == 0f && dys == 0f) {
+ if (dxs == 0D && dys == 0D) {
// this happens if the "curve" is just a point
lineTo(mid[0], mid[1]);
return;
}
// if these vectors are too small, normalize them, to avoid future
// precision problems.
- if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
- float len = (float) Math.sqrt(dxs*dxs + dys*dys);
+ if (Math.abs(dxs) < 0.1D && Math.abs(dys) < 0.1D) {
+ double len = Math.sqrt(dxs*dxs + dys*dys);
dxs /= len;
dys /= len;
}
- if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
- float len = (float) Math.sqrt(dxf*dxf + dyf*dyf);
+ if (Math.abs(dxf) < 0.1D && Math.abs(dyf) < 0.1D) {
+ double len = Math.sqrt(dxf*dxf + dyf*dyf);
dxf /= len;
dyf /= len;
}
computeOffset(dxs, dys, lineWidth2, offset0);
drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, offset0[0], offset0[1]);
final int nSplits = findSubdivPoints(curve, mid, subdivTs, 8, lineWidth2);
- float prevT = 0f;
+ double prevT = 0D;
for (int i = 0, off = 0; i < nSplits; i++, off += 6) {
- final float t = subdivTs[i];
- Helpers.subdivideCubicAt((t - prevT) / (1f - prevT),
+ final double t = subdivTs[i];
+ DHelpers.subdivideCubicAt((t - prevT) / (1D - prevT),
mid, off, mid, off, mid, off + 6);
prevT = t;
}
- final float[] l = lp;
- final float[] r = rp;
+ final double[] l = lp;
+ final double[] r = rp;
int kind = 0;
for (int i = 0, off = 0; i <= nSplits; i++, off += 6) {
kind = computeOffsetCubic(mid, off, l, r);
emitLineTo(l[0], l[1]);
switch(kind) {
case 8:
- emitCurveTo(l[2], l[3], l[4], l[5], l[6], l[7]);
- emitCurveToRev(r[0], r[1], r[2], r[3], r[4], r[5]);
+ emitDCurveTo(l[2], l[3], l[4], l[5], l[6], l[7]);
+ emitDCurveToRev(r[0], r[1], r[2], r[3], r[4], r[5]);
break;
case 4:
emitLineTo(l[2], l[3]);
emitLineToRev(r[0], r[1]);
break;
default:
}
emitLineToRev(r[kind - 2], r[kind - 1]);
}
- this.cmx = (l[kind - 2] - r[kind - 2]) / 2f;
- this.cmy = (l[kind - 1] - r[kind - 1]) / 2f;
+ this.cmx = (l[kind - 2] - r[kind - 2]) / 2D;
+ this.cmy = (l[kind - 1] - r[kind - 1]) / 2D;
this.cdx = dxf;
this.cdy = dyf;
this.cx0 = xf;
this.cy0 = yf;
this.prev = DRAWING_OP_TO;
}
- @Override public void quadTo(float x1, float y1, float x2, float y2) {
- final float[] mid = middle;
+ @Override public void quadTo(double x1, double y1, double x2, double y2) {
+ final double[] mid = middle;
mid[0] = cx0; mid[1] = cy0;
mid[2] = x1; mid[3] = y1;
mid[4] = x2; mid[5] = y2;
// inlined version of somethingTo(8);
// See the TODO on somethingTo
// need these so we can update the state at the end of this method
- final float xf = mid[4], yf = mid[5];
- float dxs = mid[2] - mid[0];
- float dys = mid[3] - mid[1];
- float dxf = mid[4] - mid[2];
- float dyf = mid[5] - mid[3];
- if ((dxs == 0f && dys == 0f) || (dxf == 0f && dyf == 0f)) {
+ final double xf = mid[4], yf = mid[5];
+ double dxs = mid[2] - mid[0];
+ double dys = mid[3] - mid[1];
+ double dxf = mid[4] - mid[2];
+ double dyf = mid[5] - mid[3];
+ if ((dxs == 0D && dys == 0D) || (dxf == 0D && dyf == 0D)) {
dxs = dxf = mid[4] - mid[0];
dys = dyf = mid[5] - mid[1];
}
- if (dxs == 0f && dys == 0f) {
+ if (dxs == 0D && dys == 0D) {
// this happens if the "curve" is just a point
lineTo(mid[0], mid[1]);
return;
}
// if these vectors are too small, normalize them, to avoid future
// precision problems.
- if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
- float len = (float) Math.sqrt(dxs*dxs + dys*dys);
+ if (Math.abs(dxs) < 0.1D && Math.abs(dys) < 0.1D) {
+ double len = Math.sqrt(dxs*dxs + dys*dys);
dxs /= len;
dys /= len;
}
- if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
- float len = (float) Math.sqrt(dxf*dxf + dyf*dyf);
+ if (Math.abs(dxf) < 0.1D && Math.abs(dyf) < 0.1D) {
+ double len = Math.sqrt(dxf*dxf + dyf*dyf);
dxf /= len;
dyf /= len;
}
computeOffset(dxs, dys, lineWidth2, offset0);
drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, offset0[0], offset0[1]);
int nSplits = findSubdivPoints(curve, mid, subdivTs, 6, lineWidth2);
- float prevt = 0f;
+ double prevt = 0D;
for (int i = 0, off = 0; i < nSplits; i++, off += 4) {
- final float t = subdivTs[i];
- Helpers.subdivideQuadAt((t - prevt) / (1f - prevt),
+ final double t = subdivTs[i];
+ DHelpers.subdivideQuadAt((t - prevt) / (1D - prevt),
mid, off, mid, off, mid, off + 4);
prevt = t;
}
- final float[] l = lp;
- final float[] r = rp;
+ final double[] l = lp;
+ final double[] r = rp;
int kind = 0;
for (int i = 0, off = 0; i <= nSplits; i++, off += 4) {
kind = computeOffsetQuad(mid, off, l, r);
@@ -1224,12 +1224,12 @@
default:
}
emitLineToRev(r[kind - 2], r[kind - 1]);
}
- this.cmx = (l[kind - 2] - r[kind - 2]) / 2f;
- this.cmy = (l[kind - 1] - r[kind - 1]) / 2f;
+ this.cmx = (l[kind - 2] - r[kind - 2]) / 2D;
+ this.cmy = (l[kind - 1] - r[kind - 1]) / 2D;
this.cdx = dxf;
this.cdy = dyf;
this.cx0 = xf;
this.cy0 = yf;
this.prev = DRAWING_OP_TO;
@@ -1246,20 +1246,20 @@
private static final int INITIAL_CURVES_COUNT = INITIAL_EDGES_COUNT << 1;
// types capacity = edges count (4096)
private static final int INITIAL_TYPES_COUNT = INITIAL_EDGES_COUNT;
- float[] curves;
+ double[] curves;
int end;
byte[] curveTypes;
- int numCurves;
+ int numDCurves;
// per-thread renderer context
- final RendererContext rdrCtx;
+ final DRendererContext rdrCtx;
// curves ref (dirty)
- final FloatArrayCache.Reference curves_ref;
+ final DoubleArrayCache.Reference curves_ref;
// curveTypes ref (dirty)
final ByteArrayCache.Reference curveTypes_ref;
// used marks (stats only)
int curveTypesUseMark;
@@ -1267,19 +1267,19 @@
/**
* Constructor
* @param rdrCtx per-thread renderer context
*/
- PolyStack(final RendererContext rdrCtx) {
+ PolyStack(final DRendererContext rdrCtx) {
this.rdrCtx = rdrCtx;
- curves_ref = rdrCtx.newDirtyFloatArrayRef(INITIAL_CURVES_COUNT); // 32K
+ curves_ref = rdrCtx.newDirtyDoubleArrayRef(INITIAL_CURVES_COUNT); // 32K
curves = curves_ref.initial;
curveTypes_ref = rdrCtx.newDirtyByteArrayRef(INITIAL_TYPES_COUNT); // 4K
curveTypes = curveTypes_ref.initial;
- numCurves = 0;
+ numDCurves = 0;
end = 0;
if (DO_STATS) {
curveTypesUseMark = 0;
curvesUseMark = 0;
@@ -1290,11 +1290,11 @@
* Disposes this PolyStack:
* clean up before reusing this instance
*/
void dispose() {
end = 0;
- numCurves = 0;
+ numDCurves = 0;
if (DO_STATS) {
rdrCtx.stats.stat_rdr_poly_stack_types.add(curveTypesUseMark);
rdrCtx.stats.stat_rdr_poly_stack_curves.add(curvesUseMark);
rdrCtx.stats.hist_rdr_poly_stack_curves.add(curvesUseMark);
@@ -1317,67 +1317,67 @@
rdrCtx.stats.stat_array_stroker_polystack_curves
.add(end + n);
}
curves = curves_ref.widenArray(curves, end, end + n);
}
- if (curveTypes.length <= numCurves) {
+ if (curveTypes.length <= numDCurves) {
if (DO_STATS) {
rdrCtx.stats.stat_array_stroker_polystack_curveTypes
- .add(numCurves + 1);
+ .add(numDCurves + 1);
}
curveTypes = curveTypes_ref.widenArray(curveTypes,
- numCurves,
- numCurves + 1);
+ numDCurves,
+ numDCurves + 1);
}
}
- void pushCubic(float x0, float y0,
- float x1, float y1,
- float x2, float y2)
+ void pushCubic(double x0, double y0,
+ double x1, double y1,
+ double x2, double y2)
{
ensureSpace(6);
- curveTypes[numCurves++] = TYPE_CUBICTO;
+ curveTypes[numDCurves++] = TYPE_CUBICTO;
// we reverse the coordinate order to make popping easier
- final float[] _curves = curves;
+ final double[] _curves = curves;
int e = end;
_curves[e++] = x2; _curves[e++] = y2;
_curves[e++] = x1; _curves[e++] = y1;
_curves[e++] = x0; _curves[e++] = y0;
end = e;
}
- void pushQuad(float x0, float y0,
- float x1, float y1)
+ void pushQuad(double x0, double y0,
+ double x1, double y1)
{
ensureSpace(4);
- curveTypes[numCurves++] = TYPE_QUADTO;
- final float[] _curves = curves;
+ curveTypes[numDCurves++] = TYPE_QUADTO;
+ final double[] _curves = curves;
int e = end;
_curves[e++] = x1; _curves[e++] = y1;
_curves[e++] = x0; _curves[e++] = y0;
end = e;
}
- void pushLine(float x, float y) {
+ void pushLine(double x, double y) {
ensureSpace(2);
- curveTypes[numCurves++] = TYPE_LINETO;
+ curveTypes[numDCurves++] = TYPE_LINETO;
curves[end++] = x; curves[end++] = y;
}
- void popAll(PathConsumer2D io) {
+ void popAll(DPathConsumer2D io) {
if (DO_STATS) {
// update used marks:
- if (numCurves > curveTypesUseMark) {
- curveTypesUseMark = numCurves;
+ if (numDCurves > curveTypesUseMark) {
+ curveTypesUseMark = numDCurves;
}
if (end > curvesUseMark) {
curvesUseMark = end;
}
}
final byte[] _curveTypes = curveTypes;
- final float[] _curves = curves;
- int nc = numCurves;
+ final double[] _curves = curves;
+ int nc = numDCurves;
int e = end;
while (nc != 0) {
switch(_curveTypes[--nc]) {
case TYPE_LINETO:
@@ -1396,18 +1396,18 @@
_curves[e+4], _curves[e+5]);
continue;
default:
}
}
- numCurves = 0;
+ numDCurves = 0;
end = 0;
}
@Override
public String toString() {
String ret = "";
- int nc = numCurves;
+ int nc = numDCurves;
int last = end;
int len;
while (nc != 0) {
switch(curveTypes[--nc]) {
case TYPE_LINETO:
< prev index next >