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