
libjava/ 2008-06-28 Matthias Klose <doko@ubuntu.com> Import GNU Classpath (classpath-0_97_2-release). * Regenerate class and header files. * Regenerate auto* files. * gcj/javaprims.h: Define jobjectRefType. * jni.cc (_Jv_JNI_GetObjectRefType): New (stub only). (_Jv_JNIFunctions): Initialize GetObjectRefType. * gnu/classpath/jdwp/VMVirtualMachine.java, java/security/VMSecureRandom.java: Merge from classpath. * HACKING: Fix typo. * ChangeLog-2007: New file. * configure.ac: Set JAVAC, pass --disable-regen-headers to classpath. libjava/classpath/ 2008-06-28 Matthias Klose <doko@ubuntu.com> * m4/ac_prog_javac.m4: Disable check for JAVAC, when not configured with --enable-java-maintainer-mode. * aclocal.m4, configure: Regenerate. * native/jni/gstreamer-peer/Makefile.am: Do not link with libclasspathnative. * native/jni/gstreamer-peer/Makefile.in: Regenerate. * tools/Makefile.am, lib/Makefile.am: Use JAVAC for setting JCOMPILER, drop flags not understood by gcj. From-SVN: r137223
630 lines
16 KiB
Java
630 lines
16 KiB
Java
/* ScanlineCoverage.java -- Manages coverage information for a scanline
|
|
Copyright (C) 2007 Free Software Foundation, Inc.
|
|
|
|
This file is part of GNU Classpath.
|
|
|
|
GNU Classpath is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
any later version.
|
|
|
|
GNU Classpath 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 for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GNU Classpath; see the file COPYING. If not, write to the
|
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
02110-1301 USA.
|
|
|
|
Linking this library statically or dynamically with other modules is
|
|
making a combined work based on this library. Thus, the terms and
|
|
conditions of the GNU General Public License cover the whole
|
|
combination.
|
|
|
|
As a special exception, the copyright holders of this library give you
|
|
permission to link this library with independent modules to produce an
|
|
executable, regardless of the license terms of these independent
|
|
modules, and to copy and distribute the resulting executable under
|
|
terms of your choice, provided that you also meet, for each linked
|
|
independent module, the terms and conditions of the license of that
|
|
module. An independent module is a module which is not derived from
|
|
or based on this library. If you modify this library, you may extend
|
|
this exception to your version of the library, but you are not
|
|
obligated to do so. If you do not wish to do so, delete this
|
|
exception statement from your version. */
|
|
|
|
package gnu.java.awt.java2d;
|
|
|
|
/**
|
|
* Stores and handles the pixel converage for a scanline. The pixel coverage
|
|
* is stored as sorted list of {@linke Covergage} entries, each of which holds
|
|
* information about the coverage for the X and Y axis. This is utilized to
|
|
* compute the actual coverage for each pixel on the scanline and finding
|
|
* chunks of pixels with equal coverage quickly.
|
|
*/
|
|
public final class ScanlineCoverage
|
|
{
|
|
|
|
/**
|
|
* Iterates over the coverage list and calculates the actual coverage
|
|
* ranges on a scanline.
|
|
*/
|
|
public final class Iterator
|
|
{
|
|
/**
|
|
* This instance is reused in the iteration.
|
|
*/
|
|
private Range range;
|
|
|
|
/**
|
|
* The pointer to the current item in the iteration.
|
|
*/
|
|
private Coverage currentItem;
|
|
|
|
/**
|
|
* The current coverage value.
|
|
*/
|
|
private int currentCoverage;
|
|
|
|
/**
|
|
* True when the current pixel coverage has already been handled, false
|
|
* otherwise.
|
|
*/
|
|
private boolean handledPixelCoverage;
|
|
|
|
/**
|
|
* Creates a new CoverageIterator.
|
|
*/
|
|
Iterator()
|
|
{
|
|
range = new Range();
|
|
}
|
|
|
|
/**
|
|
* Returns the next coverage range on the scanline. The returned object
|
|
* will always be the same object, but with different values. Keep that
|
|
* in mind when dealing with this object.
|
|
*
|
|
* @return the next coverage range on the scanline
|
|
*/
|
|
public Range next()
|
|
{
|
|
// TODO: Lump together the single-pixel coverage and the
|
|
// between-pixel coverage when the pixel coverage delta is 0.
|
|
if (handledPixelCoverage == false)
|
|
{
|
|
// Handle single pixel coverage.
|
|
range.setXPos(currentItem.xPos);
|
|
range.setLength(1);
|
|
range.setCoverage(currentCoverage + currentItem.pixelCoverage);
|
|
handledPixelCoverage = true;
|
|
}
|
|
else
|
|
{
|
|
// Handle pixel span coverage.
|
|
currentCoverage += currentItem.covDelta;
|
|
range.setCoverage(currentCoverage);
|
|
range.setXPos(currentItem.xPos + 1);
|
|
currentItem = currentItem.next;
|
|
range.setLength(currentItem.xPos - range.xPos);
|
|
handledPixelCoverage = false;
|
|
}
|
|
return range;
|
|
}
|
|
|
|
/**
|
|
* Returns {@ true} when there are more coverage ranges to iterate,
|
|
* {@ false} otherwise.
|
|
*
|
|
* @return {@ true} when there are more coverage ranges to iterate,
|
|
* {@ false} otherwise
|
|
*/
|
|
public boolean hasNext()
|
|
{
|
|
boolean hasNext;
|
|
if (currentItem != null && handledPixelCoverage == false)
|
|
{
|
|
// We have at least one more coverage item when there's a pixel
|
|
// coverage piece left.
|
|
hasNext = true;
|
|
}
|
|
else if (currentItem == null || currentItem.next == null
|
|
|| currentItem.next == last)
|
|
{
|
|
hasNext = false;
|
|
}
|
|
else
|
|
{
|
|
hasNext = true;
|
|
}
|
|
return hasNext;
|
|
}
|
|
|
|
/**
|
|
* Resets this iterator to the start of the list.
|
|
*/
|
|
void reset()
|
|
{
|
|
currentItem = head;
|
|
currentCoverage = 0;
|
|
handledPixelCoverage = false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A data object that carries information about pixel coverage on a scanline.
|
|
* The data consists of a starting X position on the scanline, the
|
|
* length of the range in pixels and the actual coverage value.
|
|
**/
|
|
public static final class Range
|
|
{
|
|
/**
|
|
* The X position on the scanline, in pixels.
|
|
*/
|
|
private int xPos;
|
|
|
|
/**
|
|
* The length of the range, in pixels.
|
|
*/
|
|
private int length;
|
|
|
|
/**
|
|
* The actual coverage. The relation depends on
|
|
* {@link ScanlineCoverage#maxCoverage}.
|
|
*/
|
|
private int coverage;
|
|
|
|
/**
|
|
* Creates a new CoverageRange object.
|
|
*/
|
|
Range()
|
|
{
|
|
// Nothing to do. The values get initialized in the corresponding
|
|
// setters.
|
|
}
|
|
|
|
/**
|
|
* Sets the X start position (left) on the scanline. This value is
|
|
* considered to be in pixels and device space.
|
|
*
|
|
* @param x the x position
|
|
*/
|
|
void setXPos(int x)
|
|
{
|
|
xPos = x;
|
|
}
|
|
|
|
/**
|
|
* Returns the X start position (left) on the scanline. This value
|
|
* is considered to be in pixels and device space.
|
|
*
|
|
* @return the X position on the scanline
|
|
*/
|
|
public int getXPos()
|
|
{
|
|
return xPos;
|
|
}
|
|
|
|
/**
|
|
* Sets the length of the pixel range. This is in pixel units.
|
|
*
|
|
* @param l the length of the range
|
|
*/
|
|
void setLength(int l)
|
|
{
|
|
length = l;
|
|
}
|
|
|
|
/**
|
|
* Returns the length of the range in pixel units.
|
|
*
|
|
* @return the length of the range in pixel units
|
|
*/
|
|
public int getLength()
|
|
{
|
|
return length;
|
|
}
|
|
|
|
/**
|
|
* Returns the first X position after the range.
|
|
*
|
|
* @return the first X position after the range
|
|
*/
|
|
public int getXPosEnd()
|
|
{
|
|
return xPos + length;
|
|
}
|
|
|
|
/**
|
|
* Sets the coverage of the pixel range. The relation of that value
|
|
* depends on {@link ScanlineCoverage#maxCoverage}.
|
|
*
|
|
* @param cov the coverage value for the pixel range
|
|
*/
|
|
void setCoverage(int cov)
|
|
{
|
|
coverage = cov;
|
|
}
|
|
|
|
/**
|
|
* Returns the coverage of the pixel range. The relation of this value
|
|
* depends on {@link ScanlineCoverage#getMaxCoverage()}.
|
|
*
|
|
* @return the coverage of the pixel range
|
|
*/
|
|
public int getCoverage()
|
|
{
|
|
return coverage;
|
|
}
|
|
|
|
/**
|
|
* Returns a string representation.
|
|
*/
|
|
public String toString()
|
|
{
|
|
return "Coverage range: xPos=" + xPos + ", length=" + length
|
|
+ ", coverage: " + coverage;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* One bucket in the list.
|
|
*/
|
|
private static final class Coverage
|
|
{
|
|
/**
|
|
* The X coordinate on the scanline to which this bucket belongs.
|
|
*/
|
|
int xPos;
|
|
|
|
/**
|
|
* The coverage delta from the pixel at xPos to xPos + 1.
|
|
*/
|
|
int covDelta;
|
|
|
|
/**
|
|
* The delta for the pixel at xPos. This is added to the pixel at xPos,
|
|
* but not to the following pixel.
|
|
*/
|
|
int pixelCoverage;
|
|
|
|
/**
|
|
* Implements a linked list. This points to the next element of the list.
|
|
*/
|
|
Coverage next;
|
|
|
|
/**
|
|
* Returns the X coordinate for this entry.
|
|
*
|
|
* @return the X coordinate for this entry
|
|
*/
|
|
public int getXPos()
|
|
{
|
|
return xPos;
|
|
}
|
|
|
|
/**
|
|
* Returns the coverage delta for this entry.
|
|
*
|
|
* @return the coverage delta for this entry
|
|
*/
|
|
public int getCoverageDelta()
|
|
{
|
|
return covDelta;
|
|
}
|
|
|
|
/**
|
|
* Returns a string representation.
|
|
*
|
|
* @return a string representation
|
|
*/
|
|
public String toString()
|
|
{
|
|
return "Coverage: xPos: " + xPos + ", covDelta: " + covDelta;
|
|
}
|
|
|
|
/**
|
|
* Returns a string representation of this entry and all the following
|
|
* in the linked list.
|
|
*
|
|
* @return a string representation of this entry and all the following
|
|
* in the linked list
|
|
*/
|
|
public String list()
|
|
{
|
|
String str = toString();
|
|
if (next != null)
|
|
str = str + " --> " + next.list();
|
|
return str;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The head of the sorted list of buckets.
|
|
*/
|
|
private Coverage head;
|
|
|
|
/**
|
|
* The current bucket. We make use of the fact that the scanline converter
|
|
* always scans the scanline (and thus this list) from left to right to
|
|
* quickly find buckets or insertion points.
|
|
*/
|
|
private Coverage current;
|
|
|
|
/**
|
|
* The item that is before current in the list.
|
|
*/
|
|
private Coverage currentPrev;
|
|
|
|
/**
|
|
* The bucket after the last valid bucket. Unused buckets are not thrown
|
|
* away and garbage collected. Instead, we keep them at the tail of the list
|
|
* and reuse them when necessary.
|
|
*/
|
|
private Coverage last;
|
|
|
|
/**
|
|
* The last valid entry.
|
|
*/
|
|
private Coverage lastPrev;
|
|
|
|
/**
|
|
* The minimum X coordinate of this scanline.
|
|
*/
|
|
private int minX;
|
|
|
|
/**
|
|
* The maximum X coordinate of this scanline.
|
|
*/
|
|
private int maxX;
|
|
|
|
/**
|
|
* The maximum coverage value.
|
|
*/
|
|
private int maxCoverage;
|
|
|
|
/**
|
|
* The iterator over the ranges of this scanline.
|
|
*/
|
|
private Iterator iterator;
|
|
|
|
/**
|
|
* Creates a new ScanlineCoverage instance.
|
|
*/
|
|
public ScanlineCoverage()
|
|
{
|
|
iterator = new Iterator();
|
|
}
|
|
|
|
/**
|
|
* Indicates the the next scan of the scanline begins and that the next
|
|
* request will be at the beginning of this list. This makes searching and
|
|
* sorting of this list very quick.
|
|
*/
|
|
public void rewind()
|
|
{
|
|
current = head;
|
|
currentPrev = null;
|
|
}
|
|
|
|
/**
|
|
* Clears the list. This does not throw away the old buckets but only
|
|
* resets the end-pointer of the list to the first element. All buckets are
|
|
* then unused and are reused when the list is filled again.
|
|
*/
|
|
public void clear()
|
|
{
|
|
last = head;
|
|
lastPrev = null;
|
|
current = head;
|
|
currentPrev = null;
|
|
minX = Integer.MAX_VALUE;
|
|
maxX = Integer.MIN_VALUE;
|
|
}
|
|
|
|
/**
|
|
* This adds the specified coverage to the pixel at the specified
|
|
* X position.
|
|
*
|
|
* @param x the X position
|
|
* @param xc the x coverage
|
|
* @param yc the y coverage
|
|
*/
|
|
public void add(int x, int xc, int yc)
|
|
{
|
|
Coverage bucket = findOrInsert(x);
|
|
bucket.covDelta += xc;
|
|
bucket.pixelCoverage += yc;
|
|
minX = Math.min(minX, x);
|
|
maxX = Math.max(maxX, x);
|
|
}
|
|
|
|
/**
|
|
* Returns the maximum coverage value for the scanline.
|
|
*
|
|
* @return the maximum coverage value for the scanline
|
|
*/
|
|
public int getMaxCoverage()
|
|
{
|
|
return maxCoverage;
|
|
}
|
|
|
|
/**
|
|
* Sets the maximum coverage value for the scanline.
|
|
*
|
|
* @param maxCov the maximum coverage value for the scanline
|
|
*/
|
|
void setMaxCoverage(int maxCov)
|
|
{
|
|
maxCoverage = maxCov;
|
|
}
|
|
|
|
/**
|
|
* Returns the maximum X coordinate of the current scanline.
|
|
*
|
|
* @return the maximum X coordinate of the current scanline
|
|
*/
|
|
public int getMaxX()
|
|
{
|
|
return maxX;
|
|
}
|
|
|
|
/**
|
|
* Returns the minimum X coordinate of the current scanline.
|
|
*
|
|
* @return the minimum X coordinate of the current scanline
|
|
*/
|
|
public int getMinX()
|
|
{
|
|
return minX;
|
|
}
|
|
|
|
/**
|
|
* Finds the bucket in the list with the specified X coordinate.
|
|
* If no such bucket is found, then a new one is fetched (either a cached
|
|
* bucket from the end of the list or a newly allocated one) inserted at the
|
|
* correct position and returned.
|
|
*
|
|
* @param x the X coordinate
|
|
*
|
|
* @return a bucket to hold the coverage data
|
|
*/
|
|
private Coverage findOrInsert(int x)
|
|
{
|
|
// First search for a matching bucket.
|
|
if (head == null)
|
|
{
|
|
// Special case: the list is still empty.
|
|
// Testpoint 1.
|
|
head = new Coverage();
|
|
head.xPos = x;
|
|
current = head;
|
|
currentPrev = null;
|
|
return head;
|
|
}
|
|
|
|
// This performs a linear search, starting from the current bucket.
|
|
// This is reasonably efficient because access to this list is always done
|
|
// in a linear fashion and we are usually not more then 1 or 2 buckets away
|
|
// from the one we're looking for.
|
|
Coverage match = current;
|
|
Coverage prev = currentPrev;
|
|
while (match != last && match.xPos < x)
|
|
{
|
|
prev = match;
|
|
match = match.next;
|
|
}
|
|
|
|
// At this point we have either found an entry with xPos >= x, or reached
|
|
// the end of the list (match == last || match == null).
|
|
if (match == null)
|
|
{
|
|
// End of the list. No cached items to reuse.
|
|
// Testpoint 2.
|
|
match = new Coverage();
|
|
match.xPos = x;
|
|
if (prev != null)
|
|
prev.next = match;
|
|
current = match;
|
|
currentPrev = prev;
|
|
return match;
|
|
}
|
|
else if (match == last)
|
|
{
|
|
// End of the list. Reuse this item. Expand list.
|
|
// Testpoint 3.
|
|
last = match.next;
|
|
lastPrev = match;
|
|
match.xPos = x;
|
|
match.covDelta = 0;
|
|
match.pixelCoverage = 0;
|
|
// Keep link to last element or null, indicating the end of the list.
|
|
current = match;
|
|
currentPrev = prev;
|
|
return match;
|
|
}
|
|
|
|
if (x == match.xPos)
|
|
{
|
|
// Special case: We have another coverage entry at the same location
|
|
// as an already existing entry. Return this.
|
|
// Testpoint 4.
|
|
current = match;
|
|
currentPrev = prev;
|
|
return match;
|
|
}
|
|
else // x <= match.xPos
|
|
{
|
|
assert (x <= match.xPos);
|
|
assert (prev == null ||x > prev.xPos);
|
|
|
|
// Create new entry, or reuse existing one.
|
|
Coverage cov;
|
|
if (last != null)
|
|
{
|
|
// Testpoint 5.
|
|
cov = last;
|
|
last = cov.next;
|
|
lastPrev.next = last;
|
|
}
|
|
else
|
|
{
|
|
// Testpoint 6.
|
|
cov = new Coverage();
|
|
}
|
|
|
|
cov.xPos = x;
|
|
cov.covDelta = 0;
|
|
cov.pixelCoverage = 0;
|
|
|
|
// Insert this item in the list.
|
|
if (prev != null)
|
|
{
|
|
// Testpoint 5 & 6.
|
|
prev.next = cov;
|
|
cov.next = match;
|
|
current = cov;
|
|
currentPrev = prev;
|
|
}
|
|
else
|
|
{
|
|
// Testpoint 7.
|
|
assert (match == head);
|
|
// Insert at head.
|
|
head = cov;
|
|
head.next = match;
|
|
current = head;
|
|
currentPrev = null;
|
|
}
|
|
return cov;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* (Re-)Starts iterating the coverage values for the scanline.
|
|
* Use the returned iterator to get the consecutive coverage ranges.
|
|
*
|
|
* @return the iterator
|
|
*/
|
|
public Iterator iterate()
|
|
{
|
|
iterator.reset();
|
|
return iterator;
|
|
}
|
|
|
|
/**
|
|
* Returns {@ true} if this object has no entries for the current scanline,
|
|
* {@ false} otherwise.
|
|
*
|
|
* @return {@ true} if this object has no entries for the current scanline,
|
|
* {@ false} otherwise
|
|
*/
|
|
public boolean isEmpty()
|
|
{
|
|
return head == null || head == last
|
|
|| head.next == null || head.next == last;
|
|
}
|
|
|
|
}
|