package gnu.java.awt.java2d;
/**
* Stores and handles the pixel converage for a scanline. The pixel coverage
* is stored as sorted list of buckets, 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.
*/
final class PixelCoverage
{
/**
* One bucket in the list.
*/
private static final class Bucket
{
/**
* The X coordinate on the scanline to which this bucket belongs.
*/
int xPos;
/**
* The X coverage.
*/
int xCov;
/**
* The Y coverage.
*/
int yCov;
/**
* Implements a linked list. This points to the next element of the list.
*/
Bucket next;
/**
* Implements a linked list. This points to the previous element of the
* list.
*/
Bucket prev;
}
/**
* The head of the sorted list of buckets.
*/
private Bucket 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 Bucket current;
/**
* 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 Bucket last;
/**
* 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.
*/
void rewind()
{
current = head;
}
/**
* 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.
*/
void clear()
{
last = head;
}
/**
* This adds the specified x and y coverage to the pixel at the specified
* X position.
*
* @param x the X position
* @param xc the x coverage
* @param yc the y coverage
*/
void add(int x, int xc, int yc)
{
Bucket bucket = findOrInsert(x);
bucket.xCov += xc;
bucket.yCov += yc;
}
/**
* 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 Bucket findOrInsert(int x)
{
// First search for a matching bucket.
if (head == null)
{
// Special case: the list is still empty.
head = new Bucket();
current = head;
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 not more then 1 or 2 buckets away from
// the one we're looking for.
Bucket match = current;
while (match != null && match.xPos != x)
{
}
return match;
}
}