This adds some infrastructure to the rasterizer, this is needed for the
upcoming quality improvements, but does not improve the rendering for
itself.
2007-05-24 Roman Kennke <[EMAIL PROTECTED]>
* gnu/java/awt/java2d/ScanlineCoverage.java
(Iterator): New class.
(Range): New class.
(Coverage.covDelta): Made field package private.
(Coverage.xPos): Made field package private.
(iterator): New field. Stores the iterator that is reused.
(ScanlineCoverage): Initialize iterator.
(assertion): Removed.
(isEmpty): Refined conditions.
(iterate): Return Iterator instance.
(next): Removed. This is done by the Iterator class now.
(test): Removed.
* gnu/java/awt/java2d/ScanlineConverter.java
(main): Removed.
* gnu/java/awt/peer/x/XGraphics2D.java
(renderScanline): Adjust to new coverage iterator stuff.
* gnu/java/awt/java2d/AbstractGraphics2D.java
(renderScanline): Adjust to new coverage iterator stuff.
/Roman
--
Dipl.-Inf. Roman Kennke, Software Engineer, http://kennke.org
aicas Allerton Interworks Computer Automated Systems GmbH
Haid-und-Neu-Straße 18 * D-76131 Karlsruhe * Germany
http://www.aicas.com * Tel: +49-721-663 968-0
USt-Id: DE216375633, Handelsregister HRB 109481, AG Karlsruhe
Geschäftsführer: Dr. James J. Hunt
Index: gnu/java/awt/peer/x/XGraphics2D.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/x/XGraphics2D.java,v
retrieving revision 1.3
diff -u -1 -5 -r1.3 XGraphics2D.java
--- gnu/java/awt/peer/x/XGraphics2D.java 22 May 2007 13:12:56 -0000 1.3
+++ gnu/java/awt/peer/x/XGraphics2D.java 24 May 2007 16:26:25 -0000
@@ -207,64 +207,60 @@
//System.err.println("tx: " + tx + ", ty: " + ty + ", pixel: " + pixel[0] + ", " + pixel[1] + ", " + pixel[2]);
// System.err.print("r: " + pixel[0]);
// System.err.print(", g: " + pixel[1]);
// System.err.println(", b: " + pixel[2]);
zPixmap.set_red(tx - x, ty - y, pixel[0]);
zPixmap.set_green(tx - x, ty - y, pixel[1]);
zPixmap.set_blue(tx - x, ty - y, pixel[2]);
}
}
xdrawable.put_image(xgc, zPixmap, x, y);
}
}
public void renderScanline(int y, ScanlineCoverage c)
{
- ScanlineCoverage.Coverage start = c.iterate();
- ScanlineCoverage.Coverage end = c.next();
- assert (start != null);
- assert (end != null);
- int coverageAlpha = 0;
+ ScanlineCoverage.Iterator iter = c.iterate();
+ float coverageAlpha = 0;
int maxCoverage = c.getMaxCoverage();
Color old = getColor();
Color col = getColor();
if (col == null)
col = Color.BLACK;
- do
+ while (iter.hasNext())
{
+ ScanlineCoverage.Range range = iter.next();
// TODO: Dumb implementation for testing.
- coverageAlpha = coverageAlpha + start.getCoverageDelta();
+ coverageAlpha = range.getCoverage();
if (coverageAlpha > 0)
{
int red = col.getRed();
int green = col.getGreen();
int blue = col.getBlue();
if (coverageAlpha < c.getMaxCoverage())
{
float alpha = coverageAlpha / maxCoverage;
red = 255 - (int) ((255 - red) * alpha);
green = 255 - (int) ((255 - green) * alpha);
blue = 255 - (int) ((255 - blue) * alpha);
}
xgc.set_foreground(red << 16 | green << 8 | blue);
- int x0 = start.getXPos();
- int x1 = end.getXPos();
- xdrawable.fill_rectangle(xgc, x0, y, x1 - x0, 1);
+ int x0 = range.getXPos();
+ int l = range.getLength();
+ xdrawable.fill_rectangle(xgc, x0, y, l, 1);
}
- start = end;
- end = c.next();
- } while (end != null);
+ }
xgc.set_foreground(old.getRGB());
}
protected void fillScanline(int x0, int x1, int y)
{
xdrawable.segment(xgc, x0, y, x1, y);
}
protected void fillScanlineAA(int x0, int x1, int y, int alpha)
{
//System.err.println("fillScanlineAA: " + x0 + ", " + x1 + ", " + y + ", " + alpha);
// FIXME: This is for testing only.
Color c = getColor();
setColor(new Color(255-alpha, 255-alpha, 255-alpha));
xdrawable.segment(xgc, x0, y, x1, y);
Index: gnu/java/awt/java2d/AbstractGraphics2D.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java,v
retrieving revision 1.16
diff -u -1 -5 -r1.16 AbstractGraphics2D.java
--- gnu/java/awt/java2d/AbstractGraphics2D.java 18 May 2007 16:22:40 -0000 1.16
+++ gnu/java/awt/java2d/AbstractGraphics2D.java 24 May 2007 16:26:26 -0000
@@ -1549,31 +1549,30 @@
{
// Determine if we need to antialias stuff.
boolean antialias = false;
if (isFont)
{
Object v = renderingHints.get(RenderingHints.KEY_TEXT_ANTIALIASING);
// We default to antialiasing for text rendering.
antialias = (v == RenderingHints.VALUE_TEXT_ANTIALIAS_ON
|| v == RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
}
else
{
Object v = renderingHints.get(RenderingHints.KEY_ANTIALIASING);
antialias = (v == RenderingHints.VALUE_ANTIALIAS_ON);
}
-
ScanlineConverter sc = getScanlineConverter();
int resolution = 0;
if (antialias)
{
// Adjust resolution according to rendering hints.
resolution = 2;
}
sc.renderShape(this, s, clip, transform, resolution);
}
/**
* Returns the color model of this Graphics object.
*
* @return the color model of this Graphics object
*/
@@ -1727,49 +1726,45 @@
PaintContext pCtx = paintContext;
int x0 = c.getMinX();
int x1 = c.getMaxX();
Raster paintRaster = pCtx.getRaster(x0, y, x1 - x0, 1);
// Do the anti aliasing thing.
float coverageAlpha = 0;
float maxCoverage = c.getMaxCoverage();
ColorModel cm = pCtx.getColorModel();
DataBuffer db = paintRaster.getDataBuffer();
Point loc = new Point(paintRaster.getMinX(), paintRaster.getMinY());
SampleModel sm = paintRaster.getSampleModel();
WritableRaster writeRaster = Raster.createWritableRaster(sm, db, loc);
WritableRaster alphaRaster = cm.getAlphaRaster(writeRaster);
int pixel;
- ScanlineCoverage.Coverage start = c.iterate();
- ScanlineCoverage.Coverage end = c.next();
- assert (start != null);
- assert (end != null);
- do
+ ScanlineCoverage.Iterator iter = c.iterate();
+ while (iter.hasNext())
{
- coverageAlpha = coverageAlpha + (start.getCoverageDelta() / maxCoverage);
+ ScanlineCoverage.Range range = iter.next();
+ coverageAlpha = range.getCoverage() / maxCoverage;
if (coverageAlpha < 1.0)
{
- for (int x = start.getXPos(); x < end.getXPos(); x++)
+ for (int x = range.getXPos(); x < range.getXPosEnd(); x++)
{
pixel = alphaRaster.getSample(x, y, 0);
pixel = (int) (pixel * coverageAlpha);
alphaRaster.setSample(x, y, 0, pixel);
}
}
- start = end;
- end = c.next();
- } while (end != null);
+ }
ColorModel paintColorModel = pCtx.getColorModel();
CompositeContext cCtx = composite.createContext(paintColorModel,
getColorModel(),
renderingHints);
WritableRaster targetChild = destinationRaster.createWritableTranslatedChild(-x0,- y);
cCtx.compose(paintRaster, targetChild, targetChild);
updateRaster(destinationRaster, x0, y, x1 - x0, 1);
cCtx.dispose();
}
/**
* Initializes this graphics object. This must be called by subclasses in
* order to correctly initialize the state of this object.
*/
Index: gnu/java/awt/java2d/ScanlineConverter.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/java2d/ScanlineConverter.java,v
retrieving revision 1.3
diff -u -1 -5 -r1.3 ScanlineConverter.java
--- gnu/java/awt/java2d/ScanlineConverter.java 18 May 2007 16:22:40 -0000 1.3
+++ gnu/java/awt/java2d/ScanlineConverter.java 24 May 2007 16:26:26 -0000
@@ -412,26 +412,16 @@
}
private void edgePoolAdd(int x0, int y0, int x1, int y1, boolean clip)
{
// Don't need no horizontal edges.
if (y0 != y1)
{
edgePoolLast.init(FIXED_DIGITS, x0, y0, x1, y1, clip);
if (edgePoolLast.poolNext == null)
{
edgePoolLast.poolNext = new PolyEdge();
}
edgePoolLast = edgePoolLast.poolNext;
}
}
-
- /**
- * Performs some tests.
- *
- * @param args
- */
- public static void main(String[] args)
- {
- ScanlineCoverage.test();
- }
}
Index: gnu/java/awt/java2d/ScanlineCoverage.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/java2d/ScanlineCoverage.java,v
retrieving revision 1.1
diff -u -1 -5 -r1.1 ScanlineCoverage.java
--- gnu/java/awt/java2d/ScanlineCoverage.java 18 May 2007 16:22:40 -0000 1.1
+++ gnu/java/awt/java2d/ScanlineCoverage.java 24 May 2007 16:26:26 -0000
@@ -36,43 +36,224 @@
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 [EMAIL PROTECTED] 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;
+
+ /**
+ * 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()
+ {
+ currentCoverage += currentItem.covDelta;
+ range.setCoverage(currentCoverage);
+ range.setXPos(currentItem.xPos);
+ currentItem = currentItem.next;
+ range.setLength(currentItem.xPos - range.xPos);
+ 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 || 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;
+ }
+ }
+
+ /**
+ * 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
+ * [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] ScanlineCoverage#getMaxCoverage()}.
+ *
+ * @return the coverage of the pixel range
+ */
+ public int getCoverage()
+ {
+ return coverage;
+ }
+ }
+
+ /**
* One bucket in the list.
*/
- public static final class Coverage
+ private static final class Coverage
{
/**
* The X coordinate on the scanline to which this bucket belongs.
*/
- private int xPos;
+ int xPos;
/**
* The X coverage delta.
*/
- private int covDelta;
+ int covDelta;
/**
* 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;
}
@@ -146,30 +327,43 @@
* 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.
*/
@@ -347,168 +541,40 @@
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 entries by returning the first Coverage
- * item in the list. Pixels left to that entry have a zero coverage.
- *
- * @return the first coverage item
- */
- public Coverage iterate()
- {
- if (head == last)
- current = null;
- else
- current = head;
- currentPrev = null;
- return current;
- }
-
- /**
- * Returns the next coverage item in the list, according to the current
- * iteration state.
+ * (Re-)Starts iterating the coverage values for the scanline.
+ * Use the returned iterator to get the consecutive coverage ranges.
*
- * @return the next coverage item in the list or {@ null} if the end has
- * been reached
+ * @return the iterator
*/
- public Coverage next()
+ public Iterator iterate()
{
- currentPrev = current;
- if (current == null || current.next == last)
- current = null;
- else
- current = current.next;
- return current;
+ 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;
- }
-
- /**
- * Performs some tests to check if this class is working correctly.
- * There are comments about a bunch of test points in this method, which
- * correspond to other points in this class as commented.
- */
- static void test()
- {
- System.out.println("ScanlineCoverage test 1");
- // Test testpoint 1 & 2.
- ScanlineCoverage c = new ScanlineCoverage();
- c.add(2, 3);
- c.add(3, 4);
- c.add(4, 5);
-
- Coverage cov = c.iterate();
- assertion(cov.xPos == 2);
- assertion(cov.covDelta == 3);
- cov = c.next();
- assertion(cov.xPos == 3);
- assertion(cov.covDelta == 4);
- cov = c.next();
- assertion(cov.xPos == 4);
- assertion(cov.covDelta == 5);
- assertion(c.next() == null);
-
- System.out.println("ScanlineCoverage test 2");
- // Test testpoint 3 and 4.
- c.clear();
- c.add(5, 4);
- c.add(7, 5);
- c.add(7, 10);
- cov = c.iterate();
- assertion(cov.xPos == 5);
- assertion(cov.covDelta == 4);
- cov = c.next();
- assertion(cov.xPos == 7);
- assertion(cov.covDelta == 15);
- assertion(c.next() == null);
-
- System.out.println("ScanlineCoverage test 3");
- // Test testpoint 5.
- c.rewind();
- c.add(6, 20);
- cov = c.iterate();
- assertion(cov.xPos == 5);
- assertion(cov.covDelta == 4);
- cov = c.next();
- assertion(cov.xPos == 6);
- assertion(cov.covDelta == 20);
- cov = c.next();
- assertion(cov.xPos == 7);
- assertion(cov.covDelta == 15);
- assertion(c.next() == null);
-
- System.out.println("ScanlineCoverage test 4");
- // Test testpoint 6.
- c.rewind();
- c.add(8, 21);
- cov = c.iterate();
- assertion(cov.xPos == 5);
- assertion(cov.covDelta == 4);
- cov = c.next();
- assertion(cov.xPos == 6);
- assertion(cov.covDelta == 20);
- cov = c.next();
- assertion(cov.xPos == 7);
- assertion(cov.covDelta == 15);
- cov = c.next();
- assertion(cov.xPos == 8);
- assertion(cov.covDelta == 21);
- assertion(c.next() == null);
-
- System.out.println("ScanlineCoverage test 5");
- // Test testpoint 6.
- c.rewind();
- c.add(2, 100);
- cov = c.iterate();
- assertion(cov.xPos == 2);
- assertion(cov.covDelta == 100);
- cov = c.next();
- assertion(cov.xPos == 5);
- assertion(cov.covDelta == 4);
- cov = c.next();
- assertion(cov.xPos == 6);
- assertion(cov.covDelta == 20);
- cov = c.next();
- assertion(cov.xPos == 7);
- assertion(cov.covDelta == 15);
- cov = c.next();
- assertion(cov.xPos == 8);
- assertion(cov.covDelta == 21);
- assertion(c.next() == null);
-
+ return head == null || head == last
+ || head.next == null || head.next == last;
}
- /**
- * Checks a condition and throws and AssertionError if this condition
- * fails.
- *
- * @param b the condition
- */
- private static void assertion(boolean b)
- {
- if (! b)
- {
- throw new AssertionError();
- }
- }
}