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 * 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 * 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 * 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. 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 0N/A // We are using addInstance here to avoid inserting horisontal 0N/A // assert(numparams == 1); 0N/A * Return the count of the number of horizontal sections of the 0N/A * specified quadratic Bezier curve. Put the parameters for the 0N/A * horizontal sections into the specified <code>ret</code> array. 0N/A * If we examine the parametric equation in t, we have: 0N/A * Py(t) = C0*(1-t)^2 + 2*CP*t*(1-t) + C1*t^2 0N/A * = C0 - 2*C0*t + C0*t^2 + 2*CP*t - 2*CP*t^2 + C1*t^2 0N/A * = C0 + (2*CP - 2*C0)*t + (C0 - 2*CP + C1)*t^2 0N/A * Py(t) = (C0 - 2*CP + C1)*t^2 + (2*CP - 2*C0)*t + (C0) 0N/A * If we take the derivative, we get: 0N/A * Py(t) = At^2 + Bt + C 0N/A * dPy(t) = 2At + B = 0 0N/A * 2*(C0 - 2*CP + C1)t + 2*(CP - C0) = 0 0N/A * 2*(C0 - 2*CP + C1)t = 2*(C0 - CP) 0N/A * t = 2*(C0 - CP) / 2*(C0 - 2*CP + C1) 0N/A * t = (C0 - CP) / (C0 - CP + C1 - CP) 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 // If denom == 0 then cp == (c0+c1)/2 and we have a line. 0N/A // No splits at t==0 and t==1 0N/A if (t <=
0 || t >=
1) {
0N/A * Split the quadratic Bezier stored at coords[pos...pos+5] representing 0N/A * the paramtric 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+5] and coords[pos+4...pos+9]. 0N/A // REMIND: Better accuracy in the root finding methods would 0N/A // ensure that cy0 is in range. As it stands, it is never 0N/A // more than "1 mantissa bit" out of range... 0N/A // The caller should have already eliminated y values 0N/A // outside of the y0 to y1 range. 0N/A // The quadratic parabola has degenerated to a line. 0N/A // ycoeff1 should not be 0.0 since we have already eliminated 0N/A // totally horizontal lines, but if it is, then we will generate 0N/A // infinity here for the root, which will not be in the [0,1] 0N/A // range so we will pass to the failure code below. 0N/A // From Numerical Recipes, 5.6, Quadratic and Cubic Equations 0N/A // If d < 0.0, then there are no roots 0N/A // For accuracy, calculate one root using: 0N/A // (-ycoeff1 +/- d) / 2ycoeff2 0N/A // and the other using: 0N/A // 2ycoeff0 / (-ycoeff1 +/- d) 0N/A // Choose the sign of the +/- so that ycoeff1+d 0N/A // gets larger in magnitude 0N/A // We already tested ycoeff2 for being 0 above 0N/A /* We failed to find a root in [0,1]. What could have gone wrong? 0N/A * First, remember that these curves are constructed to be monotonic 0N/A * in Y and totally horizontal curves have already been eliminated. 0N/A * Now keep in mind that the Y coefficients of the polynomial form 0N/A * of the curve are calculated from the Y coordinates which define 0N/A * our curve. They should theoretically define the same curve, 0N/A * but they can be off by a couple of bits of precision after the 0N/A * math is done and so can represent a slightly modified curve. 0N/A * This is normally not an issue except when we have solutions near 0N/A * the endpoints. Since the answers we get from solving the polynomial 0N/A * may be off by a few bits that means that they could lie just a 0N/A * few bits of precision outside the [0,1] range. 0N/A * Another problem could be that while the parametric curve defined 0N/A * by the Y coordinates has a local minima or maxima at or just 0N/A * outside of the endpoints, the polynomial form might express 0N/A * that same min/max just inside of and just shy of the Y coordinate 0N/A * of that endpoint. In that case, if we solve for a Y coordinate 0N/A * at or near that endpoint, we may be solving for a Y coordinate 0N/A * that is below that minima or above that maxima and we would find 0N/A * no solutions at all. 0N/A * In either case, we can assume that y is so near one of the 0N/A * endpoints that we can just collapse it onto the nearest endpoint 0N/A * without losing more than a couple of bits of precision. 0N/A // First calculate the midpoint between y0 and y1 and choose to 0N/A // return either 0.0 or 1.0 depending on whether y is above 0N/A // or below the midpoint... 0N/A // Note that we subtracted y from ycoeff0 above so both y0 and y1 0N/A // will be "relative to y" so we are really just looking at where 0N/A // zero falls with respect to the "relative midpoint" here. 0N/A return (
0 < (
y0 +
y1) /
2) ?
0.0 :
1.0;
0N/A if (t >
0 && t <
1) {
0N/A double eqn[] =
new double[
10];