/*
* Copyright (c) 1999, 2002, 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.java2d.pipe;
/**
* This class implements the ShapeIterator interface for a Region.
* This is useful as the source iterator of a device clip region
* (in its native guise), and also as the result of clipping a
* Region to a rectangle.
*/
public class RegionSpanIterator implements SpanIterator {
// The RegionIterator that we use to do the work
RegionIterator ri;
// Clipping bounds
int lox, loy, hix, hiy;
// Current Y band limits
int curloy, curhiy;
// Are we done?
boolean done = false;
// Is the associated Region rectangular?
boolean isrect;
/*
REMIND: For native implementation
long pData; // Private storage of rect info
static {
initIDs();
}
public static native void initIDs();
*/
/**
* Constructs an instance based on the given Region
*/
public RegionSpanIterator(Region r) {
int[] bounds = new int[4];
r.getBounds(bounds);
lox = bounds[0];
loy = bounds[1];
hix = bounds[2];
hiy = bounds[3];
isrect = r.isRectangular();
ri = r.getIterator();
}
/**
* Gets the bbox of the available region spans.
*/
public void getPathBox(int pathbox[]) {
pathbox[0] = lox;
pathbox[1] = loy;
pathbox[2] = hix;
pathbox[3] = hiy;
}
/**
* Intersect the box used for clipping the output spans with the
* given box.
*/
public void intersectClipBox(int clox, int cloy, int chix, int chiy) {
if (clox > lox) {
lox = clox;
}
if (cloy > loy) {
loy = cloy;
}
if (chix < hix) {
hix = chix;
}
if (chiy < hiy) {
hiy = chiy;
}
done = lox >= hix || loy >= hiy;
}
/**
* Fetches the next span that needs to be operated on.
* If the return value is false then there are no more spans.
*/
public boolean nextSpan(int spanbox[]) {
// Quick test for end conditions
if (done) {
return false;
}
// If the Region is rectangular, we store our bounds (possibly
// clipped via intersectClipBox()) in spanbox and return true
// so that the caller will process the single span. We set done
// to true to ensure that this will be the last span processed.
if (isrect) {
getPathBox(spanbox);
done = true;
return true;
}
// Local cache of current span's bounds
int curlox, curhix;
int curloy = this.curloy;
int curhiy = this.curhiy;
while (true) {
if (!ri.nextXBand(spanbox)) {
if (!ri.nextYRange(spanbox)) {
done = true;
return false;
}
// Update the current y band and clip it
curloy = spanbox[1];
curhiy = spanbox[3];
if (curloy < loy) {
curloy = loy;
}
if (curhiy > hiy) {
curhiy = hiy;
}
// Check for moving below the clip rect
if (curloy >= hiy) {
done = true;
return false;
}
continue;
}
// Clip the x box
curlox = spanbox[0];
curhix = spanbox[2];
if (curlox < lox) {
curlox = lox;
}
if (curhix > hix) {
curhix = hix;
}
// If it's non- box, we're done
if (curlox < curhix && curloy < curhiy) {
break;
}
}
// Update the result and the store y range
spanbox[0] = curlox;
spanbox[1] = this.curloy = curloy;
spanbox[2] = curhix;
spanbox[3] = this.curhiy = curhiy;
return true;
}
/**
* This method tells the iterator that it may skip all spans
* whose Y range is completely above the indicated Y coordinate.
*/
public void skipDownTo(int y) {
loy = y;
}
/**
* This method returns a native pointer to a function block that
* can be used by a native method to perform the same iteration
* cycle that the above methods provide while avoiding upcalls to
* the Java object.
* The definition of the structure whose pointer is returned by
* this method is defined in:
* <pre>
* src/share/native/sun/java2d/pipe/SpanIterator.h
* </pre>
*/
public long getNativeIterator() {
return 0;
}
/*
* Cleans out all internal data structures.
* REMIND: Native implementation
public native void dispose();
protected void finalize() {
dispose();
}
*/
}