diff options
| author | Roman Kennke <roman@kennke.org> | 2007-05-08 13:27:30 +0000 |
|---|---|---|
| committer | Roman Kennke <roman@kennke.org> | 2007-05-08 13:27:30 +0000 |
| commit | bfb5cc0ebd613f1b359bbfafe35f9264411cae19 (patch) | |
| tree | 30d46d64d713f0c358ed915549d7e0ae2298eeab /gnu/java/awt/java2d/ScanlineConverter.java | |
| parent | b61e8e8112f60e7e8978b2fd36da36d3fe5686dd (diff) | |
| download | classpath-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.java | 113 |
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); } /** |
