/* |
|
* 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(); |
|
} |
|
*/ |
|
} |