< prev index next >

modules/javafx.graphics/src/main/java/com/sun/marlin/DStroker.java

Print this page

        

*** 69,79 **** 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 double ROUND_JOIN_THRESHOLD = 1000/65536d; private static final double C = 0.5522847498307933d; private static final int MAX_N_CURVES = 11; --- 69,79 ---- 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 double ROUND_JOIN_THRESHOLD = 1000.0d/65536.0d; private static final double C = 0.5522847498307933d; private static final int MAX_N_CURVES = 11;
*** 151,162 **** int joinStyle, double miterLimit) { this.out = pc2d; ! this.lineWidth2 = lineWidth / 2d; ! this.invHalfLineWidth2Sq = 1d / (2d * lineWidth2 * lineWidth2); this.capStyle = capStyle; this.joinStyle = joinStyle; double limit = miterLimit * lineWidth2; this.miterLimitSq = limit * limit; --- 151,162 ---- int joinStyle, double miterLimit) { this.out = pc2d; ! this.lineWidth2 = lineWidth / 2.0d; ! this.invHalfLineWidth2Sq = 1.0d / (2.0d * lineWidth2 * lineWidth2); this.capStyle = capStyle; this.joinStyle = joinStyle; double limit = miterLimit * lineWidth2; this.miterLimitSq = limit * limit;
*** 175,204 **** void dispose() { reverse.dispose(); if (DO_CLEAN_DIRTY) { // Force zero-fill dirty arrays: ! 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 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 = Math.sqrt(len); m[0] = (ly * w) / len; m[1] = -(lx * w) / len; } } --- 175,204 ---- void dispose() { reverse.dispose(); if (DO_CLEAN_DIRTY) { // Force zero-fill dirty arrays: ! Arrays.fill(offset0, 0.0d); ! Arrays.fill(offset1, 0.0d); ! Arrays.fill(offset2, 0.0d); ! Arrays.fill(miter, 0.0d); ! Arrays.fill(middle, 0.0d); ! Arrays.fill(lp, 0.0d); ! Arrays.fill(rp, 0.0d); ! Arrays.fill(subdivTs, 0.0d); } } private static void computeOffset(final double lx, final double ly, final double w, final double[] m) { double len = lx*lx + ly*ly; ! if (len == 0.0d) { ! m[0] = 0.0d; ! m[1] = 0.0d; } else { ! len = Math.sqrt(len); m[0] = (ly * w) / len; m[1] = -(lx * w) / len; } }
*** 219,229 **** private void drawRoundJoin(double x, double y, double omx, double omy, double mx, double my, boolean rev, double threshold) { ! if ((omx == 0d && omy == 0d) || (mx == 0d && my == 0d)) { return; } double domx = omx - mx; double domy = omy - my; --- 219,229 ---- private void drawRoundJoin(double x, double y, double omx, double omy, double mx, double my, boolean rev, double threshold) { ! if ((omx == 0.0d && omy == 0.0d) || (mx == 0.0d && my == 0.0d)) { return; } double domx = omx - mx; double domy = omy - my;
*** 251,261 **** // (ext is the angle between omx,omy and mx,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 >= 0d) ? 1 : 2; switch (numCurves) { case 1: drawBezApproxForArc(cx, cy, omx, omy, mx, my, rev); break; --- 251,261 ---- // (ext is the angle between omx,omy and mx,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 >= 0.0d) ? 1 : 2; switch (numCurves) { case 1: drawBezApproxForArc(cx, cy, omx, omy, mx, my, rev); break;
*** 273,283 **** // 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). 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. --- 273,283 ---- // 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). 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.
*** 311,322 **** // 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|. ! 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 double x1 = cx + omx; --- 311,322 ---- // 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|. ! double cv = ((4.0d / 3.0d) * Math.sqrt(0.5d - cosext2) / ! (1.0d + Math.sqrt(cosext2 + 0.5d))); // if clockwise, we need to negate cv. if (rev) { // rev is equivalent to isCW(omx, omy, mx, my) cv = -cv; } final double x1 = cx + omx;
*** 393,405 **** // 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). double den = x10*y10p - x10p*y10; ! if (den == 0d) { ! m[off++] = (x0 + x0p) / 2d; ! m[off] = (y0 + y0p) / 2d; return; } double t = x10p*(y0-y0p) - y10p*(x0-x0p); t /= den; m[off++] = x0 + t*x10; --- 393,405 ---- // 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). double den = x10*y10p - x10p*y10; ! if (den == 0.0d) { ! m[off++] = (x0 + x0p) / 2.0d; ! m[off] = (y0 + y0p) / 2.0d; return; } double t = x10p*(y0-y0p) - y10p*(x0-x0p); t /= den; m[off++] = x0 + t*x10;
*** 411,422 **** final double dx, final double dy, double omx, double omy, double mx, double my, boolean rev) { if ((mx == omx && my == omy) || ! (pdx == 0d && pdy == 0d) || ! (dx == 0d && dy == 0d)) { return; } if (rev) { --- 411,422 ---- final double dx, final double dy, double omx, double omy, double mx, double my, boolean rev) { if ((mx == omx && my == omy) || ! (pdx == 0.0d && pdy == 0.0d) || ! (dx == 0.0d && dy == 0.0d)) { return; } if (rev) {
*** 449,469 **** if (prev == DRAWING_OP_TO) { finish(); } this.sx0 = this.cx0 = x0; this.sy0 = this.cy0 = y0; ! this.cdx = this.sdx = 1d; ! this.cdy = this.sdy = 0d; this.prev = MOVE_TO; } @Override 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 double mx = offset0[0]; final double my = offset0[1]; --- 449,469 ---- if (prev == DRAWING_OP_TO) { finish(); } this.sx0 = this.cx0 = x0; this.sy0 = this.cy0 = y0; ! this.cdx = this.sdx = 1.0d; ! this.cdy = this.sdy = 0.0d; this.prev = MOVE_TO; } @Override public void lineTo(double x1, double y1) { double dx = x1 - cx0; double dy = y1 - cy0; ! if (dx == 0.0d && dy == 0.0d) { ! dx = 1.0d; } computeOffset(dx, dy, lineWidth2, offset0); final double mx = offset0[0]; final double my = offset0[1];
*** 489,502 **** if (prev != DRAWING_OP_TO) { if (prev == CLOSE) { return; } emitMoveTo(cx0, cy0 - lineWidth2); ! this.cmx = this.smx = 0d; this.cmy = this.smy = -lineWidth2; ! this.cdx = this.sdx = 1d; ! this.cdy = this.sdy = 0d; finish(); return; } if (cx0 != sx0 || cy0 != sy0) { --- 489,502 ---- if (prev != DRAWING_OP_TO) { if (prev == CLOSE) { return; } emitMoveTo(cx0, cy0 - lineWidth2); ! this.cmx = this.smx = 0.0d; this.cmy = this.smy = -lineWidth2; ! this.cdx = this.sdx = 1.0d; ! this.cdy = this.sdy = 0.0d; finish(); return; } if (cx0 != sx0 || cy0 != sy0) {
*** 692,703 **** 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, 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; --- 692,703 ---- 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, 6.0d * Math.ulp(y2)); ! final boolean p3eqp4 = within(x3,y3,x4,y4, 6.0d * Math.ulp(y4)); if (p1eqp2 && p3eqp4) { getLineOffsets(x1, y1, x4, y4, leftOff, rightOff); return 4; } else if (p1eqp2) { dx1 = x3 - x1;
*** 709,719 **** // if p2-p1 and p4-p3 are parallel, that must mean this curve is a line double dotsq = (dx1 * dx4 + dy1 * dy4); dotsq *= 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 --- 709,719 ---- // if p2-p1 and p4-p3 are parallel, that must mean this curve is a line double dotsq = (dx1 * dx4 + dy1 * dy4); dotsq *= dotsq; double l1sq = dx1 * dx1 + dy1 * dy1, l4sq = dx4 * dx4 + dy4 * dy4; ! if (DHelpers.within(dotsq, l1sq * l4sq, 4.0d * 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,772 **** // [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. ! 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. 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 --- 761,772 ---- // [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. ! double x = (x1 + 3.0d * (x2 + x3) + x4) / 8.0d; ! double y = (y1 + 3.0d * (y2 + y3) + y4) / 8.0d; // (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. 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
*** 780,793 **** 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); double x2p, y2p, x3p, y3p; x2p = x1p + c1*dx1; --- 780,793 ---- 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 = 4.0d / (3.0d * (dx1 * dy4 - dy1 * dx4)); ! double two_pi_m_p1_m_p4x = 2.0d * xi - x1p - x4p; ! double two_pi_m_p1_m_p4y = 2.0d * 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); double x2p, y2p, x3p, y3p; x2p = x1p + c1*dx1;
*** 799,813 **** 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 - 2d * offset1[0]; yi = yi - 2d * offset1[1]; x4p = x4 - offset2[0]; y4p = y4 - offset2[1]; ! 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; --- 799,813 ---- 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 - 2.0d * offset1[0]; yi = yi - 2.0d * offset1[1]; x4p = x4 - offset2[0]; y4p = y4 - offset2[1]; ! two_pi_m_p1_m_p4x = 2.0d * xi - x1p - x4p; ! two_pi_m_p1_m_p4y = 2.0d * 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;
*** 844,865 **** // 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, 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 double dotsq = (dx1 * dx3 + dy1 * dy3); dotsq *= 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 --- 844,865 ---- // 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, 6.0d * Math.ulp(y2)); ! final boolean p2eqp3 = within(x2,y2,x3,y3, 6.0d * 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 double dotsq = (dx1 * dx3 + dy1 * dy3); dotsq *= dotsq; double l1sq = dx1 * dx1 + dy1 * dy1, l3sq = dx3 * dx3 + dy3 * dy3; ! if (DHelpers.within(dotsq, l1sq * l3sq, 4.0d * 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
*** 882,1012 **** rightOff[0] = x1p; rightOff[1] = y1p; rightOff[4] = x3p; rightOff[5] = y3p; return 6; } - // If this class is compiled with ecj, then Hotspot crashes when OSR - // compiling this function. See bugs 7004570 and 6675699 - // 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 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 == 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 == 0d && dys == 0d); - boolean p3eqp4 = (dxf == 0d && dyf == 0d); - if (p1eqp2) { - dxs = middle[4] - middle[0]; - dys = middle[5] - middle[1]; - 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 == 0d && dyf == 0d) { - dxf = middle[6] - middle[0]; - dyf = middle[7] - middle[1]; - } - } - } - 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.1d && Math.abs(dys) < 0.1d) { - double len = Math.sqrt(dxs*dxs + dys*dys); - dxs /= len; - dys /= len; - } - 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 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(); - - switch (type) { - case 8: - kind = computeOffsetCubic(middle, curCurveOff, lp, rp); - break; - case 6: - kind = computeOffsetQuad(middle, curCurveOff, 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]); - break; - case 6: - emitQuadTo(lp[2], lp[3], lp[4], lp[5]); - emitQuadToRev(rp[0], rp[1], rp[2], rp[3]); - break; - case 4: - emitLineTo(lp[2], lp[3]); - emitLineTo(rp[0], rp[1], true); - break; - } - emitLineTo(rp[kind - 2], rp[kind - 1], true); - } - - this.cmx = (lp[kind - 2] - rp[kind - 2]) / 2; - this.cmy = (lp[kind - 1] - rp[kind - 1]) / 2; - this.cdx = dxf; - this.cdy = dyf; - this.cx0 = xf; - this.cy0 = yf; - this.prev = DRAWING_OP_TO; - } - ****************************** 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 DCurve c, double[] pts, double[] ts, final int type, final double w) { 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 != 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 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]; --- 882,906 ---- rightOff[0] = x1p; rightOff[1] = y1p; rightOff[4] = x3p; rightOff[5] = y3p; return 6; } // 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 DCurve c, double[] pts, double[] ts, final int type, final double w) { 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 != 0.0d && x12 != 0.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 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];
*** 1058,1123 **** 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 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 == 0d && dys == 0d); ! boolean p3eqp4 = (dxf == 0d && dyf == 0d); if (p1eqp2) { dxs = mid[4] - mid[0]; dys = mid[5] - mid[1]; ! 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 == 0d && dyf == 0d) { dxf = mid[6] - mid[0]; dyf = mid[7] - mid[1]; } } ! 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.1d && Math.abs(dys) < 0.1d) { ! double len = Math.sqrt(dxs*dxs + dys*dys); dxs /= len; dys /= len; } 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); ! double prevT = 0d; for (int i = 0, off = 0; i < nSplits; i++, off += 6) { final double t = subdivTs[i]; ! DHelpers.subdivideCubicAt((t - prevT) / (1d - prevT), mid, off, mid, off, mid, off + 6); prevT = t; } final double[] l = lp; --- 952,1014 ---- mid[0] = cx0; mid[1] = cy0; mid[2] = x1; mid[3] = y1; mid[4] = x2; mid[5] = y2; mid[6] = x3; mid[7] = y3; // need these so we can update the state at the end of this method 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 == 0.0d && dys == 0.0d); ! boolean p3eqp4 = (dxf == 0.0d && dyf == 0.0d); if (p1eqp2) { dxs = mid[4] - mid[0]; dys = mid[5] - mid[1]; ! if (dxs == 0.0d && dys == 0.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 == 0.0d && dyf == 0.0d) { dxf = mid[6] - mid[0]; dyf = mid[7] - mid[1]; } } ! if (dxs == 0.0d && dys == 0.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.1d && Math.abs(dys) < 0.1d) { ! double len = Math.sqrt(dxs*dxs + dys*dys); dxs /= len; dys /= len; } 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); ! double prevT = 0.0d; for (int i = 0, off = 0; i < nSplits; i++, off += 6) { final double t = subdivTs[i]; ! DHelpers.subdivideCubicAt((t - prevT) / (1.0d - prevT), mid, off, mid, off, mid, off + 6); prevT = t; } final double[] l = lp;
*** 1141,1152 **** default: } emitLineToRev(r[kind - 2], r[kind - 1]); } ! 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; --- 1032,1043 ---- default: } emitLineToRev(r[kind - 2], r[kind - 1]); } ! this.cmx = (l[kind - 2] - r[kind - 2]) / 2.0d; ! this.cmy = (l[kind - 1] - r[kind - 1]) / 2.0d; this.cdx = dxf; this.cdy = dyf; this.cx0 = xf; this.cy0 = yf; this.prev = DRAWING_OP_TO;
*** 1157,1206 **** 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 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 == 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.1d && Math.abs(dys) < 0.1d) { ! double len = Math.sqrt(dxs*dxs + dys*dys); dxs /= len; dys /= len; } 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); ! double prevt = 0d; for (int i = 0, off = 0; i < nSplits; i++, off += 4) { final double t = subdivTs[i]; ! DHelpers.subdivideQuadAt((t - prevt) / (1d - prevt), mid, off, mid, off, mid, off + 4); prevt = t; } final double[] l = lp; --- 1048,1094 ---- mid[0] = cx0; mid[1] = cy0; mid[2] = x1; mid[3] = y1; mid[4] = x2; mid[5] = y2; // need these so we can update the state at the end of this method 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 == 0.0d && dys == 0.0d) || (dxf == 0.0d && dyf == 0.0d)) { dxs = dxf = mid[4] - mid[0]; dys = dyf = mid[5] - mid[1]; } ! if (dxs == 0.0d && dys == 0.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.1d && Math.abs(dys) < 0.1d) { ! double len = Math.sqrt(dxs*dxs + dys*dys); dxs /= len; dys /= len; } 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); ! double prevt = 0.0d; for (int i = 0, off = 0; i < nSplits; i++, off += 4) { final double t = subdivTs[i]; ! DHelpers.subdivideQuadAt((t - prevt) / (1.0d - prevt), mid, off, mid, off, mid, off + 4); prevt = t; } final double[] l = lp;
*** 1224,1235 **** default: } emitLineToRev(r[kind - 2], r[kind - 1]); } ! 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; --- 1112,1123 ---- default: } emitLineToRev(r[kind - 2], r[kind - 1]); } ! this.cmx = (l[kind - 2] - r[kind - 2]) / 2.0d; ! this.cmy = (l[kind - 1] - r[kind - 1]) / 2.0d; this.cdx = dxf; this.cdy = dyf; this.cx0 = xf; this.cy0 = yf; this.prev = DRAWING_OP_TO;
< prev index next >