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; } }