Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/java2d/Spans.java
38829 views
/*1* Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.java2d;2627import java.util.Comparator;28import java.util.Collections;29import java.util.Iterator;30import java.util.List;31import java.util.Vector;3233/**34* Maintains a list of half-open intervals, called Spans.35* A Span can be tested against the list of Spans36* for intersection.37*/38public class Spans {3940/**41* This class will sort and collapse its span42* entries after this many span additions via43* the <code>add</code> method.44*/45private static final int kMaxAddsSinceSort = 256;4647/**48* Holds a list of individual49* Span instances.50*/51private List mSpans = new Vector(kMaxAddsSinceSort);5253/**54* The number of <code>Span</code>55* instances that have been added56* to this object without a sort57* and collapse taking place.58*/59private int mAddsSinceSort = 0;6061public Spans() {6263}6465/**66* Add a span covering the half open interval67* including <code>start</code> up to68* but not including <code>end</code>.69*/70public void add(float start, float end) {7172if (mSpans != null) {73mSpans.add(new Span(start, end));7475if (++mAddsSinceSort >= kMaxAddsSinceSort) {76sortAndCollapse();77}78}79}8081/**82* Add a span which covers the entire range.83* This call is logically equivalent to84* <code>add(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY)</code>85* The result of making this call is that86* all future <code>add</code> calls are ignored87* and the <code>intersects</code> method always88* returns true.89*/90public void addInfinite() {91mSpans = null;92}9394/**95* Returns true if the span defined by the half-open96* interval from <code>start</code> up to,97* but not including, <code>end</code> intersects98* any of the spans defined by this instance.99*/100public boolean intersects(float start, float end) {101boolean doesIntersect;102103if (mSpans != null) {104105/* If we have added any spans since we last106* sorted and collapsed our list of spans107* then we need to resort and collapse.108*/109if (mAddsSinceSort > 0) {110sortAndCollapse();111}112113/* The SpanIntersection comparator considers114* two spans equal if they intersect. If115* the search finds a match then we have an116* intersection.117*/118int found = Collections.binarySearch(mSpans,119new Span(start, end),120SpanIntersection.instance);121122doesIntersect = found >= 0;123124/* The addInfinite() method has been invoked so125* everything intersect this instance.126*/127} else {128doesIntersect = true;129}130131return doesIntersect;132}133134/**135* Sort the spans in ascending order by their136* start position. After the spans are sorted137* collapse any spans that intersect into a138* single span. The result is a sorted,139* non-overlapping list of spans.140*/141private void sortAndCollapse() {142143Collections.sort(mSpans);144mAddsSinceSort = 0;145146Iterator iter = mSpans.iterator();147148/* Have 'span' start at the first span in149* the collection. The collection may be empty150* so we're careful.151*/152Span span = null;153if (iter.hasNext()) {154span = (Span) iter.next();155}156157/* Loop over the spans collapsing those that intersect158* into a single span.159*/160while (iter.hasNext()) {161162Span nextSpan = (Span) iter.next();163164/* The spans are in ascending start position165* order and so the next span's starting point166* is either in the span we are trying to grow167* or it is beyond the first span and thus the168* two spans do not intersect.169*170* span: <----------<171* nextSpan: <------ (intersects)172* nextSpan: <------ (doesn't intersect)173*174* If the spans intersect then we'll remove175* nextSpan from the list. If nextSpan's176* ending was beyond the first's then177* we extend the first.178*179* span: <----------<180* nextSpan: <-----< (don't change span)181* nextSpan: <-----------< (grow span)182*/183184if (span.subsume(nextSpan)) {185iter.remove();186187/* The next span did not intersect the current188* span and so it can not be collapsed. Instead189* it becomes the start of the next set of spans190* to be collapsed.191*/192} else {193span = nextSpan;194}195}196}197198/*199// For debugging.200201private void printSpans() {202System.out.println("----------");203if (mSpans != null) {204Iterator iter = mSpans.iterator();205while (iter.hasNext()) {206Span span = (Span) iter.next();207System.out.println(span);208}209}210System.out.println("----------");211212}213*/214215/**216* Holds a single half-open interval.217*/218static class Span implements Comparable {219220/**221* The span includes the starting point.222*/223private float mStart;224225/**226* The span goes up to but does not include227* the ending point.228*/229private float mEnd;230231/**232* Create a half-open interval including233* <code>start</code> but not including234* <code>end</code>.235*/236Span(float start, float end) {237mStart = start;238mEnd = end;239}240241/**242* Return the start of the <code>Span</code>.243* The start is considered part of the244* half-open interval.245*/246final float getStart() {247return mStart;248}249250/**251* Return the end of the <code>Span</code>.252* The end is not considered part of the253* half-open interval.254*/255final float getEnd() {256return mEnd;257}258259/**260* Change the initial position of the261* <code>Span</code>.262*/263final void setStart(float start) {264mStart = start;265}266267/**268* Change the terminal position of the269* <code>Span</code>.270*/271final void setEnd(float end) {272mEnd = end;273}274275/**276* Attempt to alter this <code>Span</code>277* to include <code>otherSpan</code> without278* altering this span's starting position.279* If <code>otherSpan</code> can be so consumed280* by this <code>Span</code> then <code>true</code>281* is returned.282*/283boolean subsume(Span otherSpan) {284285/* We can only subsume 'otherSpan' if286* its starting position lies in our287* interval.288*/289boolean isSubsumed = contains(otherSpan.mStart);290291/* If the other span's starting position292* was in our interval and the other span293* was longer than this span, then we need294* to grow this span to cover the difference.295*/296if (isSubsumed && otherSpan.mEnd > mEnd) {297mEnd = otherSpan.mEnd;298}299300return isSubsumed;301}302303/**304* Return true if the passed in position305* lies in the half-open interval defined306* by this <code>Span</code>.307*/308boolean contains(float pos) {309return mStart <= pos && pos < mEnd;310}311312/**313* Rank spans according to their starting314* position. The end position is ignored315* in this ranking.316*/317public int compareTo(Object o) {318Span otherSpan = (Span) o;319float otherStart = otherSpan.getStart();320int result;321322if (mStart < otherStart) {323result = -1;324} else if (mStart > otherStart) {325result = 1;326} else {327result = 0;328}329330return result;331}332333public String toString() {334return "Span: " + mStart + " to " + mEnd;335}336337}338339/**340* This class ranks a pair of <code>Span</code>341* instances. If the instances intersect they342* are deemed equal otherwise they are ranked343* by their relative position. Use344* <code>SpanIntersection.instance</code> to345* get the single instance of this class.346*/347static class SpanIntersection implements Comparator {348349/**350* This class is a Singleton and the following351* is the single instance.352*/353static final SpanIntersection instance =354new SpanIntersection();355356/**357* Only this class can create instances of itself.358*/359private SpanIntersection() {360361}362363public int compare(Object o1, Object o2) {364int result;365Span span1 = (Span) o1;366Span span2 = (Span) o2;367368/* Span 1 is entirely to the left of span2.369* span1: <-----<370* span2: <-----<371*/372if (span1.getEnd() <= span2.getStart()) {373result = -1;374375/* Span 2 is entirely to the right of span2.376* span1: <-----<377* span2: <-----<378*/379} else if (span1.getStart() >= span2.getEnd()) {380result = 1;381382/* Otherwise they intersect and we declare them equal.383*/384} else {385result = 0;386}387388return result;389}390391}392}393394395