0N/A/*
2362N/A * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.awt.geom;
0N/A
0N/Aimport java.awt.geom.Rectangle2D;
0N/Aimport java.awt.geom.PathIterator;
0N/Aimport java.awt.geom.QuadCurve2D;
0N/Aimport java.util.Vector;
0N/A
0N/Afinal class Order3 extends Curve {
0N/A private double x0;
0N/A private double y0;
0N/A private double cx0;
0N/A private double cy0;
0N/A private double cx1;
0N/A private double cy1;
0N/A private double x1;
0N/A private double y1;
0N/A
0N/A private double xmin;
0N/A private double xmax;
0N/A
0N/A private double xcoeff0;
0N/A private double xcoeff1;
0N/A private double xcoeff2;
0N/A private double xcoeff3;
0N/A
0N/A private double ycoeff0;
0N/A private double ycoeff1;
0N/A private double ycoeff2;
0N/A private double ycoeff3;
0N/A
0N/A public static void insert(Vector curves, double tmp[],
0N/A double x0, double y0,
0N/A double cx0, double cy0,
0N/A double cx1, double cy1,
0N/A double x1, double y1,
0N/A int direction)
0N/A {
0N/A int numparams = getHorizontalParams(y0, cy0, cy1, y1, tmp);
0N/A if (numparams == 0) {
0N/A // We are using addInstance here to avoid inserting horisontal
0N/A // segments
0N/A addInstance(curves, x0, y0, cx0, cy0, cx1, cy1, x1, y1, direction);
0N/A return;
0N/A }
0N/A // Store coordinates for splitting at tmp[3..10]
0N/A tmp[3] = x0; tmp[4] = y0;
0N/A tmp[5] = cx0; tmp[6] = cy0;
0N/A tmp[7] = cx1; tmp[8] = cy1;
0N/A tmp[9] = x1; tmp[10] = y1;
0N/A double t = tmp[0];
0N/A if (numparams > 1 && t > tmp[1]) {
0N/A // Perform a "2 element sort"...
0N/A tmp[0] = tmp[1];
0N/A tmp[1] = t;
0N/A t = tmp[0];
0N/A }
0N/A split(tmp, 3, t);
0N/A if (numparams > 1) {
0N/A // Recalculate tmp[1] relative to the range [tmp[0]...1]
0N/A t = (tmp[1] - t) / (1 - t);
0N/A split(tmp, 9, t);
0N/A }
0N/A int index = 3;
0N/A if (direction == DECREASING) {
0N/A index += numparams * 6;
0N/A }
0N/A while (numparams >= 0) {
0N/A addInstance(curves,
0N/A tmp[index + 0], tmp[index + 1],
0N/A tmp[index + 2], tmp[index + 3],
0N/A tmp[index + 4], tmp[index + 5],
0N/A tmp[index + 6], tmp[index + 7],
0N/A direction);
0N/A numparams--;
0N/A if (direction == INCREASING) {
0N/A index += 6;
0N/A } else {
0N/A index -= 6;
0N/A }
0N/A }
0N/A }
0N/A
0N/A public static void addInstance(Vector curves,
0N/A double x0, double y0,
0N/A double cx0, double cy0,
0N/A double cx1, double cy1,
0N/A double x1, double y1,
0N/A int direction) {
0N/A if (y0 > y1) {
0N/A curves.add(new Order3(x1, y1, cx1, cy1, cx0, cy0, x0, y0,
0N/A -direction));
0N/A } else if (y1 > y0) {
0N/A curves.add(new Order3(x0, y0, cx0, cy0, cx1, cy1, x1, y1,
0N/A direction));
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * Return the count of the number of horizontal sections of the
0N/A * specified cubic Bezier curve. Put the parameters for the
0N/A * horizontal sections into the specified <code>ret</code> array.
0N/A * <p>
0N/A * If we examine the parametric equation in t, we have:
0N/A * Py(t) = C0(1-t)^3 + 3CP0 t(1-t)^2 + 3CP1 t^2(1-t) + C1 t^3
0N/A * = C0 - 3C0t + 3C0t^2 - C0t^3 +
0N/A * 3CP0t - 6CP0t^2 + 3CP0t^3 +
0N/A * 3CP1t^2 - 3CP1t^3 +
0N/A * C1t^3
0N/A * Py(t) = (C1 - 3CP1 + 3CP0 - C0) t^3 +
0N/A * (3C0 - 6CP0 + 3CP1) t^2 +
0N/A * (3CP0 - 3C0) t +
0N/A * (C0)
0N/A * If we take the derivative, we get:
0N/A * Py(t) = Dt^3 + At^2 + Bt + C
0N/A * dPy(t) = 3Dt^2 + 2At + B = 0
0N/A * 0 = 3*(C1 - 3*CP1 + 3*CP0 - C0)t^2
0N/A * + 2*(3*CP1 - 6*CP0 + 3*C0)t
0N/A * + (3*CP0 - 3*C0)
0N/A * 0 = 3*(C1 - 3*CP1 + 3*CP0 - C0)t^2
0N/A * + 3*2*(CP1 - 2*CP0 + C0)t
0N/A * + 3*(CP0 - C0)
0N/A * 0 = (C1 - CP1 - CP1 - CP1 + CP0 + CP0 + CP0 - C0)t^2
0N/A * + 2*(CP1 - CP0 - CP0 + C0)t
0N/A * + (CP0 - C0)
0N/A * 0 = (C1 - CP1 + CP0 - CP1 + CP0 - CP1 + CP0 - C0)t^2
0N/A * + 2*(CP1 - CP0 - CP0 + C0)t
0N/A * + (CP0 - C0)
0N/A * 0 = ((C1 - CP1) - (CP1 - CP0) - (CP1 - CP0) + (CP0 - C0))t^2
0N/A * + 2*((CP1 - CP0) - (CP0 - C0))t
0N/A * + (CP0 - C0)
0N/A * Note that this method will return 0 if the equation is a line,
0N/A * which is either always horizontal or never horizontal.
0N/A * Completely horizontal curves need to be eliminated by other
0N/A * means outside of this method.
0N/A */
0N/A public static int getHorizontalParams(double c0, double cp0,
0N/A double cp1, double c1,
0N/A double ret[]) {
0N/A if (c0 <= cp0 && cp0 <= cp1 && cp1 <= c1) {
0N/A return 0;
0N/A }
0N/A c1 -= cp1;
0N/A cp1 -= cp0;
0N/A cp0 -= c0;
0N/A ret[0] = cp0;
0N/A ret[1] = (cp1 - cp0) * 2;
0N/A ret[2] = (c1 - cp1 - cp1 + cp0);
0N/A int numroots = QuadCurve2D.solveQuadratic(ret, ret);
0N/A int j = 0;
0N/A for (int i = 0; i < numroots; i++) {
0N/A double t = ret[i];
0N/A // No splits at t==0 and t==1
0N/A if (t > 0 && t < 1) {
0N/A if (j < i) {
0N/A ret[j] = t;
0N/A }
0N/A j++;
0N/A }
0N/A }
0N/A return j;
0N/A }
0N/A
0N/A /*
0N/A * Split the cubic Bezier stored at coords[pos...pos+7] representing
0N/A * the parametric range [0..1] into two subcurves representing the
0N/A * parametric subranges [0..t] and [t..1]. Store the results back
0N/A * into the array at coords[pos...pos+7] and coords[pos+6...pos+13].
0N/A */
0N/A public static void split(double coords[], int pos, double t) {
0N/A double x0, y0, cx0, cy0, cx1, cy1, x1, y1;
0N/A coords[pos+12] = x1 = coords[pos+6];
0N/A coords[pos+13] = y1 = coords[pos+7];
0N/A cx1 = coords[pos+4];
0N/A cy1 = coords[pos+5];
0N/A x1 = cx1 + (x1 - cx1) * t;
0N/A y1 = cy1 + (y1 - cy1) * t;
0N/A x0 = coords[pos+0];
0N/A y0 = coords[pos+1];
0N/A cx0 = coords[pos+2];
0N/A cy0 = coords[pos+3];
0N/A x0 = x0 + (cx0 - x0) * t;
0N/A y0 = y0 + (cy0 - y0) * t;
0N/A cx0 = cx0 + (cx1 - cx0) * t;
0N/A cy0 = cy0 + (cy1 - cy0) * t;
0N/A cx1 = cx0 + (x1 - cx0) * t;
0N/A cy1 = cy0 + (y1 - cy0) * t;
0N/A cx0 = x0 + (cx0 - x0) * t;
0N/A cy0 = y0 + (cy0 - y0) * t;
0N/A coords[pos+2] = x0;
0N/A coords[pos+3] = y0;
0N/A coords[pos+4] = cx0;
0N/A coords[pos+5] = cy0;
0N/A coords[pos+6] = cx0 + (cx1 - cx0) * t;
0N/A coords[pos+7] = cy0 + (cy1 - cy0) * t;
0N/A coords[pos+8] = cx1;
0N/A coords[pos+9] = cy1;
0N/A coords[pos+10] = x1;
0N/A coords[pos+11] = y1;
0N/A }
0N/A
0N/A public Order3(double x0, double y0,
0N/A double cx0, double cy0,
0N/A double cx1, double cy1,
0N/A double x1, double y1,
0N/A int direction)
0N/A {
0N/A super(direction);
0N/A // REMIND: Better accuracy in the root finding methods would
0N/A // ensure that cys are in range. As it stands, they are never
0N/A // more than "1 mantissa bit" out of range...
0N/A if (cy0 < y0) cy0 = y0;
0N/A if (cy1 > y1) cy1 = y1;
0N/A this.x0 = x0;
0N/A this.y0 = y0;
0N/A this.cx0 = cx0;
0N/A this.cy0 = cy0;
0N/A this.cx1 = cx1;
0N/A this.cy1 = cy1;
0N/A this.x1 = x1;
0N/A this.y1 = y1;
0N/A xmin = Math.min(Math.min(x0, x1), Math.min(cx0, cx1));
0N/A xmax = Math.max(Math.max(x0, x1), Math.max(cx0, cx1));
0N/A xcoeff0 = x0;
0N/A xcoeff1 = (cx0 - x0) * 3.0;
0N/A xcoeff2 = (cx1 - cx0 - cx0 + x0) * 3.0;
0N/A xcoeff3 = x1 - (cx1 - cx0) * 3.0 - x0;
0N/A ycoeff0 = y0;
0N/A ycoeff1 = (cy0 - y0) * 3.0;
0N/A ycoeff2 = (cy1 - cy0 - cy0 + y0) * 3.0;
0N/A ycoeff3 = y1 - (cy1 - cy0) * 3.0 - y0;
0N/A YforT1 = YforT2 = YforT3 = y0;
0N/A }
0N/A
0N/A public int getOrder() {
0N/A return 3;
0N/A }
0N/A
0N/A public double getXTop() {
0N/A return x0;
0N/A }
0N/A
0N/A public double getYTop() {
0N/A return y0;
0N/A }
0N/A
0N/A public double getXBot() {
0N/A return x1;
0N/A }
0N/A
0N/A public double getYBot() {
0N/A return y1;
0N/A }
0N/A
0N/A public double getXMin() {
0N/A return xmin;
0N/A }
0N/A
0N/A public double getXMax() {
0N/A return xmax;
0N/A }
0N/A
0N/A public double getX0() {
0N/A return (direction == INCREASING) ? x0 : x1;
0N/A }
0N/A
0N/A public double getY0() {
0N/A return (direction == INCREASING) ? y0 : y1;
0N/A }
0N/A
0N/A public double getCX0() {
0N/A return (direction == INCREASING) ? cx0 : cx1;
0N/A }
0N/A
0N/A public double getCY0() {
0N/A return (direction == INCREASING) ? cy0 : cy1;
0N/A }
0N/A
0N/A public double getCX1() {
0N/A return (direction == DECREASING) ? cx0 : cx1;
0N/A }
0N/A
0N/A public double getCY1() {
0N/A return (direction == DECREASING) ? cy0 : cy1;
0N/A }
0N/A
0N/A public double getX1() {
0N/A return (direction == DECREASING) ? x0 : x1;
0N/A }
0N/A
0N/A public double getY1() {
0N/A return (direction == DECREASING) ? y0 : y1;
0N/A }
0N/A
0N/A private double TforY1;
0N/A private double YforT1;
0N/A private double TforY2;
0N/A private double YforT2;
0N/A private double TforY3;
0N/A private double YforT3;
0N/A
0N/A /*
0N/A * Solve the cubic whose coefficients are in the a,b,c,d fields and
0N/A * return the first root in the range [0, 1].
0N/A * The cubic solved is represented by the equation:
0N/A * x^3 + (ycoeff2)x^2 + (ycoeff1)x + (ycoeff0) = y
0N/A * @return the first valid root (in the range [0, 1])
0N/A */
0N/A public double TforY(double y) {
0N/A if (y <= y0) return 0;
0N/A if (y >= y1) return 1;
0N/A if (y == YforT1) return TforY1;
0N/A if (y == YforT2) return TforY2;
0N/A if (y == YforT3) return TforY3;
0N/A // From Numerical Recipes, 5.6, Quadratic and Cubic Equations
0N/A if (ycoeff3 == 0.0) {
0N/A // The cubic degenerated to quadratic (or line or ...).
0N/A return Order2.TforY(y, ycoeff0, ycoeff1, ycoeff2);
0N/A }
0N/A double a = ycoeff2 / ycoeff3;
0N/A double b = ycoeff1 / ycoeff3;
0N/A double c = (ycoeff0 - y) / ycoeff3;
0N/A int roots = 0;
0N/A double Q = (a * a - 3.0 * b) / 9.0;
0N/A double R = (2.0 * a * a * a - 9.0 * a * b + 27.0 * c) / 54.0;
0N/A double R2 = R * R;
0N/A double Q3 = Q * Q * Q;
0N/A double a_3 = a / 3.0;
0N/A double t;
0N/A if (R2 < Q3) {
0N/A double theta = Math.acos(R / Math.sqrt(Q3));
0N/A Q = -2.0 * Math.sqrt(Q);
0N/A t = refine(a, b, c, y, Q * Math.cos(theta / 3.0) - a_3);
0N/A if (t < 0) {
0N/A t = refine(a, b, c, y,
0N/A Q * Math.cos((theta + Math.PI * 2.0)/ 3.0) - a_3);
0N/A }
0N/A if (t < 0) {
0N/A t = refine(a, b, c, y,
0N/A Q * Math.cos((theta - Math.PI * 2.0)/ 3.0) - a_3);
0N/A }
0N/A } else {
0N/A boolean neg = (R < 0.0);
0N/A double S = Math.sqrt(R2 - Q3);
0N/A if (neg) {
0N/A R = -R;
0N/A }
0N/A double A = Math.pow(R + S, 1.0 / 3.0);
0N/A if (!neg) {
0N/A A = -A;
0N/A }
0N/A double B = (A == 0.0) ? 0.0 : (Q / A);
0N/A t = refine(a, b, c, y, (A + B) - a_3);
0N/A }
0N/A if (t < 0) {
0N/A //throw new InternalError("bad t");
0N/A double t0 = 0;
0N/A double t1 = 1;
0N/A while (true) {
0N/A t = (t0 + t1) / 2;
0N/A if (t == t0 || t == t1) {
0N/A break;
0N/A }
0N/A double yt = YforT(t);
0N/A if (yt < y) {
0N/A t0 = t;
0N/A } else if (yt > y) {
0N/A t1 = t;
0N/A } else {
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A if (t >= 0) {
0N/A TforY3 = TforY2;
0N/A YforT3 = YforT2;
0N/A TforY2 = TforY1;
0N/A YforT2 = YforT1;
0N/A TforY1 = t;
0N/A YforT1 = y;
0N/A }
0N/A return t;
0N/A }
0N/A
0N/A public double refine(double a, double b, double c,
0N/A double target, double t)
0N/A {
0N/A if (t < -0.1 || t > 1.1) {
0N/A return -1;
0N/A }
0N/A double y = YforT(t);
0N/A double t0, t1;
0N/A if (y < target) {
0N/A t0 = t;
0N/A t1 = 1;
0N/A } else {
0N/A t0 = 0;
0N/A t1 = t;
0N/A }
0N/A double origt = t;
0N/A double origy = y;
0N/A boolean useslope = true;
0N/A while (y != target) {
0N/A if (!useslope) {
0N/A double t2 = (t0 + t1) / 2;
0N/A if (t2 == t0 || t2 == t1) {
0N/A break;
0N/A }
0N/A t = t2;
0N/A } else {
0N/A double slope = dYforT(t, 1);
0N/A if (slope == 0) {
0N/A useslope = false;
0N/A continue;
0N/A }
0N/A double t2 = t + ((target - y) / slope);
0N/A if (t2 == t || t2 <= t0 || t2 >= t1) {
0N/A useslope = false;
0N/A continue;
0N/A }
0N/A t = t2;
0N/A }
0N/A y = YforT(t);
0N/A if (y < target) {
0N/A t0 = t;
0N/A } else if (y > target) {
0N/A t1 = t;
0N/A } else {
0N/A break;
0N/A }
0N/A }
0N/A boolean verbose = false;
0N/A if (false && t >= 0 && t <= 1) {
0N/A y = YforT(t);
0N/A long tdiff = diffbits(t, origt);
0N/A long ydiff = diffbits(y, origy);
0N/A long yerr = diffbits(y, target);
0N/A if (yerr > 0 || (verbose && tdiff > 0)) {
0N/A System.out.println("target was y = "+target);
0N/A System.out.println("original was y = "+origy+", t = "+origt);
0N/A System.out.println("final was y = "+y+", t = "+t);
0N/A System.out.println("t diff is "+tdiff);
0N/A System.out.println("y diff is "+ydiff);
0N/A System.out.println("y error is "+yerr);
0N/A double tlow = prev(t);
0N/A double ylow = YforT(tlow);
0N/A double thi = next(t);
0N/A double yhi = YforT(thi);
0N/A if (Math.abs(target - ylow) < Math.abs(target - y) ||
0N/A Math.abs(target - yhi) < Math.abs(target - y))
0N/A {
0N/A System.out.println("adjacent y's = ["+ylow+", "+yhi+"]");
0N/A }
0N/A }
0N/A }
0N/A return (t > 1) ? -1 : t;
0N/A }
0N/A
0N/A public double XforY(double y) {
0N/A if (y <= y0) {
0N/A return x0;
0N/A }
0N/A if (y >= y1) {
0N/A return x1;
0N/A }
0N/A return XforT(TforY(y));
0N/A }
0N/A
0N/A public double XforT(double t) {
0N/A return (((xcoeff3 * t) + xcoeff2) * t + xcoeff1) * t + xcoeff0;
0N/A }
0N/A
0N/A public double YforT(double t) {
0N/A return (((ycoeff3 * t) + ycoeff2) * t + ycoeff1) * t + ycoeff0;
0N/A }
0N/A
0N/A public double dXforT(double t, int deriv) {
0N/A switch (deriv) {
0N/A case 0:
0N/A return (((xcoeff3 * t) + xcoeff2) * t + xcoeff1) * t + xcoeff0;
0N/A case 1:
0N/A return ((3 * xcoeff3 * t) + 2 * xcoeff2) * t + xcoeff1;
0N/A case 2:
0N/A return (6 * xcoeff3 * t) + 2 * xcoeff2;
0N/A case 3:
0N/A return 6 * xcoeff3;
0N/A default:
0N/A return 0;
0N/A }
0N/A }
0N/A
0N/A public double dYforT(double t, int deriv) {
0N/A switch (deriv) {
0N/A case 0:
0N/A return (((ycoeff3 * t) + ycoeff2) * t + ycoeff1) * t + ycoeff0;
0N/A case 1:
0N/A return ((3 * ycoeff3 * t) + 2 * ycoeff2) * t + ycoeff1;
0N/A case 2:
0N/A return (6 * ycoeff3 * t) + 2 * ycoeff2;
0N/A case 3:
0N/A return 6 * ycoeff3;
0N/A default:
0N/A return 0;
0N/A }
0N/A }
0N/A
0N/A public double nextVertical(double t0, double t1) {
0N/A double eqn[] = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3};
0N/A int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);
0N/A for (int i = 0; i < numroots; i++) {
0N/A if (eqn[i] > t0 && eqn[i] < t1) {
0N/A t1 = eqn[i];
0N/A }
0N/A }
0N/A return t1;
0N/A }
0N/A
0N/A public void enlarge(Rectangle2D r) {
0N/A r.add(x0, y0);
0N/A double eqn[] = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3};
0N/A int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);
0N/A for (int i = 0; i < numroots; i++) {
0N/A double t = eqn[i];
0N/A if (t > 0 && t < 1) {
0N/A r.add(XforT(t), YforT(t));
0N/A }
0N/A }
0N/A r.add(x1, y1);
0N/A }
0N/A
0N/A public Curve getSubCurve(double ystart, double yend, int dir) {
0N/A if (ystart <= y0 && yend >= y1) {
0N/A return getWithDirection(dir);
0N/A }
0N/A double eqn[] = new double[14];
0N/A double t0, t1;
0N/A t0 = TforY(ystart);
0N/A t1 = TforY(yend);
0N/A eqn[0] = x0;
0N/A eqn[1] = y0;
0N/A eqn[2] = cx0;
0N/A eqn[3] = cy0;
0N/A eqn[4] = cx1;
0N/A eqn[5] = cy1;
0N/A eqn[6] = x1;
0N/A eqn[7] = y1;
0N/A if (t0 > t1) {
0N/A /* This happens in only rare cases where ystart is
0N/A * very near yend and solving for the yend root ends
0N/A * up stepping slightly lower in t than solving for
0N/A * the ystart root.
0N/A * Ideally we might want to skip this tiny little
0N/A * segment and just fudge the surrounding coordinates
0N/A * to bridge the gap left behind, but there is no way
0N/A * to do that from here. Higher levels could
0N/A * potentially eliminate these tiny "fixup" segments,
0N/A * but not without a lot of extra work on the code that
0N/A * coalesces chains of curves into subpaths. The
0N/A * simplest solution for now is to just reorder the t
0N/A * values and chop out a miniscule curve piece.
0N/A */
0N/A double t = t0;
0N/A t0 = t1;
0N/A t1 = t;
0N/A }
0N/A if (t1 < 1) {
0N/A split(eqn, 0, t1);
0N/A }
0N/A int i;
0N/A if (t0 <= 0) {
0N/A i = 0;
0N/A } else {
0N/A split(eqn, 0, t0 / t1);
0N/A i = 6;
0N/A }
0N/A return new Order3(eqn[i+0], ystart,
0N/A eqn[i+2], eqn[i+3],
0N/A eqn[i+4], eqn[i+5],
0N/A eqn[i+6], yend,
0N/A dir);
0N/A }
0N/A
0N/A public Curve getReversedCurve() {
0N/A return new Order3(x0, y0, cx0, cy0, cx1, cy1, x1, y1, -direction);
0N/A }
0N/A
0N/A public int getSegment(double coords[]) {
0N/A if (direction == INCREASING) {
0N/A coords[0] = cx0;
0N/A coords[1] = cy0;
0N/A coords[2] = cx1;
0N/A coords[3] = cy1;
0N/A coords[4] = x1;
0N/A coords[5] = y1;
0N/A } else {
0N/A coords[0] = cx1;
0N/A coords[1] = cy1;
0N/A coords[2] = cx0;
0N/A coords[3] = cy0;
0N/A coords[4] = x0;
0N/A coords[5] = y0;
0N/A }
0N/A return PathIterator.SEG_CUBICTO;
0N/A }
0N/A
0N/A public String controlPointString() {
0N/A return (("("+round(getCX0())+", "+round(getCY0())+"), ")+
0N/A ("("+round(getCX1())+", "+round(getCY1())+"), "));
0N/A }
0N/A}