summaryrefslogtreecommitdiff
path: root/gnu/java/awt/java2d/ScanlineConverter.java
diff options
context:
space:
mode:
authorRoman Kennke <roman@kennke.org>2007-05-08 13:27:30 +0000
committerRoman Kennke <roman@kennke.org>2007-05-08 13:27:30 +0000
commitbfb5cc0ebd613f1b359bbfafe35f9264411cae19 (patch)
tree30d46d64d713f0c358ed915549d7e0ae2298eeab /gnu/java/awt/java2d/ScanlineConverter.java
parentb61e8e8112f60e7e8978b2fd36da36d3fe5686dd (diff)
downloadclasspath-bfb5cc0ebd613f1b359bbfafe35f9264411cae19.tar.gz
2007-05-08 Roman Kennke <roman@kennke.org>
* gnu/java/awt/java2d/AbstractGraphics2D.java (AA_SAMPLING): Removed. (alpha): Removed field. (edgeTable): Removed field. (fillScanlineAA): Removed obsolete method. (drawPolyline): Implemented by using a GeneralPath. (drawPolygon): Reset the cached polygon. (fillPolygon): Reset the cached polygon. (fillShape): Default to antialias on for text. (rawDrawLine): Use ShapeCache. (rawDrawRect): Use ShapeCache. (rawFillRect): Use ShapeCache. (fillScanlineAA): New method for antialiased rendering. * gnu/java/awt/java2d/ScanlineConverter.java (scanlinesPerPixel): New field. (minX,maxX): New fields. (scanlineYCov,scanlineXCov): New fields. (slPix0): New field. (alphaRes): New field. (renderShape): Add antialiasing functionality. (doScanline): Add antialiasing functionality. (setResolution): Add antialiasing functionality. (addShape): Determine span in X direction. (fit): Fix thinko. * gnu/java/awt/java2d/ShapeCache.java (polyline): New field for caching polylines.
Diffstat (limited to 'gnu/java/awt/java2d/ScanlineConverter.java')
-rw-r--r--gnu/java/awt/java2d/ScanlineConverter.java113
1 files changed, 91 insertions, 22 deletions
diff --git a/gnu/java/awt/java2d/ScanlineConverter.java b/gnu/java/awt/java2d/ScanlineConverter.java
index 9f9d8921f..5254af901 100644
--- a/gnu/java/awt/java2d/ScanlineConverter.java
+++ b/gnu/java/awt/java2d/ScanlineConverter.java
@@ -87,6 +87,8 @@ final class ScanlineConverter
*/
private int resolution;
+ private int scanlinesPerPixel;
+
/**
* One half step according to the resolution. This is stored to avoid
* unnecessary operations during rendering.
@@ -109,6 +111,13 @@ final class ScanlineConverter
private int minY;
private int maxY;
+ private int minX;
+ private int maxX;
+
+ private int[] scanlineYCov;
+ private int[] scanlineXCov;
+ private int slPix0;
+ private int alphaRes;
/**
* Create a new ScanlineConverter.
@@ -139,11 +148,12 @@ final class ScanlineConverter
boolean haveClip = clip != null;
// Add shapes.
- PathIterator path = shape.getPathIterator(trans, resolution);
+ float flatness = Fixed.floatValue(FIXED_DIGITS, resolution / 2);
+ PathIterator path = shape.getPathIterator(trans, flatness);
addShape(path, false);
if (haveClip)
{
- path= clip.getPathIterator(trans, resolution);
+ path= clip.getPathIterator(trans, flatness);
addShape(path, true);
}
@@ -156,12 +166,26 @@ final class ScanlineConverter
edge = edge.poolNext;
}
+ // For AA: Prepare the scanline pixels array.
+ if (resolution < ONE)
+ {
+ int x0 = Fixed.intValue(FIXED_DIGITS, minX);
+ int x1 = Fixed.intValue(FIXED_DIGITS, maxX) + 1;
+ int span = x1 - x0;
+ if (scanlineYCov == null || span >= scanlineYCov.length)
+ {
+ scanlineYCov = new int[span];
+ scanlineXCov = new int[span];
+ }
+ slPix0 = x0;
+ }
+
int y = upperBounds;
- int lastIndex = scanlineIndex(y - resolution);
int index;
activeEdges.clear();
// The render loop...
Scanline scanline = null;
+ int lastRealY = Fixed.intValue(FIXED_DIGITS, y);
while (y <= maxY)
{
// First we put together our list of active edges.
@@ -184,15 +208,16 @@ final class ScanlineConverter
activeEdges.intersectSortAndPack(FIXED_DIGITS, y + halfStep);
// Ok, now we can perform the actual scanlining.
- boolean push = lastIndex != index;
+ int realY = Fixed.intValue(FIXED_DIGITS, y + resolution);
+ boolean push = lastRealY != realY;
doScanline(g, y, push, haveClip);
// Remove obsolete active edges.
//activeEdges.remove(y + halfStep);
-
// Go on with the next line...
y += resolution;
- lastIndex = index;
+ lastRealY = realY;
+
}
}
@@ -215,6 +240,8 @@ final class ScanlineConverter
// Reset bounds.
minY = Integer.MAX_VALUE;
maxY = Integer.MIN_VALUE;
+ minX = Integer.MAX_VALUE;
+ maxX = Integer.MIN_VALUE;
}
/**
@@ -223,6 +250,7 @@ final class ScanlineConverter
private void doScanline(AbstractGraphics2D g, int y, boolean push,
boolean haveClip)
{
+
// We begin outside the clip and outside the shape. We only draw when
// we are inside the clip AND inside the shape.
boolean inClip = ! haveClip;
@@ -238,21 +266,24 @@ final class ScanlineConverter
int x0 = lastEdge.xIntersection;
int x1 = edge.xIntersection;
assert x0 <= x1;
- if (push)
+ if (resolution == ONE)
{
- if (resolution == ONE)
- {
- // Non-AA rendering.
- g.fillScanline(Fixed.intValue(FIXED_DIGITS, x0),
- Fixed.intValue(FIXED_DIGITS, x1 - resolution),
- Fixed.intValue(FIXED_DIGITS, y));
- }
- else
- {
- // AA rendering.
- // FIXME: Implement.
- System.err.println("Implement AA rendering.");
- }
+ // Non-AA rendering.
+ g.fillScanline(Fixed.intValue(FIXED_DIGITS, x0 + resolution / 2),
+ Fixed.intValue(FIXED_DIGITS, x1 - resolution / 2),
+ Fixed.intValue(FIXED_DIGITS, y));
+ }
+ else
+ {
+ int pix0 = Fixed.intValue(FIXED_DIGITS, x0);
+ int frac0 = ONE - (x0 - Fixed.floor(FIXED_DIGITS, x0));
+ int pix1 = Fixed.intValue(FIXED_DIGITS, x1);
+ int frac1 = ONE - (x1 - Fixed.floor(FIXED_DIGITS, x1));
+ //System.err.println("render scanline AA: " + Fixed.floatValue(FIXED_DIGITS, y) + ", " + pix0 + ", " + pix1 + "(" + Fixed.floatValue(FIXED_DIGITS, x0) + ", " + Fixed.floatValue(FIXED_DIGITS, x1) +")");
+ scanlineYCov[pix0 - slPix0] += alphaRes;
+ scanlineYCov[pix1 - slPix0] -= alphaRes;
+ scanlineXCov[pix0 - slPix0] += frac0;
+ scanlineXCov[pix1 - slPix0] += frac1;
}
}
if (edge.isClip)
@@ -262,7 +293,39 @@ final class ScanlineConverter
lastEdge = edge;
}
- }
+
+ // For AA we push out the scanline when necessary.
+ if (push && ONE > resolution)
+ {
+ // Push out AA'ed scanline.
+ int rx1 = 0;
+ int alpha = 0;
+ for (int idx = 0; idx < scanlineYCov.length; idx++)
+ {
+ rx1 = slPix0 + idx;
+ if (scanlineYCov[idx] != 0)
+ {
+ // Render transitioning pixel with x coverage included.
+ int transAlpha = alpha + (scanlineYCov[idx] * scanlineXCov[idx]) / (scanlinesPerPixel * 64);
+ //System.err.println("pixel: " + rx1 + " old alpha: " + alpha + " ycov:" + scanlineYCov[idx] + " xcov: " + scanlineXCov[idx] + " tAlpha: " + transAlpha);
+ g.fillScanlineAA(rx1, rx1,
+ Fixed.intValue(FIXED_DIGITS, y),
+ Math.max(Math.min(transAlpha, 255), 0));
+ alpha = alpha + scanlineYCov[idx];
+ }
+ else if (alpha > 0)
+ {
+ //System.err.println("pixel: " + rx1 + " alpha: " + alpha);
+ g.fillScanlineAA(rx1, rx1,
+ Fixed.intValue(FIXED_DIGITS, y),
+ Math.min(alpha, 255));
+ }
+ scanlineYCov[idx] = 0;
+ scanlineXCov[idx] = 0;
+ }
+ }
+ }
+
/**
* Sets the resolution. A value of 0 rasterizes the shape normally without
@@ -272,9 +335,11 @@ final class ScanlineConverter
*/
private void setResolution(int res)
{
+ scanlinesPerPixel = 1 << res;
int one = Fixed.fixedValue(FIXED_DIGITS, 1);
resolution = one / (1 << res);
halfStep = resolution / 2;
+ alphaRes = 256 >> res;
}
/**
@@ -309,6 +374,8 @@ final class ScanlineConverter
startY = lastY = Fixed.fixedValue(FIXED_DIGITS, coords[1]);
minY = Math.min(startY, minY);
maxY = Math.max(startY, maxY);
+ minX = Math.min(startX, minX);
+ maxX = Math.max(startX, maxX);
break;
case PathIterator.SEG_LINETO:
int x = Fixed.fixedValue(FIXED_DIGITS, coords[0]);
@@ -318,6 +385,8 @@ final class ScanlineConverter
lastY = y;
minY = Math.min(lastY, minY);
maxY = Math.max(lastY, maxY);
+ minX = Math.min(lastX, minX);
+ maxX = Math.max(lastX, maxX);
break;
case PathIterator.SEG_CLOSE:
edgePoolAdd(lastX, lastY, startX, startY, clip);
@@ -371,7 +440,7 @@ final class ScanlineConverter
{
int val1 = Fixed.div(FIXED_DIGITS, y, resolution);
int rounded = Fixed.round(FIXED_DIGITS, val1);
- return Fixed.div(FIXED_DIGITS, rounded, resolution);
+ return Fixed.mul(FIXED_DIGITS, rounded, resolution);
}
/**