feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
561
jdkSrc/jdk8/sun/awt/geom/AreaOp.java
Normal file
561
jdkSrc/jdk8/sun/awt/geom/AreaOp.java
Normal file
@@ -0,0 +1,561 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.awt.geom;
|
||||
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Comparator;
|
||||
import java.util.Arrays;
|
||||
|
||||
public abstract class AreaOp {
|
||||
public static abstract class CAGOp extends AreaOp {
|
||||
boolean inLeft;
|
||||
boolean inRight;
|
||||
boolean inResult;
|
||||
|
||||
public void newRow() {
|
||||
inLeft = false;
|
||||
inRight = false;
|
||||
inResult = false;
|
||||
}
|
||||
|
||||
public int classify(Edge e) {
|
||||
if (e.getCurveTag() == CTAG_LEFT) {
|
||||
inLeft = !inLeft;
|
||||
} else {
|
||||
inRight = !inRight;
|
||||
}
|
||||
boolean newClass = newClassification(inLeft, inRight);
|
||||
if (inResult == newClass) {
|
||||
return ETAG_IGNORE;
|
||||
}
|
||||
inResult = newClass;
|
||||
return (newClass ? ETAG_ENTER : ETAG_EXIT);
|
||||
}
|
||||
|
||||
public int getState() {
|
||||
return (inResult ? RSTAG_INSIDE : RSTAG_OUTSIDE);
|
||||
}
|
||||
|
||||
public abstract boolean newClassification(boolean inLeft,
|
||||
boolean inRight);
|
||||
}
|
||||
|
||||
public static class AddOp extends CAGOp {
|
||||
public boolean newClassification(boolean inLeft, boolean inRight) {
|
||||
return (inLeft || inRight);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SubOp extends CAGOp {
|
||||
public boolean newClassification(boolean inLeft, boolean inRight) {
|
||||
return (inLeft && !inRight);
|
||||
}
|
||||
}
|
||||
|
||||
public static class IntOp extends CAGOp {
|
||||
public boolean newClassification(boolean inLeft, boolean inRight) {
|
||||
return (inLeft && inRight);
|
||||
}
|
||||
}
|
||||
|
||||
public static class XorOp extends CAGOp {
|
||||
public boolean newClassification(boolean inLeft, boolean inRight) {
|
||||
return (inLeft != inRight);
|
||||
}
|
||||
}
|
||||
|
||||
public static class NZWindOp extends AreaOp {
|
||||
private int count;
|
||||
|
||||
public void newRow() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
public int classify(Edge e) {
|
||||
// Note: the right curves should be an empty set with this op...
|
||||
// assert(e.getCurveTag() == CTAG_LEFT);
|
||||
int newCount = count;
|
||||
int type = (newCount == 0 ? ETAG_ENTER : ETAG_IGNORE);
|
||||
newCount += e.getCurve().getDirection();
|
||||
count = newCount;
|
||||
return (newCount == 0 ? ETAG_EXIT : type);
|
||||
}
|
||||
|
||||
public int getState() {
|
||||
return ((count == 0) ? RSTAG_OUTSIDE : RSTAG_INSIDE);
|
||||
}
|
||||
}
|
||||
|
||||
public static class EOWindOp extends AreaOp {
|
||||
private boolean inside;
|
||||
|
||||
public void newRow() {
|
||||
inside = false;
|
||||
}
|
||||
|
||||
public int classify(Edge e) {
|
||||
// Note: the right curves should be an empty set with this op...
|
||||
// assert(e.getCurveTag() == CTAG_LEFT);
|
||||
boolean newInside = !inside;
|
||||
inside = newInside;
|
||||
return (newInside ? ETAG_ENTER : ETAG_EXIT);
|
||||
}
|
||||
|
||||
public int getState() {
|
||||
return (inside ? RSTAG_INSIDE : RSTAG_OUTSIDE);
|
||||
}
|
||||
}
|
||||
|
||||
private AreaOp() {
|
||||
}
|
||||
|
||||
/* Constants to tag the left and right curves in the edge list */
|
||||
public static final int CTAG_LEFT = 0;
|
||||
public static final int CTAG_RIGHT = 1;
|
||||
|
||||
/* Constants to classify edges */
|
||||
public static final int ETAG_IGNORE = 0;
|
||||
public static final int ETAG_ENTER = 1;
|
||||
public static final int ETAG_EXIT = -1;
|
||||
|
||||
/* Constants used to classify result state */
|
||||
public static final int RSTAG_INSIDE = 1;
|
||||
public static final int RSTAG_OUTSIDE = -1;
|
||||
|
||||
public abstract void newRow();
|
||||
|
||||
public abstract int classify(Edge e);
|
||||
|
||||
public abstract int getState();
|
||||
|
||||
public Vector calculate(Vector left, Vector right) {
|
||||
Vector edges = new Vector();
|
||||
addEdges(edges, left, AreaOp.CTAG_LEFT);
|
||||
addEdges(edges, right, AreaOp.CTAG_RIGHT);
|
||||
edges = pruneEdges(edges);
|
||||
if (false) {
|
||||
System.out.println("result: ");
|
||||
int numcurves = edges.size();
|
||||
Curve[] curvelist = (Curve[]) edges.toArray(new Curve[numcurves]);
|
||||
for (int i = 0; i < numcurves; i++) {
|
||||
System.out.println("curvelist["+i+"] = "+curvelist[i]);
|
||||
}
|
||||
}
|
||||
return edges;
|
||||
}
|
||||
|
||||
private static void addEdges(Vector edges, Vector curves, int curvetag) {
|
||||
Enumeration enum_ = curves.elements();
|
||||
while (enum_.hasMoreElements()) {
|
||||
Curve c = (Curve) enum_.nextElement();
|
||||
if (c.getOrder() > 0) {
|
||||
edges.add(new Edge(c, curvetag));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Comparator YXTopComparator = new Comparator() {
|
||||
public int compare(Object o1, Object o2) {
|
||||
Curve c1 = ((Edge) o1).getCurve();
|
||||
Curve c2 = ((Edge) o2).getCurve();
|
||||
double v1, v2;
|
||||
if ((v1 = c1.getYTop()) == (v2 = c2.getYTop())) {
|
||||
if ((v1 = c1.getXTop()) == (v2 = c2.getXTop())) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (v1 < v2) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
private Vector pruneEdges(Vector edges) {
|
||||
int numedges = edges.size();
|
||||
if (numedges < 2) {
|
||||
return edges;
|
||||
}
|
||||
Edge[] edgelist = (Edge[]) edges.toArray(new Edge[numedges]);
|
||||
Arrays.sort(edgelist, YXTopComparator);
|
||||
if (false) {
|
||||
System.out.println("pruning: ");
|
||||
for (int i = 0; i < numedges; i++) {
|
||||
System.out.println("edgelist["+i+"] = "+edgelist[i]);
|
||||
}
|
||||
}
|
||||
Edge e;
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
int cur = 0;
|
||||
int next = 0;
|
||||
double yrange[] = new double[2];
|
||||
Vector subcurves = new Vector();
|
||||
Vector chains = new Vector();
|
||||
Vector links = new Vector();
|
||||
// Active edges are between left (inclusive) and right (exclusive)
|
||||
while (left < numedges) {
|
||||
double y = yrange[0];
|
||||
// Prune active edges that fall off the top of the active y range
|
||||
for (cur = next = right - 1; cur >= left; cur--) {
|
||||
e = edgelist[cur];
|
||||
if (e.getCurve().getYBot() > y) {
|
||||
if (next > cur) {
|
||||
edgelist[next] = e;
|
||||
}
|
||||
next--;
|
||||
}
|
||||
}
|
||||
left = next + 1;
|
||||
// Grab a new "top of Y range" if the active edges are empty
|
||||
if (left >= right) {
|
||||
if (right >= numedges) {
|
||||
break;
|
||||
}
|
||||
y = edgelist[right].getCurve().getYTop();
|
||||
if (y > yrange[0]) {
|
||||
finalizeSubCurves(subcurves, chains);
|
||||
}
|
||||
yrange[0] = y;
|
||||
}
|
||||
// Incorporate new active edges that enter the active y range
|
||||
while (right < numedges) {
|
||||
e = edgelist[right];
|
||||
if (e.getCurve().getYTop() > y) {
|
||||
break;
|
||||
}
|
||||
right++;
|
||||
}
|
||||
// Sort the current active edges by their X values and
|
||||
// determine the maximum valid Y range where the X ordering
|
||||
// is correct
|
||||
yrange[1] = edgelist[left].getCurve().getYBot();
|
||||
if (right < numedges) {
|
||||
y = edgelist[right].getCurve().getYTop();
|
||||
if (yrange[1] > y) {
|
||||
yrange[1] = y;
|
||||
}
|
||||
}
|
||||
if (false) {
|
||||
System.out.println("current line: y = ["+
|
||||
yrange[0]+", "+yrange[1]+"]");
|
||||
for (cur = left; cur < right; cur++) {
|
||||
System.out.println(" "+edgelist[cur]);
|
||||
}
|
||||
}
|
||||
// Note: We could start at left+1, but we need to make
|
||||
// sure that edgelist[left] has its equivalence set to 0.
|
||||
int nexteq = 1;
|
||||
for (cur = left; cur < right; cur++) {
|
||||
e = edgelist[cur];
|
||||
e.setEquivalence(0);
|
||||
for (next = cur; next > left; next--) {
|
||||
Edge prevedge = edgelist[next-1];
|
||||
int ordering = e.compareTo(prevedge, yrange);
|
||||
if (yrange[1] <= yrange[0]) {
|
||||
throw new InternalError("backstepping to "+yrange[1]+
|
||||
" from "+yrange[0]);
|
||||
}
|
||||
if (ordering >= 0) {
|
||||
if (ordering == 0) {
|
||||
// If the curves are equal, mark them to be
|
||||
// deleted later if they cancel each other
|
||||
// out so that we avoid having extraneous
|
||||
// curve segments.
|
||||
int eq = prevedge.getEquivalence();
|
||||
if (eq == 0) {
|
||||
eq = nexteq++;
|
||||
prevedge.setEquivalence(eq);
|
||||
}
|
||||
e.setEquivalence(eq);
|
||||
}
|
||||
break;
|
||||
}
|
||||
edgelist[next] = prevedge;
|
||||
}
|
||||
edgelist[next] = e;
|
||||
}
|
||||
if (false) {
|
||||
System.out.println("current sorted line: y = ["+
|
||||
yrange[0]+", "+yrange[1]+"]");
|
||||
for (cur = left; cur < right; cur++) {
|
||||
System.out.println(" "+edgelist[cur]);
|
||||
}
|
||||
}
|
||||
// Now prune the active edge list.
|
||||
// For each edge in the list, determine its classification
|
||||
// (entering shape, exiting shape, ignore - no change) and
|
||||
// record the current Y range and its classification in the
|
||||
// Edge object for use later in constructing the new outline.
|
||||
newRow();
|
||||
double ystart = yrange[0];
|
||||
double yend = yrange[1];
|
||||
for (cur = left; cur < right; cur++) {
|
||||
e = edgelist[cur];
|
||||
int etag;
|
||||
int eq = e.getEquivalence();
|
||||
if (eq != 0) {
|
||||
// Find one of the segments in the "equal" range
|
||||
// with the right transition state and prefer an
|
||||
// edge that was either active up until ystart
|
||||
// or the edge that extends the furthest downward
|
||||
// (i.e. has the most potential for continuation)
|
||||
int origstate = getState();
|
||||
etag = (origstate == AreaOp.RSTAG_INSIDE
|
||||
? AreaOp.ETAG_EXIT
|
||||
: AreaOp.ETAG_ENTER);
|
||||
Edge activematch = null;
|
||||
Edge longestmatch = e;
|
||||
double furthesty = yend;
|
||||
do {
|
||||
// Note: classify() must be called
|
||||
// on every edge we consume here.
|
||||
classify(e);
|
||||
if (activematch == null &&
|
||||
e.isActiveFor(ystart, etag))
|
||||
{
|
||||
activematch = e;
|
||||
}
|
||||
y = e.getCurve().getYBot();
|
||||
if (y > furthesty) {
|
||||
longestmatch = e;
|
||||
furthesty = y;
|
||||
}
|
||||
} while (++cur < right &&
|
||||
(e = edgelist[cur]).getEquivalence() == eq);
|
||||
--cur;
|
||||
if (getState() == origstate) {
|
||||
etag = AreaOp.ETAG_IGNORE;
|
||||
} else {
|
||||
e = (activematch != null ? activematch : longestmatch);
|
||||
}
|
||||
} else {
|
||||
etag = classify(e);
|
||||
}
|
||||
if (etag != AreaOp.ETAG_IGNORE) {
|
||||
e.record(yend, etag);
|
||||
links.add(new CurveLink(e.getCurve(), ystart, yend, etag));
|
||||
}
|
||||
}
|
||||
// assert(getState() == AreaOp.RSTAG_OUTSIDE);
|
||||
if (getState() != AreaOp.RSTAG_OUTSIDE) {
|
||||
System.out.println("Still inside at end of active edge list!");
|
||||
System.out.println("num curves = "+(right-left));
|
||||
System.out.println("num links = "+links.size());
|
||||
System.out.println("y top = "+yrange[0]);
|
||||
if (right < numedges) {
|
||||
System.out.println("y top of next curve = "+
|
||||
edgelist[right].getCurve().getYTop());
|
||||
} else {
|
||||
System.out.println("no more curves");
|
||||
}
|
||||
for (cur = left; cur < right; cur++) {
|
||||
e = edgelist[cur];
|
||||
System.out.println(e);
|
||||
int eq = e.getEquivalence();
|
||||
if (eq != 0) {
|
||||
System.out.println(" was equal to "+eq+"...");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (false) {
|
||||
System.out.println("new links:");
|
||||
for (int i = 0; i < links.size(); i++) {
|
||||
CurveLink link = (CurveLink) links.elementAt(i);
|
||||
System.out.println(" "+link.getSubCurve());
|
||||
}
|
||||
}
|
||||
resolveLinks(subcurves, chains, links);
|
||||
links.clear();
|
||||
// Finally capture the bottom of the valid Y range as the top
|
||||
// of the next Y range.
|
||||
yrange[0] = yend;
|
||||
}
|
||||
finalizeSubCurves(subcurves, chains);
|
||||
Vector ret = new Vector();
|
||||
Enumeration enum_ = subcurves.elements();
|
||||
while (enum_.hasMoreElements()) {
|
||||
CurveLink link = (CurveLink) enum_.nextElement();
|
||||
ret.add(link.getMoveto());
|
||||
CurveLink nextlink = link;
|
||||
while ((nextlink = nextlink.getNext()) != null) {
|
||||
if (!link.absorb(nextlink)) {
|
||||
ret.add(link.getSubCurve());
|
||||
link = nextlink;
|
||||
}
|
||||
}
|
||||
ret.add(link.getSubCurve());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void finalizeSubCurves(Vector subcurves, Vector chains) {
|
||||
int numchains = chains.size();
|
||||
if (numchains == 0) {
|
||||
return;
|
||||
}
|
||||
if ((numchains & 1) != 0) {
|
||||
throw new InternalError("Odd number of chains!");
|
||||
}
|
||||
ChainEnd[] endlist = new ChainEnd[numchains];
|
||||
chains.toArray(endlist);
|
||||
for (int i = 1; i < numchains; i += 2) {
|
||||
ChainEnd open = endlist[i - 1];
|
||||
ChainEnd close = endlist[i];
|
||||
CurveLink subcurve = open.linkTo(close);
|
||||
if (subcurve != null) {
|
||||
subcurves.add(subcurve);
|
||||
}
|
||||
}
|
||||
chains.clear();
|
||||
}
|
||||
|
||||
private static CurveLink[] EmptyLinkList = new CurveLink[2];
|
||||
private static ChainEnd[] EmptyChainList = new ChainEnd[2];
|
||||
|
||||
public static void resolveLinks(Vector subcurves,
|
||||
Vector chains,
|
||||
Vector links)
|
||||
{
|
||||
int numlinks = links.size();
|
||||
CurveLink[] linklist;
|
||||
if (numlinks == 0) {
|
||||
linklist = EmptyLinkList;
|
||||
} else {
|
||||
if ((numlinks & 1) != 0) {
|
||||
throw new InternalError("Odd number of new curves!");
|
||||
}
|
||||
linklist = new CurveLink[numlinks+2];
|
||||
links.toArray(linklist);
|
||||
}
|
||||
int numchains = chains.size();
|
||||
ChainEnd[] endlist;
|
||||
if (numchains == 0) {
|
||||
endlist = EmptyChainList;
|
||||
} else {
|
||||
if ((numchains & 1) != 0) {
|
||||
throw new InternalError("Odd number of chains!");
|
||||
}
|
||||
endlist = new ChainEnd[numchains+2];
|
||||
chains.toArray(endlist);
|
||||
}
|
||||
int curchain = 0;
|
||||
int curlink = 0;
|
||||
chains.clear();
|
||||
ChainEnd chain = endlist[0];
|
||||
ChainEnd nextchain = endlist[1];
|
||||
CurveLink link = linklist[0];
|
||||
CurveLink nextlink = linklist[1];
|
||||
while (chain != null || link != null) {
|
||||
/*
|
||||
* Strategy 1:
|
||||
* Connect chains or links if they are the only things left...
|
||||
*/
|
||||
boolean connectchains = (link == null);
|
||||
boolean connectlinks = (chain == null);
|
||||
|
||||
if (!connectchains && !connectlinks) {
|
||||
// assert(link != null && chain != null);
|
||||
/*
|
||||
* Strategy 2:
|
||||
* Connect chains or links if they close off an open area...
|
||||
*/
|
||||
connectchains = ((curchain & 1) == 0 &&
|
||||
chain.getX() == nextchain.getX());
|
||||
connectlinks = ((curlink & 1) == 0 &&
|
||||
link.getX() == nextlink.getX());
|
||||
|
||||
if (!connectchains && !connectlinks) {
|
||||
/*
|
||||
* Strategy 3:
|
||||
* Connect chains or links if their successor is
|
||||
* between them and their potential connectee...
|
||||
*/
|
||||
double cx = chain.getX();
|
||||
double lx = link.getX();
|
||||
connectchains =
|
||||
(nextchain != null && cx < lx &&
|
||||
obstructs(nextchain.getX(), lx, curchain));
|
||||
connectlinks =
|
||||
(nextlink != null && lx < cx &&
|
||||
obstructs(nextlink.getX(), cx, curlink));
|
||||
}
|
||||
}
|
||||
if (connectchains) {
|
||||
CurveLink subcurve = chain.linkTo(nextchain);
|
||||
if (subcurve != null) {
|
||||
subcurves.add(subcurve);
|
||||
}
|
||||
curchain += 2;
|
||||
chain = endlist[curchain];
|
||||
nextchain = endlist[curchain+1];
|
||||
}
|
||||
if (connectlinks) {
|
||||
ChainEnd openend = new ChainEnd(link, null);
|
||||
ChainEnd closeend = new ChainEnd(nextlink, openend);
|
||||
openend.setOtherEnd(closeend);
|
||||
chains.add(openend);
|
||||
chains.add(closeend);
|
||||
curlink += 2;
|
||||
link = linklist[curlink];
|
||||
nextlink = linklist[curlink+1];
|
||||
}
|
||||
if (!connectchains && !connectlinks) {
|
||||
// assert(link != null);
|
||||
// assert(chain != null);
|
||||
// assert(chain.getEtag() == link.getEtag());
|
||||
chain.addLink(link);
|
||||
chains.add(chain);
|
||||
curchain++;
|
||||
chain = nextchain;
|
||||
nextchain = endlist[curchain+1];
|
||||
curlink++;
|
||||
link = nextlink;
|
||||
nextlink = linklist[curlink+1];
|
||||
}
|
||||
}
|
||||
if ((chains.size() & 1) != 0) {
|
||||
System.out.println("Odd number of chains!");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Does the position of the next edge at v1 "obstruct" the
|
||||
* connectivity between current edge and the potential
|
||||
* partner edge which is positioned at v2?
|
||||
*
|
||||
* Phase tells us whether we are testing for a transition
|
||||
* into or out of the interior part of the resulting area.
|
||||
*
|
||||
* Require 4-connected continuity if this edge and the partner
|
||||
* edge are both "entering into" type edges
|
||||
* Allow 8-connected continuity for "exiting from" type edges
|
||||
*/
|
||||
public static boolean obstructs(double v1, double v2, int phase) {
|
||||
return (((phase & 1) == 0) ? (v1 <= v2) : (v1 < v2));
|
||||
}
|
||||
}
|
||||
117
jdkSrc/jdk8/sun/awt/geom/ChainEnd.java
Normal file
117
jdkSrc/jdk8/sun/awt/geom/ChainEnd.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.awt.geom;
|
||||
|
||||
final class ChainEnd {
|
||||
CurveLink head;
|
||||
CurveLink tail;
|
||||
ChainEnd partner;
|
||||
int etag;
|
||||
|
||||
public ChainEnd(CurveLink first, ChainEnd partner) {
|
||||
this.head = first;
|
||||
this.tail = first;
|
||||
this.partner = partner;
|
||||
this.etag = first.getEdgeTag();
|
||||
}
|
||||
|
||||
public CurveLink getChain() {
|
||||
return head;
|
||||
}
|
||||
|
||||
public void setOtherEnd(ChainEnd partner) {
|
||||
this.partner = partner;
|
||||
}
|
||||
|
||||
public ChainEnd getPartner() {
|
||||
return partner;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns head of a complete chain to be added to subcurves
|
||||
* or null if the links did not complete such a chain.
|
||||
*/
|
||||
public CurveLink linkTo(ChainEnd that) {
|
||||
if (etag == AreaOp.ETAG_IGNORE ||
|
||||
that.etag == AreaOp.ETAG_IGNORE)
|
||||
{
|
||||
throw new InternalError("ChainEnd linked more than once!");
|
||||
}
|
||||
if (etag == that.etag) {
|
||||
throw new InternalError("Linking chains of the same type!");
|
||||
}
|
||||
ChainEnd enter, exit;
|
||||
// assert(partner.etag != that.partner.etag);
|
||||
if (etag == AreaOp.ETAG_ENTER) {
|
||||
enter = this;
|
||||
exit = that;
|
||||
} else {
|
||||
enter = that;
|
||||
exit = this;
|
||||
}
|
||||
// Now make sure these ChainEnds are not linked to any others...
|
||||
etag = AreaOp.ETAG_IGNORE;
|
||||
that.etag = AreaOp.ETAG_IGNORE;
|
||||
// Now link everything up...
|
||||
enter.tail.setNext(exit.head);
|
||||
enter.tail = exit.tail;
|
||||
if (partner == that) {
|
||||
// Curve has closed on itself...
|
||||
return enter.head;
|
||||
}
|
||||
// Link this chain into one end of the chain formed by the partners
|
||||
ChainEnd otherenter = exit.partner;
|
||||
ChainEnd otherexit = enter.partner;
|
||||
otherenter.partner = otherexit;
|
||||
otherexit.partner = otherenter;
|
||||
if (enter.head.getYTop() < otherenter.head.getYTop()) {
|
||||
enter.tail.setNext(otherenter.head);
|
||||
otherenter.head = enter.head;
|
||||
} else {
|
||||
otherexit.tail.setNext(enter.head);
|
||||
otherexit.tail = enter.tail;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addLink(CurveLink newlink) {
|
||||
if (etag == AreaOp.ETAG_ENTER) {
|
||||
tail.setNext(newlink);
|
||||
tail = newlink;
|
||||
} else {
|
||||
newlink.setNext(head);
|
||||
head = newlink;
|
||||
}
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
if (etag == AreaOp.ETAG_ENTER) {
|
||||
return tail.getXBot();
|
||||
} else {
|
||||
return head.getXBot();
|
||||
}
|
||||
}
|
||||
}
|
||||
522
jdkSrc/jdk8/sun/awt/geom/Crossings.java
Normal file
522
jdkSrc/jdk8/sun/awt/geom/Crossings.java
Normal file
@@ -0,0 +1,522 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.awt.geom;
|
||||
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public abstract class Crossings {
|
||||
public static final boolean debug = false;
|
||||
|
||||
int limit = 0;
|
||||
double yranges[] = new double[10];
|
||||
|
||||
double xlo, ylo, xhi, yhi;
|
||||
|
||||
public Crossings(double xlo, double ylo, double xhi, double yhi) {
|
||||
this.xlo = xlo;
|
||||
this.ylo = ylo;
|
||||
this.xhi = xhi;
|
||||
this.yhi = yhi;
|
||||
}
|
||||
|
||||
public final double getXLo() {
|
||||
return xlo;
|
||||
}
|
||||
|
||||
public final double getYLo() {
|
||||
return ylo;
|
||||
}
|
||||
|
||||
public final double getXHi() {
|
||||
return xhi;
|
||||
}
|
||||
|
||||
public final double getYHi() {
|
||||
return yhi;
|
||||
}
|
||||
|
||||
public abstract void record(double ystart, double yend, int direction);
|
||||
|
||||
public void print() {
|
||||
System.out.println("Crossings [");
|
||||
System.out.println(" bounds = ["+ylo+", "+yhi+"]");
|
||||
for (int i = 0; i < limit; i += 2) {
|
||||
System.out.println(" ["+yranges[i]+", "+yranges[i+1]+"]");
|
||||
}
|
||||
System.out.println("]");
|
||||
}
|
||||
|
||||
public final boolean isEmpty() {
|
||||
return (limit == 0);
|
||||
}
|
||||
|
||||
public abstract boolean covers(double ystart, double yend);
|
||||
|
||||
public static Crossings findCrossings(Vector curves,
|
||||
double xlo, double ylo,
|
||||
double xhi, double yhi)
|
||||
{
|
||||
Crossings cross = new EvenOdd(xlo, ylo, xhi, yhi);
|
||||
Enumeration enum_ = curves.elements();
|
||||
while (enum_.hasMoreElements()) {
|
||||
Curve c = (Curve) enum_.nextElement();
|
||||
if (c.accumulateCrossings(cross)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (debug) {
|
||||
cross.print();
|
||||
}
|
||||
return cross;
|
||||
}
|
||||
|
||||
public static Crossings findCrossings(PathIterator pi,
|
||||
double xlo, double ylo,
|
||||
double xhi, double yhi)
|
||||
{
|
||||
Crossings cross;
|
||||
if (pi.getWindingRule() == pi.WIND_EVEN_ODD) {
|
||||
cross = new EvenOdd(xlo, ylo, xhi, yhi);
|
||||
} else {
|
||||
cross = new NonZero(xlo, ylo, xhi, yhi);
|
||||
}
|
||||
// coords array is big enough for holding:
|
||||
// coordinates returned from currentSegment (6)
|
||||
// OR
|
||||
// two subdivided quadratic curves (2+4+4=10)
|
||||
// AND
|
||||
// 0-1 horizontal splitting parameters
|
||||
// OR
|
||||
// 2 parametric equation derivative coefficients
|
||||
// OR
|
||||
// three subdivided cubic curves (2+6+6+6=20)
|
||||
// AND
|
||||
// 0-2 horizontal splitting parameters
|
||||
// OR
|
||||
// 3 parametric equation derivative coefficients
|
||||
double coords[] = new double[23];
|
||||
double movx = 0;
|
||||
double movy = 0;
|
||||
double curx = 0;
|
||||
double cury = 0;
|
||||
double newx, newy;
|
||||
while (!pi.isDone()) {
|
||||
int type = pi.currentSegment(coords);
|
||||
switch (type) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
if (movy != cury &&
|
||||
cross.accumulateLine(curx, cury, movx, movy))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
movx = curx = coords[0];
|
||||
movy = cury = coords[1];
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
newx = coords[0];
|
||||
newy = coords[1];
|
||||
if (cross.accumulateLine(curx, cury, newx, newy)) {
|
||||
return null;
|
||||
}
|
||||
curx = newx;
|
||||
cury = newy;
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
newx = coords[2];
|
||||
newy = coords[3];
|
||||
if (cross.accumulateQuad(curx, cury, coords)) {
|
||||
return null;
|
||||
}
|
||||
curx = newx;
|
||||
cury = newy;
|
||||
break;
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
newx = coords[4];
|
||||
newy = coords[5];
|
||||
if (cross.accumulateCubic(curx, cury, coords)) {
|
||||
return null;
|
||||
}
|
||||
curx = newx;
|
||||
cury = newy;
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
if (movy != cury &&
|
||||
cross.accumulateLine(curx, cury, movx, movy))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
curx = movx;
|
||||
cury = movy;
|
||||
break;
|
||||
}
|
||||
pi.next();
|
||||
}
|
||||
if (movy != cury) {
|
||||
if (cross.accumulateLine(curx, cury, movx, movy)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (debug) {
|
||||
cross.print();
|
||||
}
|
||||
return cross;
|
||||
}
|
||||
|
||||
public boolean accumulateLine(double x0, double y0,
|
||||
double x1, double y1)
|
||||
{
|
||||
if (y0 <= y1) {
|
||||
return accumulateLine(x0, y0, x1, y1, 1);
|
||||
} else {
|
||||
return accumulateLine(x1, y1, x0, y0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean accumulateLine(double x0, double y0,
|
||||
double x1, double y1,
|
||||
int direction)
|
||||
{
|
||||
if (yhi <= y0 || ylo >= y1) {
|
||||
return false;
|
||||
}
|
||||
if (x0 >= xhi && x1 >= xhi) {
|
||||
return false;
|
||||
}
|
||||
if (y0 == y1) {
|
||||
return (x0 >= xlo || x1 >= xlo);
|
||||
}
|
||||
double xstart, ystart, xend, yend;
|
||||
double dx = (x1 - x0);
|
||||
double dy = (y1 - y0);
|
||||
if (y0 < ylo) {
|
||||
xstart = x0 + (ylo - y0) * dx / dy;
|
||||
ystart = ylo;
|
||||
} else {
|
||||
xstart = x0;
|
||||
ystart = y0;
|
||||
}
|
||||
if (yhi < y1) {
|
||||
xend = x0 + (yhi - y0) * dx / dy;
|
||||
yend = yhi;
|
||||
} else {
|
||||
xend = x1;
|
||||
yend = y1;
|
||||
}
|
||||
if (xstart >= xhi && xend >= xhi) {
|
||||
return false;
|
||||
}
|
||||
if (xstart > xlo || xend > xlo) {
|
||||
return true;
|
||||
}
|
||||
record(ystart, yend, direction);
|
||||
return false;
|
||||
}
|
||||
|
||||
private Vector tmp = new Vector();
|
||||
|
||||
public boolean accumulateQuad(double x0, double y0, double coords[]) {
|
||||
if (y0 < ylo && coords[1] < ylo && coords[3] < ylo) {
|
||||
return false;
|
||||
}
|
||||
if (y0 > yhi && coords[1] > yhi && coords[3] > yhi) {
|
||||
return false;
|
||||
}
|
||||
if (x0 > xhi && coords[0] > xhi && coords[2] > xhi) {
|
||||
return false;
|
||||
}
|
||||
if (x0 < xlo && coords[0] < xlo && coords[2] < xlo) {
|
||||
if (y0 < coords[3]) {
|
||||
record(Math.max(y0, ylo), Math.min(coords[3], yhi), 1);
|
||||
} else if (y0 > coords[3]) {
|
||||
record(Math.max(coords[3], ylo), Math.min(y0, yhi), -1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Curve.insertQuad(tmp, x0, y0, coords);
|
||||
Enumeration enum_ = tmp.elements();
|
||||
while (enum_.hasMoreElements()) {
|
||||
Curve c = (Curve) enum_.nextElement();
|
||||
if (c.accumulateCrossings(this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
tmp.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean accumulateCubic(double x0, double y0, double coords[]) {
|
||||
if (y0 < ylo && coords[1] < ylo &&
|
||||
coords[3] < ylo && coords[5] < ylo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (y0 > yhi && coords[1] > yhi &&
|
||||
coords[3] > yhi && coords[5] > yhi)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (x0 > xhi && coords[0] > xhi &&
|
||||
coords[2] > xhi && coords[4] > xhi)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (x0 < xlo && coords[0] < xlo &&
|
||||
coords[2] < xlo && coords[4] < xlo)
|
||||
{
|
||||
if (y0 <= coords[5]) {
|
||||
record(Math.max(y0, ylo), Math.min(coords[5], yhi), 1);
|
||||
} else {
|
||||
record(Math.max(coords[5], ylo), Math.min(y0, yhi), -1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Curve.insertCubic(tmp, x0, y0, coords);
|
||||
Enumeration enum_ = tmp.elements();
|
||||
while (enum_.hasMoreElements()) {
|
||||
Curve c = (Curve) enum_.nextElement();
|
||||
if (c.accumulateCrossings(this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
tmp.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
public final static class EvenOdd extends Crossings {
|
||||
public EvenOdd(double xlo, double ylo, double xhi, double yhi) {
|
||||
super(xlo, ylo, xhi, yhi);
|
||||
}
|
||||
|
||||
public final boolean covers(double ystart, double yend) {
|
||||
return (limit == 2 && yranges[0] <= ystart && yranges[1] >= yend);
|
||||
}
|
||||
|
||||
public void record(double ystart, double yend, int direction) {
|
||||
if (ystart >= yend) {
|
||||
return;
|
||||
}
|
||||
int from = 0;
|
||||
// Quickly jump over all pairs that are completely "above"
|
||||
while (from < limit && ystart > yranges[from+1]) {
|
||||
from += 2;
|
||||
}
|
||||
int to = from;
|
||||
while (from < limit) {
|
||||
double yrlo = yranges[from++];
|
||||
double yrhi = yranges[from++];
|
||||
if (yend < yrlo) {
|
||||
// Quickly handle insertion of the new range
|
||||
yranges[to++] = ystart;
|
||||
yranges[to++] = yend;
|
||||
ystart = yrlo;
|
||||
yend = yrhi;
|
||||
continue;
|
||||
}
|
||||
// The ranges overlap - sort, collapse, insert, iterate
|
||||
double yll, ylh, yhl, yhh;
|
||||
if (ystart < yrlo) {
|
||||
yll = ystart;
|
||||
ylh = yrlo;
|
||||
} else {
|
||||
yll = yrlo;
|
||||
ylh = ystart;
|
||||
}
|
||||
if (yend < yrhi) {
|
||||
yhl = yend;
|
||||
yhh = yrhi;
|
||||
} else {
|
||||
yhl = yrhi;
|
||||
yhh = yend;
|
||||
}
|
||||
if (ylh == yhl) {
|
||||
ystart = yll;
|
||||
yend = yhh;
|
||||
} else {
|
||||
if (ylh > yhl) {
|
||||
ystart = yhl;
|
||||
yhl = ylh;
|
||||
ylh = ystart;
|
||||
}
|
||||
if (yll != ylh) {
|
||||
yranges[to++] = yll;
|
||||
yranges[to++] = ylh;
|
||||
}
|
||||
ystart = yhl;
|
||||
yend = yhh;
|
||||
}
|
||||
if (ystart >= yend) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (to < from && from < limit) {
|
||||
System.arraycopy(yranges, from, yranges, to, limit-from);
|
||||
}
|
||||
to += (limit-from);
|
||||
if (ystart < yend) {
|
||||
if (to >= yranges.length) {
|
||||
double newranges[] = new double[to+10];
|
||||
System.arraycopy(yranges, 0, newranges, 0, to);
|
||||
yranges = newranges;
|
||||
}
|
||||
yranges[to++] = ystart;
|
||||
yranges[to++] = yend;
|
||||
}
|
||||
limit = to;
|
||||
}
|
||||
}
|
||||
|
||||
public final static class NonZero extends Crossings {
|
||||
private int crosscounts[];
|
||||
|
||||
public NonZero(double xlo, double ylo, double xhi, double yhi) {
|
||||
super(xlo, ylo, xhi, yhi);
|
||||
crosscounts = new int[yranges.length / 2];
|
||||
}
|
||||
|
||||
public final boolean covers(double ystart, double yend) {
|
||||
int i = 0;
|
||||
while (i < limit) {
|
||||
double ylo = yranges[i++];
|
||||
double yhi = yranges[i++];
|
||||
if (ystart >= yhi) {
|
||||
continue;
|
||||
}
|
||||
if (ystart < ylo) {
|
||||
return false;
|
||||
}
|
||||
if (yend <= yhi) {
|
||||
return true;
|
||||
}
|
||||
ystart = yhi;
|
||||
}
|
||||
return (ystart >= yend);
|
||||
}
|
||||
|
||||
public void remove(int cur) {
|
||||
limit -= 2;
|
||||
int rem = limit - cur;
|
||||
if (rem > 0) {
|
||||
System.arraycopy(yranges, cur+2, yranges, cur, rem);
|
||||
System.arraycopy(crosscounts, cur/2+1,
|
||||
crosscounts, cur/2,
|
||||
rem/2);
|
||||
}
|
||||
}
|
||||
|
||||
public void insert(int cur, double lo, double hi, int dir) {
|
||||
int rem = limit - cur;
|
||||
double oldranges[] = yranges;
|
||||
int oldcounts[] = crosscounts;
|
||||
if (limit >= yranges.length) {
|
||||
yranges = new double[limit+10];
|
||||
System.arraycopy(oldranges, 0, yranges, 0, cur);
|
||||
crosscounts = new int[(limit+10)/2];
|
||||
System.arraycopy(oldcounts, 0, crosscounts, 0, cur/2);
|
||||
}
|
||||
if (rem > 0) {
|
||||
System.arraycopy(oldranges, cur, yranges, cur+2, rem);
|
||||
System.arraycopy(oldcounts, cur/2,
|
||||
crosscounts, cur/2+1,
|
||||
rem/2);
|
||||
}
|
||||
yranges[cur+0] = lo;
|
||||
yranges[cur+1] = hi;
|
||||
crosscounts[cur/2] = dir;
|
||||
limit += 2;
|
||||
}
|
||||
|
||||
public void record(double ystart, double yend, int direction) {
|
||||
if (ystart >= yend) {
|
||||
return;
|
||||
}
|
||||
int cur = 0;
|
||||
// Quickly jump over all pairs that are completely "above"
|
||||
while (cur < limit && ystart > yranges[cur+1]) {
|
||||
cur += 2;
|
||||
}
|
||||
if (cur < limit) {
|
||||
int rdir = crosscounts[cur/2];
|
||||
double yrlo = yranges[cur+0];
|
||||
double yrhi = yranges[cur+1];
|
||||
if (yrhi == ystart && rdir == direction) {
|
||||
// Remove the range from the list and collapse it
|
||||
// into the range being inserted. Note that the
|
||||
// new combined range may overlap the following range
|
||||
// so we must not simply combine the ranges in place
|
||||
// unless we are at the last range.
|
||||
if (cur+2 == limit) {
|
||||
yranges[cur+1] = yend;
|
||||
return;
|
||||
}
|
||||
remove(cur);
|
||||
ystart = yrlo;
|
||||
rdir = crosscounts[cur/2];
|
||||
yrlo = yranges[cur+0];
|
||||
yrhi = yranges[cur+1];
|
||||
}
|
||||
if (yend < yrlo) {
|
||||
// Just insert the new range at the current location
|
||||
insert(cur, ystart, yend, direction);
|
||||
return;
|
||||
}
|
||||
if (yend == yrlo && rdir == direction) {
|
||||
// Just prepend the new range to the current one
|
||||
yranges[cur] = ystart;
|
||||
return;
|
||||
}
|
||||
// The ranges must overlap - (yend > yrlo && yrhi > ystart)
|
||||
if (ystart < yrlo) {
|
||||
insert(cur, ystart, yrlo, direction);
|
||||
cur += 2;
|
||||
ystart = yrlo;
|
||||
} else if (yrlo < ystart) {
|
||||
insert(cur, yrlo, ystart, rdir);
|
||||
cur += 2;
|
||||
yrlo = ystart;
|
||||
}
|
||||
// assert(yrlo == ystart);
|
||||
int newdir = rdir + direction;
|
||||
double newend = Math.min(yend, yrhi);
|
||||
if (newdir == 0) {
|
||||
remove(cur);
|
||||
} else {
|
||||
crosscounts[cur/2] = newdir;
|
||||
yranges[cur++] = ystart;
|
||||
yranges[cur++] = newend;
|
||||
}
|
||||
ystart = yrlo = newend;
|
||||
if (yrlo < yrhi) {
|
||||
insert(cur, yrlo, yrhi, rdir);
|
||||
}
|
||||
}
|
||||
if (ystart < yend) {
|
||||
insert(cur, ystart, yend, direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1206
jdkSrc/jdk8/sun/awt/geom/Curve.java
Normal file
1206
jdkSrc/jdk8/sun/awt/geom/Curve.java
Normal file
File diff suppressed because it is too large
Load Diff
114
jdkSrc/jdk8/sun/awt/geom/CurveLink.java
Normal file
114
jdkSrc/jdk8/sun/awt/geom/CurveLink.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.awt.geom;
|
||||
|
||||
final class CurveLink {
|
||||
Curve curve;
|
||||
double ytop;
|
||||
double ybot;
|
||||
int etag;
|
||||
|
||||
CurveLink next;
|
||||
|
||||
public CurveLink(Curve curve, double ystart, double yend, int etag) {
|
||||
this.curve = curve;
|
||||
this.ytop = ystart;
|
||||
this.ybot = yend;
|
||||
this.etag = etag;
|
||||
if (ytop < curve.getYTop() || ybot > curve.getYBot()) {
|
||||
throw new InternalError("bad curvelink ["+ytop+"=>"+ybot+"] for "+curve);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean absorb(CurveLink link) {
|
||||
return absorb(link.curve, link.ytop, link.ybot, link.etag);
|
||||
}
|
||||
|
||||
public boolean absorb(Curve curve, double ystart, double yend, int etag) {
|
||||
if (this.curve != curve || this.etag != etag ||
|
||||
ybot < ystart || ytop > yend)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ystart < curve.getYTop() || yend > curve.getYBot()) {
|
||||
throw new InternalError("bad curvelink ["+ystart+"=>"+yend+"] for "+curve);
|
||||
}
|
||||
this.ytop = Math.min(ytop, ystart);
|
||||
this.ybot = Math.max(ybot, yend);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return (ytop == ybot);
|
||||
}
|
||||
|
||||
public Curve getCurve() {
|
||||
return curve;
|
||||
}
|
||||
|
||||
public Curve getSubCurve() {
|
||||
if (ytop == curve.getYTop() && ybot == curve.getYBot()) {
|
||||
return curve.getWithDirection(etag);
|
||||
}
|
||||
return curve.getSubCurve(ytop, ybot, etag);
|
||||
}
|
||||
|
||||
public Curve getMoveto() {
|
||||
return new Order0(getXTop(), getYTop());
|
||||
}
|
||||
|
||||
public double getXTop() {
|
||||
return curve.XforY(ytop);
|
||||
}
|
||||
|
||||
public double getYTop() {
|
||||
return ytop;
|
||||
}
|
||||
|
||||
public double getXBot() {
|
||||
return curve.XforY(ybot);
|
||||
}
|
||||
|
||||
public double getYBot() {
|
||||
return ybot;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return curve.XforY(ytop);
|
||||
}
|
||||
|
||||
public int getEdgeTag() {
|
||||
return etag;
|
||||
}
|
||||
|
||||
public void setNext(CurveLink link) {
|
||||
this.next = link;
|
||||
}
|
||||
|
||||
public CurveLink getNext() {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
125
jdkSrc/jdk8/sun/awt/geom/Edge.java
Normal file
125
jdkSrc/jdk8/sun/awt/geom/Edge.java
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.awt.geom;
|
||||
|
||||
final class Edge {
|
||||
static final int INIT_PARTS = 4;
|
||||
static final int GROW_PARTS = 10;
|
||||
|
||||
Curve curve;
|
||||
int ctag;
|
||||
int etag;
|
||||
double activey;
|
||||
int equivalence;
|
||||
|
||||
public Edge(Curve c, int ctag) {
|
||||
this(c, ctag, AreaOp.ETAG_IGNORE);
|
||||
}
|
||||
|
||||
public Edge(Curve c, int ctag, int etag) {
|
||||
this.curve = c;
|
||||
this.ctag = ctag;
|
||||
this.etag = etag;
|
||||
}
|
||||
|
||||
public Curve getCurve() {
|
||||
return curve;
|
||||
}
|
||||
|
||||
public int getCurveTag() {
|
||||
return ctag;
|
||||
}
|
||||
|
||||
public int getEdgeTag() {
|
||||
return etag;
|
||||
}
|
||||
|
||||
public void setEdgeTag(int etag) {
|
||||
this.etag = etag;
|
||||
}
|
||||
|
||||
public int getEquivalence() {
|
||||
return equivalence;
|
||||
}
|
||||
|
||||
public void setEquivalence(int eq) {
|
||||
equivalence = eq;
|
||||
}
|
||||
|
||||
private Edge lastEdge;
|
||||
private int lastResult;
|
||||
private double lastLimit;
|
||||
|
||||
public int compareTo(Edge other, double yrange[]) {
|
||||
if (other == lastEdge && yrange[0] < lastLimit) {
|
||||
if (yrange[1] > lastLimit) {
|
||||
yrange[1] = lastLimit;
|
||||
}
|
||||
return lastResult;
|
||||
}
|
||||
if (this == other.lastEdge && yrange[0] < other.lastLimit) {
|
||||
if (yrange[1] > other.lastLimit) {
|
||||
yrange[1] = other.lastLimit;
|
||||
}
|
||||
return 0-other.lastResult;
|
||||
}
|
||||
//long start = System.currentTimeMillis();
|
||||
int ret = curve.compareTo(other.curve, yrange);
|
||||
//long end = System.currentTimeMillis();
|
||||
/*
|
||||
System.out.println("compare: "+
|
||||
((System.identityHashCode(this) <
|
||||
System.identityHashCode(other))
|
||||
? this+" to "+other
|
||||
: other+" to "+this)+
|
||||
" == "+ret+" at "+yrange[1]+
|
||||
" in "+(end-start)+"ms");
|
||||
*/
|
||||
lastEdge = other;
|
||||
lastLimit = yrange[1];
|
||||
lastResult = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void record(double yend, int etag) {
|
||||
this.activey = yend;
|
||||
this.etag = etag;
|
||||
}
|
||||
|
||||
public boolean isActiveFor(double y, int etag) {
|
||||
return (this.etag == etag && this.activey >= y);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ("Edge["+curve+
|
||||
", "+
|
||||
(ctag == AreaOp.CTAG_LEFT ? "L" : "R")+
|
||||
", "+
|
||||
(etag == AreaOp.ETAG_ENTER ? "I" :
|
||||
(etag == AreaOp.ETAG_EXIT ? "O" : "N"))+
|
||||
"]");
|
||||
}
|
||||
}
|
||||
142
jdkSrc/jdk8/sun/awt/geom/Order0.java
Normal file
142
jdkSrc/jdk8/sun/awt/geom/Order0.java
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.awt.geom;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.util.Vector;
|
||||
|
||||
final class Order0 extends Curve {
|
||||
private double x;
|
||||
private double y;
|
||||
|
||||
public Order0(double x, double y) {
|
||||
super(INCREASING);
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public double getXTop() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getYTop() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getXBot() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getYBot() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getXMin() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getXMax() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getX0() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY0() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getX1() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY1() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double XforY(double y) {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double TforY(double y) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public double XforT(double t) {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double YforT(double t) {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double dXforT(double t, int deriv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public double dYforT(double t, int deriv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public double nextVertical(double t0, double t1) {
|
||||
return t1;
|
||||
}
|
||||
|
||||
public int crossingsFor(double x, double y) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean accumulateCrossings(Crossings c) {
|
||||
return (x > c.getXLo() &&
|
||||
x < c.getXHi() &&
|
||||
y > c.getYLo() &&
|
||||
y < c.getYHi());
|
||||
}
|
||||
|
||||
public void enlarge(Rectangle2D r) {
|
||||
r.add(x, y);
|
||||
}
|
||||
|
||||
public Curve getSubCurve(double ystart, double yend, int dir) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Curve getReversedCurve() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getSegment(double coords[]) {
|
||||
coords[0] = x;
|
||||
coords[1] = y;
|
||||
return PathIterator.SEG_MOVETO;
|
||||
}
|
||||
}
|
||||
312
jdkSrc/jdk8/sun/awt/geom/Order1.java
Normal file
312
jdkSrc/jdk8/sun/awt/geom/Order1.java
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.awt.geom;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.util.Vector;
|
||||
|
||||
final class Order1 extends Curve {
|
||||
private double x0;
|
||||
private double y0;
|
||||
private double x1;
|
||||
private double y1;
|
||||
private double xmin;
|
||||
private double xmax;
|
||||
|
||||
public Order1(double x0, double y0,
|
||||
double x1, double y1,
|
||||
int direction)
|
||||
{
|
||||
super(direction);
|
||||
this.x0 = x0;
|
||||
this.y0 = y0;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
if (x0 < x1) {
|
||||
this.xmin = x0;
|
||||
this.xmax = x1;
|
||||
} else {
|
||||
this.xmin = x1;
|
||||
this.xmax = x0;
|
||||
}
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public double getXTop() {
|
||||
return x0;
|
||||
}
|
||||
|
||||
public double getYTop() {
|
||||
return y0;
|
||||
}
|
||||
|
||||
public double getXBot() {
|
||||
return x1;
|
||||
}
|
||||
|
||||
public double getYBot() {
|
||||
return y1;
|
||||
}
|
||||
|
||||
public double getXMin() {
|
||||
return xmin;
|
||||
}
|
||||
|
||||
public double getXMax() {
|
||||
return xmax;
|
||||
}
|
||||
|
||||
public double getX0() {
|
||||
return (direction == INCREASING) ? x0 : x1;
|
||||
}
|
||||
|
||||
public double getY0() {
|
||||
return (direction == INCREASING) ? y0 : y1;
|
||||
}
|
||||
|
||||
public double getX1() {
|
||||
return (direction == DECREASING) ? x0 : x1;
|
||||
}
|
||||
|
||||
public double getY1() {
|
||||
return (direction == DECREASING) ? y0 : y1;
|
||||
}
|
||||
|
||||
public double XforY(double y) {
|
||||
if (x0 == x1 || y <= y0) {
|
||||
return x0;
|
||||
}
|
||||
if (y >= y1) {
|
||||
return x1;
|
||||
}
|
||||
// assert(y0 != y1); /* No horizontal lines... */
|
||||
return (x0 + (y - y0) * (x1 - x0) / (y1 - y0));
|
||||
}
|
||||
|
||||
public double TforY(double y) {
|
||||
if (y <= y0) {
|
||||
return 0;
|
||||
}
|
||||
if (y >= y1) {
|
||||
return 1;
|
||||
}
|
||||
return (y - y0) / (y1 - y0);
|
||||
}
|
||||
|
||||
public double XforT(double t) {
|
||||
return x0 + t * (x1 - x0);
|
||||
}
|
||||
|
||||
public double YforT(double t) {
|
||||
return y0 + t * (y1 - y0);
|
||||
}
|
||||
|
||||
public double dXforT(double t, int deriv) {
|
||||
switch (deriv) {
|
||||
case 0:
|
||||
return x0 + t * (x1 - x0);
|
||||
case 1:
|
||||
return (x1 - x0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public double dYforT(double t, int deriv) {
|
||||
switch (deriv) {
|
||||
case 0:
|
||||
return y0 + t * (y1 - y0);
|
||||
case 1:
|
||||
return (y1 - y0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public double nextVertical(double t0, double t1) {
|
||||
return t1;
|
||||
}
|
||||
|
||||
public boolean accumulateCrossings(Crossings c) {
|
||||
double xlo = c.getXLo();
|
||||
double ylo = c.getYLo();
|
||||
double xhi = c.getXHi();
|
||||
double yhi = c.getYHi();
|
||||
if (xmin >= xhi) {
|
||||
return false;
|
||||
}
|
||||
double xstart, ystart, xend, yend;
|
||||
if (y0 < ylo) {
|
||||
if (y1 <= ylo) {
|
||||
return false;
|
||||
}
|
||||
ystart = ylo;
|
||||
xstart = XforY(ylo);
|
||||
} else {
|
||||
if (y0 >= yhi) {
|
||||
return false;
|
||||
}
|
||||
ystart = y0;
|
||||
xstart = x0;
|
||||
}
|
||||
if (y1 > yhi) {
|
||||
yend = yhi;
|
||||
xend = XforY(yhi);
|
||||
} else {
|
||||
yend = y1;
|
||||
xend = x1;
|
||||
}
|
||||
if (xstart >= xhi && xend >= xhi) {
|
||||
return false;
|
||||
}
|
||||
if (xstart > xlo || xend > xlo) {
|
||||
return true;
|
||||
}
|
||||
c.record(ystart, yend, direction);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void enlarge(Rectangle2D r) {
|
||||
r.add(x0, y0);
|
||||
r.add(x1, y1);
|
||||
}
|
||||
|
||||
public Curve getSubCurve(double ystart, double yend, int dir) {
|
||||
if (ystart == y0 && yend == y1) {
|
||||
return getWithDirection(dir);
|
||||
}
|
||||
if (x0 == x1) {
|
||||
return new Order1(x0, ystart, x1, yend, dir);
|
||||
}
|
||||
double num = x0 - x1;
|
||||
double denom = y0 - y1;
|
||||
double xstart = (x0 + (ystart - y0) * num / denom);
|
||||
double xend = (x0 + (yend - y0) * num / denom);
|
||||
return new Order1(xstart, ystart, xend, yend, dir);
|
||||
}
|
||||
|
||||
public Curve getReversedCurve() {
|
||||
return new Order1(x0, y0, x1, y1, -direction);
|
||||
}
|
||||
|
||||
public int compareTo(Curve other, double yrange[]) {
|
||||
if (!(other instanceof Order1)) {
|
||||
return super.compareTo(other, yrange);
|
||||
}
|
||||
Order1 c1 = (Order1) other;
|
||||
if (yrange[1] <= yrange[0]) {
|
||||
throw new InternalError("yrange already screwed up...");
|
||||
}
|
||||
yrange[1] = Math.min(Math.min(yrange[1], y1), c1.y1);
|
||||
if (yrange[1] <= yrange[0]) {
|
||||
throw new InternalError("backstepping from "+yrange[0]+" to "+yrange[1]);
|
||||
}
|
||||
if (xmax <= c1.xmin) {
|
||||
return (xmin == c1.xmax) ? 0 : -1;
|
||||
}
|
||||
if (xmin >= c1.xmax) {
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* If "this" is curve A and "other" is curve B, then...
|
||||
* xA(y) = x0A + (y - y0A) (x1A - x0A) / (y1A - y0A)
|
||||
* xB(y) = x0B + (y - y0B) (x1B - x0B) / (y1B - y0B)
|
||||
* xA(y) == xB(y)
|
||||
* x0A + (y - y0A) (x1A - x0A) / (y1A - y0A)
|
||||
* == x0B + (y - y0B) (x1B - x0B) / (y1B - y0B)
|
||||
* 0 == x0A (y1A - y0A) (y1B - y0B) + (y - y0A) (x1A - x0A) (y1B - y0B)
|
||||
* - x0B (y1A - y0A) (y1B - y0B) - (y - y0B) (x1B - x0B) (y1A - y0A)
|
||||
* 0 == (x0A - x0B) (y1A - y0A) (y1B - y0B)
|
||||
* + (y - y0A) (x1A - x0A) (y1B - y0B)
|
||||
* - (y - y0B) (x1B - x0B) (y1A - y0A)
|
||||
* If (dxA == x1A - x0A), etc...
|
||||
* 0 == (x0A - x0B) * dyA * dyB
|
||||
* + (y - y0A) * dxA * dyB
|
||||
* - (y - y0B) * dxB * dyA
|
||||
* 0 == (x0A - x0B) * dyA * dyB
|
||||
* + y * dxA * dyB - y0A * dxA * dyB
|
||||
* - y * dxB * dyA + y0B * dxB * dyA
|
||||
* 0 == (x0A - x0B) * dyA * dyB
|
||||
* + y * dxA * dyB - y * dxB * dyA
|
||||
* - y0A * dxA * dyB + y0B * dxB * dyA
|
||||
* 0 == (x0A - x0B) * dyA * dyB
|
||||
* + y * (dxA * dyB - dxB * dyA)
|
||||
* - y0A * dxA * dyB + y0B * dxB * dyA
|
||||
* y == ((x0A - x0B) * dyA * dyB
|
||||
* - y0A * dxA * dyB + y0B * dxB * dyA)
|
||||
* / (-(dxA * dyB - dxB * dyA))
|
||||
* y == ((x0A - x0B) * dyA * dyB
|
||||
* - y0A * dxA * dyB + y0B * dxB * dyA)
|
||||
* / (dxB * dyA - dxA * dyB)
|
||||
*/
|
||||
double dxa = x1 - x0;
|
||||
double dya = y1 - y0;
|
||||
double dxb = c1.x1 - c1.x0;
|
||||
double dyb = c1.y1 - c1.y0;
|
||||
double denom = dxb * dya - dxa * dyb;
|
||||
double y;
|
||||
if (denom != 0) {
|
||||
double num = ((x0 - c1.x0) * dya * dyb
|
||||
- y0 * dxa * dyb
|
||||
+ c1.y0 * dxb * dya);
|
||||
y = num / denom;
|
||||
if (y <= yrange[0]) {
|
||||
// intersection is above us
|
||||
// Use bottom-most common y for comparison
|
||||
y = Math.min(y1, c1.y1);
|
||||
} else {
|
||||
// intersection is below the top of our range
|
||||
if (y < yrange[1]) {
|
||||
// If intersection is in our range, adjust valid range
|
||||
yrange[1] = y;
|
||||
}
|
||||
// Use top-most common y for comparison
|
||||
y = Math.max(y0, c1.y0);
|
||||
}
|
||||
} else {
|
||||
// lines are parallel, choose any common y for comparison
|
||||
// Note - prefer an endpoint for speed of calculating the X
|
||||
// (see shortcuts in Order1.XforY())
|
||||
y = Math.max(y0, c1.y0);
|
||||
}
|
||||
return orderof(XforY(y), c1.XforY(y));
|
||||
}
|
||||
|
||||
public int getSegment(double coords[]) {
|
||||
if (direction == INCREASING) {
|
||||
coords[0] = x1;
|
||||
coords[1] = y1;
|
||||
} else {
|
||||
coords[0] = x0;
|
||||
coords[1] = y0;
|
||||
}
|
||||
return PathIterator.SEG_LINETO;
|
||||
}
|
||||
}
|
||||
453
jdkSrc/jdk8/sun/awt/geom/Order2.java
Normal file
453
jdkSrc/jdk8/sun/awt/geom/Order2.java
Normal file
@@ -0,0 +1,453 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.awt.geom;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.QuadCurve2D;
|
||||
import java.util.Vector;
|
||||
|
||||
final class Order2 extends Curve {
|
||||
private double x0;
|
||||
private double y0;
|
||||
private double cx0;
|
||||
private double cy0;
|
||||
private double x1;
|
||||
private double y1;
|
||||
private double xmin;
|
||||
private double xmax;
|
||||
|
||||
private double xcoeff0;
|
||||
private double xcoeff1;
|
||||
private double xcoeff2;
|
||||
private double ycoeff0;
|
||||
private double ycoeff1;
|
||||
private double ycoeff2;
|
||||
|
||||
public static void insert(Vector curves, double tmp[],
|
||||
double x0, double y0,
|
||||
double cx0, double cy0,
|
||||
double x1, double y1,
|
||||
int direction)
|
||||
{
|
||||
int numparams = getHorizontalParams(y0, cy0, y1, tmp);
|
||||
if (numparams == 0) {
|
||||
// We are using addInstance here to avoid inserting horisontal
|
||||
// segments
|
||||
addInstance(curves, x0, y0, cx0, cy0, x1, y1, direction);
|
||||
return;
|
||||
}
|
||||
// assert(numparams == 1);
|
||||
double t = tmp[0];
|
||||
tmp[0] = x0; tmp[1] = y0;
|
||||
tmp[2] = cx0; tmp[3] = cy0;
|
||||
tmp[4] = x1; tmp[5] = y1;
|
||||
split(tmp, 0, t);
|
||||
int i0 = (direction == INCREASING)? 0 : 4;
|
||||
int i1 = 4 - i0;
|
||||
addInstance(curves, tmp[i0], tmp[i0 + 1], tmp[i0 + 2], tmp[i0 + 3],
|
||||
tmp[i0 + 4], tmp[i0 + 5], direction);
|
||||
addInstance(curves, tmp[i1], tmp[i1 + 1], tmp[i1 + 2], tmp[i1 + 3],
|
||||
tmp[i1 + 4], tmp[i1 + 5], direction);
|
||||
}
|
||||
|
||||
public static void addInstance(Vector curves,
|
||||
double x0, double y0,
|
||||
double cx0, double cy0,
|
||||
double x1, double y1,
|
||||
int direction) {
|
||||
if (y0 > y1) {
|
||||
curves.add(new Order2(x1, y1, cx0, cy0, x0, y0, -direction));
|
||||
} else if (y1 > y0) {
|
||||
curves.add(new Order2(x0, y0, cx0, cy0, x1, y1, direction));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the count of the number of horizontal sections of the
|
||||
* specified quadratic Bezier curve. Put the parameters for the
|
||||
* horizontal sections into the specified <code>ret</code> array.
|
||||
* <p>
|
||||
* If we examine the parametric equation in t, we have:
|
||||
* Py(t) = C0*(1-t)^2 + 2*CP*t*(1-t) + C1*t^2
|
||||
* = C0 - 2*C0*t + C0*t^2 + 2*CP*t - 2*CP*t^2 + C1*t^2
|
||||
* = C0 + (2*CP - 2*C0)*t + (C0 - 2*CP + C1)*t^2
|
||||
* Py(t) = (C0 - 2*CP + C1)*t^2 + (2*CP - 2*C0)*t + (C0)
|
||||
* If we take the derivative, we get:
|
||||
* Py(t) = At^2 + Bt + C
|
||||
* dPy(t) = 2At + B = 0
|
||||
* 2*(C0 - 2*CP + C1)t + 2*(CP - C0) = 0
|
||||
* 2*(C0 - 2*CP + C1)t = 2*(C0 - CP)
|
||||
* t = 2*(C0 - CP) / 2*(C0 - 2*CP + C1)
|
||||
* t = (C0 - CP) / (C0 - CP + C1 - CP)
|
||||
* Note that this method will return 0 if the equation is a line,
|
||||
* which is either always horizontal or never horizontal.
|
||||
* Completely horizontal curves need to be eliminated by other
|
||||
* means outside of this method.
|
||||
*/
|
||||
public static int getHorizontalParams(double c0, double cp, double c1,
|
||||
double ret[]) {
|
||||
if (c0 <= cp && cp <= c1) {
|
||||
return 0;
|
||||
}
|
||||
c0 -= cp;
|
||||
c1 -= cp;
|
||||
double denom = c0 + c1;
|
||||
// If denom == 0 then cp == (c0+c1)/2 and we have a line.
|
||||
if (denom == 0) {
|
||||
return 0;
|
||||
}
|
||||
double t = c0 / denom;
|
||||
// No splits at t==0 and t==1
|
||||
if (t <= 0 || t >= 1) {
|
||||
return 0;
|
||||
}
|
||||
ret[0] = t;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split the quadratic Bezier stored at coords[pos...pos+5] representing
|
||||
* the paramtric range [0..1] into two subcurves representing the
|
||||
* parametric subranges [0..t] and [t..1]. Store the results back
|
||||
* into the array at coords[pos...pos+5] and coords[pos+4...pos+9].
|
||||
*/
|
||||
public static void split(double coords[], int pos, double t) {
|
||||
double x0, y0, cx, cy, x1, y1;
|
||||
coords[pos+8] = x1 = coords[pos+4];
|
||||
coords[pos+9] = y1 = coords[pos+5];
|
||||
cx = coords[pos+2];
|
||||
cy = coords[pos+3];
|
||||
x1 = cx + (x1 - cx) * t;
|
||||
y1 = cy + (y1 - cy) * t;
|
||||
x0 = coords[pos+0];
|
||||
y0 = coords[pos+1];
|
||||
x0 = x0 + (cx - x0) * t;
|
||||
y0 = y0 + (cy - y0) * t;
|
||||
cx = x0 + (x1 - x0) * t;
|
||||
cy = y0 + (y1 - y0) * t;
|
||||
coords[pos+2] = x0;
|
||||
coords[pos+3] = y0;
|
||||
coords[pos+4] = cx;
|
||||
coords[pos+5] = cy;
|
||||
coords[pos+6] = x1;
|
||||
coords[pos+7] = y1;
|
||||
}
|
||||
|
||||
public Order2(double x0, double y0,
|
||||
double cx0, double cy0,
|
||||
double x1, double y1,
|
||||
int direction)
|
||||
{
|
||||
super(direction);
|
||||
// REMIND: Better accuracy in the root finding methods would
|
||||
// ensure that cy0 is in range. As it stands, it is never
|
||||
// more than "1 mantissa bit" out of range...
|
||||
if (cy0 < y0) {
|
||||
cy0 = y0;
|
||||
} else if (cy0 > y1) {
|
||||
cy0 = y1;
|
||||
}
|
||||
this.x0 = x0;
|
||||
this.y0 = y0;
|
||||
this.cx0 = cx0;
|
||||
this.cy0 = cy0;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
xmin = Math.min(Math.min(x0, x1), cx0);
|
||||
xmax = Math.max(Math.max(x0, x1), cx0);
|
||||
xcoeff0 = x0;
|
||||
xcoeff1 = cx0 + cx0 - x0 - x0;
|
||||
xcoeff2 = x0 - cx0 - cx0 + x1;
|
||||
ycoeff0 = y0;
|
||||
ycoeff1 = cy0 + cy0 - y0 - y0;
|
||||
ycoeff2 = y0 - cy0 - cy0 + y1;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public double getXTop() {
|
||||
return x0;
|
||||
}
|
||||
|
||||
public double getYTop() {
|
||||
return y0;
|
||||
}
|
||||
|
||||
public double getXBot() {
|
||||
return x1;
|
||||
}
|
||||
|
||||
public double getYBot() {
|
||||
return y1;
|
||||
}
|
||||
|
||||
public double getXMin() {
|
||||
return xmin;
|
||||
}
|
||||
|
||||
public double getXMax() {
|
||||
return xmax;
|
||||
}
|
||||
|
||||
public double getX0() {
|
||||
return (direction == INCREASING) ? x0 : x1;
|
||||
}
|
||||
|
||||
public double getY0() {
|
||||
return (direction == INCREASING) ? y0 : y1;
|
||||
}
|
||||
|
||||
public double getCX0() {
|
||||
return cx0;
|
||||
}
|
||||
|
||||
public double getCY0() {
|
||||
return cy0;
|
||||
}
|
||||
|
||||
public double getX1() {
|
||||
return (direction == DECREASING) ? x0 : x1;
|
||||
}
|
||||
|
||||
public double getY1() {
|
||||
return (direction == DECREASING) ? y0 : y1;
|
||||
}
|
||||
|
||||
public double XforY(double y) {
|
||||
if (y <= y0) {
|
||||
return x0;
|
||||
}
|
||||
if (y >= y1) {
|
||||
return x1;
|
||||
}
|
||||
return XforT(TforY(y));
|
||||
}
|
||||
|
||||
public double TforY(double y) {
|
||||
if (y <= y0) {
|
||||
return 0;
|
||||
}
|
||||
if (y >= y1) {
|
||||
return 1;
|
||||
}
|
||||
return TforY(y, ycoeff0, ycoeff1, ycoeff2);
|
||||
}
|
||||
|
||||
public static double TforY(double y,
|
||||
double ycoeff0, double ycoeff1, double ycoeff2)
|
||||
{
|
||||
// The caller should have already eliminated y values
|
||||
// outside of the y0 to y1 range.
|
||||
ycoeff0 -= y;
|
||||
if (ycoeff2 == 0.0) {
|
||||
// The quadratic parabola has degenerated to a line.
|
||||
// ycoeff1 should not be 0.0 since we have already eliminated
|
||||
// totally horizontal lines, but if it is, then we will generate
|
||||
// infinity here for the root, which will not be in the [0,1]
|
||||
// range so we will pass to the failure code below.
|
||||
double root = -ycoeff0 / ycoeff1;
|
||||
if (root >= 0 && root <= 1) {
|
||||
return root;
|
||||
}
|
||||
} else {
|
||||
// From Numerical Recipes, 5.6, Quadratic and Cubic Equations
|
||||
double d = ycoeff1 * ycoeff1 - 4.0 * ycoeff2 * ycoeff0;
|
||||
// If d < 0.0, then there are no roots
|
||||
if (d >= 0.0) {
|
||||
d = Math.sqrt(d);
|
||||
// For accuracy, calculate one root using:
|
||||
// (-ycoeff1 +/- d) / 2ycoeff2
|
||||
// and the other using:
|
||||
// 2ycoeff0 / (-ycoeff1 +/- d)
|
||||
// Choose the sign of the +/- so that ycoeff1+d
|
||||
// gets larger in magnitude
|
||||
if (ycoeff1 < 0.0) {
|
||||
d = -d;
|
||||
}
|
||||
double q = (ycoeff1 + d) / -2.0;
|
||||
// We already tested ycoeff2 for being 0 above
|
||||
double root = q / ycoeff2;
|
||||
if (root >= 0 && root <= 1) {
|
||||
return root;
|
||||
}
|
||||
if (q != 0.0) {
|
||||
root = ycoeff0 / q;
|
||||
if (root >= 0 && root <= 1) {
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* We failed to find a root in [0,1]. What could have gone wrong?
|
||||
* First, remember that these curves are constructed to be monotonic
|
||||
* in Y and totally horizontal curves have already been eliminated.
|
||||
* Now keep in mind that the Y coefficients of the polynomial form
|
||||
* of the curve are calculated from the Y coordinates which define
|
||||
* our curve. They should theoretically define the same curve,
|
||||
* but they can be off by a couple of bits of precision after the
|
||||
* math is done and so can represent a slightly modified curve.
|
||||
* This is normally not an issue except when we have solutions near
|
||||
* the endpoints. Since the answers we get from solving the polynomial
|
||||
* may be off by a few bits that means that they could lie just a
|
||||
* few bits of precision outside the [0,1] range.
|
||||
*
|
||||
* Another problem could be that while the parametric curve defined
|
||||
* by the Y coordinates has a local minima or maxima at or just
|
||||
* outside of the endpoints, the polynomial form might express
|
||||
* that same min/max just inside of and just shy of the Y coordinate
|
||||
* of that endpoint. In that case, if we solve for a Y coordinate
|
||||
* at or near that endpoint, we may be solving for a Y coordinate
|
||||
* that is below that minima or above that maxima and we would find
|
||||
* no solutions at all.
|
||||
*
|
||||
* In either case, we can assume that y is so near one of the
|
||||
* endpoints that we can just collapse it onto the nearest endpoint
|
||||
* without losing more than a couple of bits of precision.
|
||||
*/
|
||||
// First calculate the midpoint between y0 and y1 and choose to
|
||||
// return either 0.0 or 1.0 depending on whether y is above
|
||||
// or below the midpoint...
|
||||
// Note that we subtracted y from ycoeff0 above so both y0 and y1
|
||||
// will be "relative to y" so we are really just looking at where
|
||||
// zero falls with respect to the "relative midpoint" here.
|
||||
double y0 = ycoeff0;
|
||||
double y1 = ycoeff0 + ycoeff1 + ycoeff2;
|
||||
return (0 < (y0 + y1) / 2) ? 0.0 : 1.0;
|
||||
}
|
||||
|
||||
public double XforT(double t) {
|
||||
return (xcoeff2 * t + xcoeff1) * t + xcoeff0;
|
||||
}
|
||||
|
||||
public double YforT(double t) {
|
||||
return (ycoeff2 * t + ycoeff1) * t + ycoeff0;
|
||||
}
|
||||
|
||||
public double dXforT(double t, int deriv) {
|
||||
switch (deriv) {
|
||||
case 0:
|
||||
return (xcoeff2 * t + xcoeff1) * t + xcoeff0;
|
||||
case 1:
|
||||
return 2 * xcoeff2 * t + xcoeff1;
|
||||
case 2:
|
||||
return 2 * xcoeff2;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public double dYforT(double t, int deriv) {
|
||||
switch (deriv) {
|
||||
case 0:
|
||||
return (ycoeff2 * t + ycoeff1) * t + ycoeff0;
|
||||
case 1:
|
||||
return 2 * ycoeff2 * t + ycoeff1;
|
||||
case 2:
|
||||
return 2 * ycoeff2;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public double nextVertical(double t0, double t1) {
|
||||
double t = -xcoeff1 / (2 * xcoeff2);
|
||||
if (t > t0 && t < t1) {
|
||||
return t;
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
public void enlarge(Rectangle2D r) {
|
||||
r.add(x0, y0);
|
||||
double t = -xcoeff1 / (2 * xcoeff2);
|
||||
if (t > 0 && t < 1) {
|
||||
r.add(XforT(t), YforT(t));
|
||||
}
|
||||
r.add(x1, y1);
|
||||
}
|
||||
|
||||
public Curve getSubCurve(double ystart, double yend, int dir) {
|
||||
double t0, t1;
|
||||
if (ystart <= y0) {
|
||||
if (yend >= y1) {
|
||||
return getWithDirection(dir);
|
||||
}
|
||||
t0 = 0;
|
||||
} else {
|
||||
t0 = TforY(ystart, ycoeff0, ycoeff1, ycoeff2);
|
||||
}
|
||||
if (yend >= y1) {
|
||||
t1 = 1;
|
||||
} else {
|
||||
t1 = TforY(yend, ycoeff0, ycoeff1, ycoeff2);
|
||||
}
|
||||
double eqn[] = new double[10];
|
||||
eqn[0] = x0;
|
||||
eqn[1] = y0;
|
||||
eqn[2] = cx0;
|
||||
eqn[3] = cy0;
|
||||
eqn[4] = x1;
|
||||
eqn[5] = y1;
|
||||
if (t1 < 1) {
|
||||
split(eqn, 0, t1);
|
||||
}
|
||||
int i;
|
||||
if (t0 <= 0) {
|
||||
i = 0;
|
||||
} else {
|
||||
split(eqn, 0, t0 / t1);
|
||||
i = 4;
|
||||
}
|
||||
return new Order2(eqn[i+0], ystart,
|
||||
eqn[i+2], eqn[i+3],
|
||||
eqn[i+4], yend,
|
||||
dir);
|
||||
}
|
||||
|
||||
public Curve getReversedCurve() {
|
||||
return new Order2(x0, y0, cx0, cy0, x1, y1, -direction);
|
||||
}
|
||||
|
||||
public int getSegment(double coords[]) {
|
||||
coords[0] = cx0;
|
||||
coords[1] = cy0;
|
||||
if (direction == INCREASING) {
|
||||
coords[2] = x1;
|
||||
coords[3] = y1;
|
||||
} else {
|
||||
coords[2] = x0;
|
||||
coords[3] = y0;
|
||||
}
|
||||
return PathIterator.SEG_QUADTO;
|
||||
}
|
||||
|
||||
public String controlPointString() {
|
||||
return ("("+round(cx0)+", "+round(cy0)+"), ");
|
||||
}
|
||||
}
|
||||
634
jdkSrc/jdk8/sun/awt/geom/Order3.java
Normal file
634
jdkSrc/jdk8/sun/awt/geom/Order3.java
Normal file
@@ -0,0 +1,634 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.awt.geom;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.QuadCurve2D;
|
||||
import java.util.Vector;
|
||||
|
||||
final class Order3 extends Curve {
|
||||
private double x0;
|
||||
private double y0;
|
||||
private double cx0;
|
||||
private double cy0;
|
||||
private double cx1;
|
||||
private double cy1;
|
||||
private double x1;
|
||||
private double y1;
|
||||
|
||||
private double xmin;
|
||||
private double xmax;
|
||||
|
||||
private double xcoeff0;
|
||||
private double xcoeff1;
|
||||
private double xcoeff2;
|
||||
private double xcoeff3;
|
||||
|
||||
private double ycoeff0;
|
||||
private double ycoeff1;
|
||||
private double ycoeff2;
|
||||
private double ycoeff3;
|
||||
|
||||
public static void insert(Vector curves, double tmp[],
|
||||
double x0, double y0,
|
||||
double cx0, double cy0,
|
||||
double cx1, double cy1,
|
||||
double x1, double y1,
|
||||
int direction)
|
||||
{
|
||||
int numparams = getHorizontalParams(y0, cy0, cy1, y1, tmp);
|
||||
if (numparams == 0) {
|
||||
// We are using addInstance here to avoid inserting horisontal
|
||||
// segments
|
||||
addInstance(curves, x0, y0, cx0, cy0, cx1, cy1, x1, y1, direction);
|
||||
return;
|
||||
}
|
||||
// Store coordinates for splitting at tmp[3..10]
|
||||
tmp[3] = x0; tmp[4] = y0;
|
||||
tmp[5] = cx0; tmp[6] = cy0;
|
||||
tmp[7] = cx1; tmp[8] = cy1;
|
||||
tmp[9] = x1; tmp[10] = y1;
|
||||
double t = tmp[0];
|
||||
if (numparams > 1 && t > tmp[1]) {
|
||||
// Perform a "2 element sort"...
|
||||
tmp[0] = tmp[1];
|
||||
tmp[1] = t;
|
||||
t = tmp[0];
|
||||
}
|
||||
split(tmp, 3, t);
|
||||
if (numparams > 1) {
|
||||
// Recalculate tmp[1] relative to the range [tmp[0]...1]
|
||||
t = (tmp[1] - t) / (1 - t);
|
||||
split(tmp, 9, t);
|
||||
}
|
||||
int index = 3;
|
||||
if (direction == DECREASING) {
|
||||
index += numparams * 6;
|
||||
}
|
||||
while (numparams >= 0) {
|
||||
addInstance(curves,
|
||||
tmp[index + 0], tmp[index + 1],
|
||||
tmp[index + 2], tmp[index + 3],
|
||||
tmp[index + 4], tmp[index + 5],
|
||||
tmp[index + 6], tmp[index + 7],
|
||||
direction);
|
||||
numparams--;
|
||||
if (direction == INCREASING) {
|
||||
index += 6;
|
||||
} else {
|
||||
index -= 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void addInstance(Vector curves,
|
||||
double x0, double y0,
|
||||
double cx0, double cy0,
|
||||
double cx1, double cy1,
|
||||
double x1, double y1,
|
||||
int direction) {
|
||||
if (y0 > y1) {
|
||||
curves.add(new Order3(x1, y1, cx1, cy1, cx0, cy0, x0, y0,
|
||||
-direction));
|
||||
} else if (y1 > y0) {
|
||||
curves.add(new Order3(x0, y0, cx0, cy0, cx1, cy1, x1, y1,
|
||||
direction));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the count of the number of horizontal sections of the
|
||||
* specified cubic Bezier curve. Put the parameters for the
|
||||
* horizontal sections into the specified <code>ret</code> array.
|
||||
* <p>
|
||||
* If we examine the parametric equation in t, we have:
|
||||
* Py(t) = C0(1-t)^3 + 3CP0 t(1-t)^2 + 3CP1 t^2(1-t) + C1 t^3
|
||||
* = C0 - 3C0t + 3C0t^2 - C0t^3 +
|
||||
* 3CP0t - 6CP0t^2 + 3CP0t^3 +
|
||||
* 3CP1t^2 - 3CP1t^3 +
|
||||
* C1t^3
|
||||
* Py(t) = (C1 - 3CP1 + 3CP0 - C0) t^3 +
|
||||
* (3C0 - 6CP0 + 3CP1) t^2 +
|
||||
* (3CP0 - 3C0) t +
|
||||
* (C0)
|
||||
* If we take the derivative, we get:
|
||||
* Py(t) = Dt^3 + At^2 + Bt + C
|
||||
* dPy(t) = 3Dt^2 + 2At + B = 0
|
||||
* 0 = 3*(C1 - 3*CP1 + 3*CP0 - C0)t^2
|
||||
* + 2*(3*CP1 - 6*CP0 + 3*C0)t
|
||||
* + (3*CP0 - 3*C0)
|
||||
* 0 = 3*(C1 - 3*CP1 + 3*CP0 - C0)t^2
|
||||
* + 3*2*(CP1 - 2*CP0 + C0)t
|
||||
* + 3*(CP0 - C0)
|
||||
* 0 = (C1 - CP1 - CP1 - CP1 + CP0 + CP0 + CP0 - C0)t^2
|
||||
* + 2*(CP1 - CP0 - CP0 + C0)t
|
||||
* + (CP0 - C0)
|
||||
* 0 = (C1 - CP1 + CP0 - CP1 + CP0 - CP1 + CP0 - C0)t^2
|
||||
* + 2*(CP1 - CP0 - CP0 + C0)t
|
||||
* + (CP0 - C0)
|
||||
* 0 = ((C1 - CP1) - (CP1 - CP0) - (CP1 - CP0) + (CP0 - C0))t^2
|
||||
* + 2*((CP1 - CP0) - (CP0 - C0))t
|
||||
* + (CP0 - C0)
|
||||
* Note that this method will return 0 if the equation is a line,
|
||||
* which is either always horizontal or never horizontal.
|
||||
* Completely horizontal curves need to be eliminated by other
|
||||
* means outside of this method.
|
||||
*/
|
||||
public static int getHorizontalParams(double c0, double cp0,
|
||||
double cp1, double c1,
|
||||
double ret[]) {
|
||||
if (c0 <= cp0 && cp0 <= cp1 && cp1 <= c1) {
|
||||
return 0;
|
||||
}
|
||||
c1 -= cp1;
|
||||
cp1 -= cp0;
|
||||
cp0 -= c0;
|
||||
ret[0] = cp0;
|
||||
ret[1] = (cp1 - cp0) * 2;
|
||||
ret[2] = (c1 - cp1 - cp1 + cp0);
|
||||
int numroots = QuadCurve2D.solveQuadratic(ret, ret);
|
||||
int j = 0;
|
||||
for (int i = 0; i < numroots; i++) {
|
||||
double t = ret[i];
|
||||
// No splits at t==0 and t==1
|
||||
if (t > 0 && t < 1) {
|
||||
if (j < i) {
|
||||
ret[j] = t;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split the cubic Bezier stored at coords[pos...pos+7] representing
|
||||
* the parametric range [0..1] into two subcurves representing the
|
||||
* parametric subranges [0..t] and [t..1]. Store the results back
|
||||
* into the array at coords[pos...pos+7] and coords[pos+6...pos+13].
|
||||
*/
|
||||
public static void split(double coords[], int pos, double t) {
|
||||
double x0, y0, cx0, cy0, cx1, cy1, x1, y1;
|
||||
coords[pos+12] = x1 = coords[pos+6];
|
||||
coords[pos+13] = y1 = coords[pos+7];
|
||||
cx1 = coords[pos+4];
|
||||
cy1 = coords[pos+5];
|
||||
x1 = cx1 + (x1 - cx1) * t;
|
||||
y1 = cy1 + (y1 - cy1) * t;
|
||||
x0 = coords[pos+0];
|
||||
y0 = coords[pos+1];
|
||||
cx0 = coords[pos+2];
|
||||
cy0 = coords[pos+3];
|
||||
x0 = x0 + (cx0 - x0) * t;
|
||||
y0 = y0 + (cy0 - y0) * t;
|
||||
cx0 = cx0 + (cx1 - cx0) * t;
|
||||
cy0 = cy0 + (cy1 - cy0) * t;
|
||||
cx1 = cx0 + (x1 - cx0) * t;
|
||||
cy1 = cy0 + (y1 - cy0) * t;
|
||||
cx0 = x0 + (cx0 - x0) * t;
|
||||
cy0 = y0 + (cy0 - y0) * t;
|
||||
coords[pos+2] = x0;
|
||||
coords[pos+3] = y0;
|
||||
coords[pos+4] = cx0;
|
||||
coords[pos+5] = cy0;
|
||||
coords[pos+6] = cx0 + (cx1 - cx0) * t;
|
||||
coords[pos+7] = cy0 + (cy1 - cy0) * t;
|
||||
coords[pos+8] = cx1;
|
||||
coords[pos+9] = cy1;
|
||||
coords[pos+10] = x1;
|
||||
coords[pos+11] = y1;
|
||||
}
|
||||
|
||||
public Order3(double x0, double y0,
|
||||
double cx0, double cy0,
|
||||
double cx1, double cy1,
|
||||
double x1, double y1,
|
||||
int direction)
|
||||
{
|
||||
super(direction);
|
||||
// REMIND: Better accuracy in the root finding methods would
|
||||
// ensure that cys are in range. As it stands, they are never
|
||||
// more than "1 mantissa bit" out of range...
|
||||
if (cy0 < y0) cy0 = y0;
|
||||
if (cy1 > y1) cy1 = y1;
|
||||
this.x0 = x0;
|
||||
this.y0 = y0;
|
||||
this.cx0 = cx0;
|
||||
this.cy0 = cy0;
|
||||
this.cx1 = cx1;
|
||||
this.cy1 = cy1;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
xmin = Math.min(Math.min(x0, x1), Math.min(cx0, cx1));
|
||||
xmax = Math.max(Math.max(x0, x1), Math.max(cx0, cx1));
|
||||
xcoeff0 = x0;
|
||||
xcoeff1 = (cx0 - x0) * 3.0;
|
||||
xcoeff2 = (cx1 - cx0 - cx0 + x0) * 3.0;
|
||||
xcoeff3 = x1 - (cx1 - cx0) * 3.0 - x0;
|
||||
ycoeff0 = y0;
|
||||
ycoeff1 = (cy0 - y0) * 3.0;
|
||||
ycoeff2 = (cy1 - cy0 - cy0 + y0) * 3.0;
|
||||
ycoeff3 = y1 - (cy1 - cy0) * 3.0 - y0;
|
||||
YforT1 = YforT2 = YforT3 = y0;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
public double getXTop() {
|
||||
return x0;
|
||||
}
|
||||
|
||||
public double getYTop() {
|
||||
return y0;
|
||||
}
|
||||
|
||||
public double getXBot() {
|
||||
return x1;
|
||||
}
|
||||
|
||||
public double getYBot() {
|
||||
return y1;
|
||||
}
|
||||
|
||||
public double getXMin() {
|
||||
return xmin;
|
||||
}
|
||||
|
||||
public double getXMax() {
|
||||
return xmax;
|
||||
}
|
||||
|
||||
public double getX0() {
|
||||
return (direction == INCREASING) ? x0 : x1;
|
||||
}
|
||||
|
||||
public double getY0() {
|
||||
return (direction == INCREASING) ? y0 : y1;
|
||||
}
|
||||
|
||||
public double getCX0() {
|
||||
return (direction == INCREASING) ? cx0 : cx1;
|
||||
}
|
||||
|
||||
public double getCY0() {
|
||||
return (direction == INCREASING) ? cy0 : cy1;
|
||||
}
|
||||
|
||||
public double getCX1() {
|
||||
return (direction == DECREASING) ? cx0 : cx1;
|
||||
}
|
||||
|
||||
public double getCY1() {
|
||||
return (direction == DECREASING) ? cy0 : cy1;
|
||||
}
|
||||
|
||||
public double getX1() {
|
||||
return (direction == DECREASING) ? x0 : x1;
|
||||
}
|
||||
|
||||
public double getY1() {
|
||||
return (direction == DECREASING) ? y0 : y1;
|
||||
}
|
||||
|
||||
private double TforY1;
|
||||
private double YforT1;
|
||||
private double TforY2;
|
||||
private double YforT2;
|
||||
private double TforY3;
|
||||
private double YforT3;
|
||||
|
||||
/*
|
||||
* Solve the cubic whose coefficients are in the a,b,c,d fields and
|
||||
* return the first root in the range [0, 1].
|
||||
* The cubic solved is represented by the equation:
|
||||
* x^3 + (ycoeff2)x^2 + (ycoeff1)x + (ycoeff0) = y
|
||||
* @return the first valid root (in the range [0, 1])
|
||||
*/
|
||||
public double TforY(double y) {
|
||||
if (y <= y0) return 0;
|
||||
if (y >= y1) return 1;
|
||||
if (y == YforT1) return TforY1;
|
||||
if (y == YforT2) return TforY2;
|
||||
if (y == YforT3) return TforY3;
|
||||
// From Numerical Recipes, 5.6, Quadratic and Cubic Equations
|
||||
if (ycoeff3 == 0.0) {
|
||||
// The cubic degenerated to quadratic (or line or ...).
|
||||
return Order2.TforY(y, ycoeff0, ycoeff1, ycoeff2);
|
||||
}
|
||||
double a = ycoeff2 / ycoeff3;
|
||||
double b = ycoeff1 / ycoeff3;
|
||||
double c = (ycoeff0 - y) / ycoeff3;
|
||||
int roots = 0;
|
||||
double Q = (a * a - 3.0 * b) / 9.0;
|
||||
double R = (2.0 * a * a * a - 9.0 * a * b + 27.0 * c) / 54.0;
|
||||
double R2 = R * R;
|
||||
double Q3 = Q * Q * Q;
|
||||
double a_3 = a / 3.0;
|
||||
double t;
|
||||
if (R2 < Q3) {
|
||||
double theta = Math.acos(R / Math.sqrt(Q3));
|
||||
Q = -2.0 * Math.sqrt(Q);
|
||||
t = refine(a, b, c, y, Q * Math.cos(theta / 3.0) - a_3);
|
||||
if (t < 0) {
|
||||
t = refine(a, b, c, y,
|
||||
Q * Math.cos((theta + Math.PI * 2.0)/ 3.0) - a_3);
|
||||
}
|
||||
if (t < 0) {
|
||||
t = refine(a, b, c, y,
|
||||
Q * Math.cos((theta - Math.PI * 2.0)/ 3.0) - a_3);
|
||||
}
|
||||
} else {
|
||||
boolean neg = (R < 0.0);
|
||||
double S = Math.sqrt(R2 - Q3);
|
||||
if (neg) {
|
||||
R = -R;
|
||||
}
|
||||
double A = Math.pow(R + S, 1.0 / 3.0);
|
||||
if (!neg) {
|
||||
A = -A;
|
||||
}
|
||||
double B = (A == 0.0) ? 0.0 : (Q / A);
|
||||
t = refine(a, b, c, y, (A + B) - a_3);
|
||||
}
|
||||
if (t < 0) {
|
||||
//throw new InternalError("bad t");
|
||||
double t0 = 0;
|
||||
double t1 = 1;
|
||||
while (true) {
|
||||
t = (t0 + t1) / 2;
|
||||
if (t == t0 || t == t1) {
|
||||
break;
|
||||
}
|
||||
double yt = YforT(t);
|
||||
if (yt < y) {
|
||||
t0 = t;
|
||||
} else if (yt > y) {
|
||||
t1 = t;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (t >= 0) {
|
||||
TforY3 = TforY2;
|
||||
YforT3 = YforT2;
|
||||
TforY2 = TforY1;
|
||||
YforT2 = YforT1;
|
||||
TforY1 = t;
|
||||
YforT1 = y;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public double refine(double a, double b, double c,
|
||||
double target, double t)
|
||||
{
|
||||
if (t < -0.1 || t > 1.1) {
|
||||
return -1;
|
||||
}
|
||||
double y = YforT(t);
|
||||
double t0, t1;
|
||||
if (y < target) {
|
||||
t0 = t;
|
||||
t1 = 1;
|
||||
} else {
|
||||
t0 = 0;
|
||||
t1 = t;
|
||||
}
|
||||
double origt = t;
|
||||
double origy = y;
|
||||
boolean useslope = true;
|
||||
while (y != target) {
|
||||
if (!useslope) {
|
||||
double t2 = (t0 + t1) / 2;
|
||||
if (t2 == t0 || t2 == t1) {
|
||||
break;
|
||||
}
|
||||
t = t2;
|
||||
} else {
|
||||
double slope = dYforT(t, 1);
|
||||
if (slope == 0) {
|
||||
useslope = false;
|
||||
continue;
|
||||
}
|
||||
double t2 = t + ((target - y) / slope);
|
||||
if (t2 == t || t2 <= t0 || t2 >= t1) {
|
||||
useslope = false;
|
||||
continue;
|
||||
}
|
||||
t = t2;
|
||||
}
|
||||
y = YforT(t);
|
||||
if (y < target) {
|
||||
t0 = t;
|
||||
} else if (y > target) {
|
||||
t1 = t;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
boolean verbose = false;
|
||||
if (false && t >= 0 && t <= 1) {
|
||||
y = YforT(t);
|
||||
long tdiff = diffbits(t, origt);
|
||||
long ydiff = diffbits(y, origy);
|
||||
long yerr = diffbits(y, target);
|
||||
if (yerr > 0 || (verbose && tdiff > 0)) {
|
||||
System.out.println("target was y = "+target);
|
||||
System.out.println("original was y = "+origy+", t = "+origt);
|
||||
System.out.println("final was y = "+y+", t = "+t);
|
||||
System.out.println("t diff is "+tdiff);
|
||||
System.out.println("y diff is "+ydiff);
|
||||
System.out.println("y error is "+yerr);
|
||||
double tlow = prev(t);
|
||||
double ylow = YforT(tlow);
|
||||
double thi = next(t);
|
||||
double yhi = YforT(thi);
|
||||
if (Math.abs(target - ylow) < Math.abs(target - y) ||
|
||||
Math.abs(target - yhi) < Math.abs(target - y))
|
||||
{
|
||||
System.out.println("adjacent y's = ["+ylow+", "+yhi+"]");
|
||||
}
|
||||
}
|
||||
}
|
||||
return (t > 1) ? -1 : t;
|
||||
}
|
||||
|
||||
public double XforY(double y) {
|
||||
if (y <= y0) {
|
||||
return x0;
|
||||
}
|
||||
if (y >= y1) {
|
||||
return x1;
|
||||
}
|
||||
return XforT(TforY(y));
|
||||
}
|
||||
|
||||
public double XforT(double t) {
|
||||
return (((xcoeff3 * t) + xcoeff2) * t + xcoeff1) * t + xcoeff0;
|
||||
}
|
||||
|
||||
public double YforT(double t) {
|
||||
return (((ycoeff3 * t) + ycoeff2) * t + ycoeff1) * t + ycoeff0;
|
||||
}
|
||||
|
||||
public double dXforT(double t, int deriv) {
|
||||
switch (deriv) {
|
||||
case 0:
|
||||
return (((xcoeff3 * t) + xcoeff2) * t + xcoeff1) * t + xcoeff0;
|
||||
case 1:
|
||||
return ((3 * xcoeff3 * t) + 2 * xcoeff2) * t + xcoeff1;
|
||||
case 2:
|
||||
return (6 * xcoeff3 * t) + 2 * xcoeff2;
|
||||
case 3:
|
||||
return 6 * xcoeff3;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public double dYforT(double t, int deriv) {
|
||||
switch (deriv) {
|
||||
case 0:
|
||||
return (((ycoeff3 * t) + ycoeff2) * t + ycoeff1) * t + ycoeff0;
|
||||
case 1:
|
||||
return ((3 * ycoeff3 * t) + 2 * ycoeff2) * t + ycoeff1;
|
||||
case 2:
|
||||
return (6 * ycoeff3 * t) + 2 * ycoeff2;
|
||||
case 3:
|
||||
return 6 * ycoeff3;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public double nextVertical(double t0, double t1) {
|
||||
double eqn[] = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3};
|
||||
int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);
|
||||
for (int i = 0; i < numroots; i++) {
|
||||
if (eqn[i] > t0 && eqn[i] < t1) {
|
||||
t1 = eqn[i];
|
||||
}
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
public void enlarge(Rectangle2D r) {
|
||||
r.add(x0, y0);
|
||||
double eqn[] = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3};
|
||||
int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);
|
||||
for (int i = 0; i < numroots; i++) {
|
||||
double t = eqn[i];
|
||||
if (t > 0 && t < 1) {
|
||||
r.add(XforT(t), YforT(t));
|
||||
}
|
||||
}
|
||||
r.add(x1, y1);
|
||||
}
|
||||
|
||||
public Curve getSubCurve(double ystart, double yend, int dir) {
|
||||
if (ystart <= y0 && yend >= y1) {
|
||||
return getWithDirection(dir);
|
||||
}
|
||||
double eqn[] = new double[14];
|
||||
double t0, t1;
|
||||
t0 = TforY(ystart);
|
||||
t1 = TforY(yend);
|
||||
eqn[0] = x0;
|
||||
eqn[1] = y0;
|
||||
eqn[2] = cx0;
|
||||
eqn[3] = cy0;
|
||||
eqn[4] = cx1;
|
||||
eqn[5] = cy1;
|
||||
eqn[6] = x1;
|
||||
eqn[7] = y1;
|
||||
if (t0 > t1) {
|
||||
/* This happens in only rare cases where ystart is
|
||||
* very near yend and solving for the yend root ends
|
||||
* up stepping slightly lower in t than solving for
|
||||
* the ystart root.
|
||||
* Ideally we might want to skip this tiny little
|
||||
* segment and just fudge the surrounding coordinates
|
||||
* to bridge the gap left behind, but there is no way
|
||||
* to do that from here. Higher levels could
|
||||
* potentially eliminate these tiny "fixup" segments,
|
||||
* but not without a lot of extra work on the code that
|
||||
* coalesces chains of curves into subpaths. The
|
||||
* simplest solution for now is to just reorder the t
|
||||
* values and chop out a miniscule curve piece.
|
||||
*/
|
||||
double t = t0;
|
||||
t0 = t1;
|
||||
t1 = t;
|
||||
}
|
||||
if (t1 < 1) {
|
||||
split(eqn, 0, t1);
|
||||
}
|
||||
int i;
|
||||
if (t0 <= 0) {
|
||||
i = 0;
|
||||
} else {
|
||||
split(eqn, 0, t0 / t1);
|
||||
i = 6;
|
||||
}
|
||||
return new Order3(eqn[i+0], ystart,
|
||||
eqn[i+2], eqn[i+3],
|
||||
eqn[i+4], eqn[i+5],
|
||||
eqn[i+6], yend,
|
||||
dir);
|
||||
}
|
||||
|
||||
public Curve getReversedCurve() {
|
||||
return new Order3(x0, y0, cx0, cy0, cx1, cy1, x1, y1, -direction);
|
||||
}
|
||||
|
||||
public int getSegment(double coords[]) {
|
||||
if (direction == INCREASING) {
|
||||
coords[0] = cx0;
|
||||
coords[1] = cy0;
|
||||
coords[2] = cx1;
|
||||
coords[3] = cy1;
|
||||
coords[4] = x1;
|
||||
coords[5] = y1;
|
||||
} else {
|
||||
coords[0] = cx1;
|
||||
coords[1] = cy1;
|
||||
coords[2] = cx0;
|
||||
coords[3] = cy0;
|
||||
coords[4] = x0;
|
||||
coords[5] = y0;
|
||||
}
|
||||
return PathIterator.SEG_CUBICTO;
|
||||
}
|
||||
|
||||
public String controlPointString() {
|
||||
return (("("+round(getCX0())+", "+round(getCY0())+"), ")+
|
||||
("("+round(getCX1())+", "+round(getCY1())+"), "));
|
||||
}
|
||||
}
|
||||
78
jdkSrc/jdk8/sun/awt/geom/PathConsumer2D.java
Normal file
78
jdkSrc/jdk8/sun/awt/geom/PathConsumer2D.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.awt.geom;
|
||||
|
||||
public interface PathConsumer2D {
|
||||
/**
|
||||
* @see java.awt.geom.Path2D.Float.moveTo
|
||||
*/
|
||||
public void moveTo(float x, float y);
|
||||
|
||||
/**
|
||||
* @see java.awt.geom.Path2D.Float.lineTo
|
||||
*/
|
||||
public void lineTo(float x, float y);
|
||||
|
||||
/**
|
||||
* @see java.awt.geom.Path2D.Float.quadTo
|
||||
*/
|
||||
public void quadTo(float x1, float y1,
|
||||
float x2, float y2);
|
||||
|
||||
/**
|
||||
* @see java.awt.geom.Path2D.Float.curveTo
|
||||
*/
|
||||
public void curveTo(float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3);
|
||||
|
||||
/**
|
||||
* @see java.awt.geom.Path2D.Float.closePath
|
||||
*/
|
||||
public void closePath();
|
||||
|
||||
/**
|
||||
* Called after the last segment of the last subpath when the
|
||||
* iteration of the path segments is completely done. This
|
||||
* method serves to trigger the end of path processing in the
|
||||
* consumer that would normally be triggered when a
|
||||
* {@link java.awt.geom.PathIterator PathIterator}
|
||||
* returns {@code true} from its {@code done} method.
|
||||
*/
|
||||
public void pathDone();
|
||||
|
||||
/**
|
||||
* If a given PathConsumer performs all or most of its work
|
||||
* natively then it can return a (non-zero) pointer to a
|
||||
* native function vector that defines C functions for all
|
||||
* of the above methods.
|
||||
* The specific pointer it returns is a pointer to a
|
||||
* PathConsumerVec structure as defined in the include file
|
||||
* src/share/native/sun/java2d/pipe/PathConsumer2D.h
|
||||
* @return a native pointer to a PathConsumerVec structure.
|
||||
*/
|
||||
public long getNativeConsumer();
|
||||
}
|
||||
Reference in New Issue
Block a user