summaryrefslogtreecommitdiff
path: root/gnu/java/awt/java2d
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
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')
-rw-r--r--gnu/java/awt/java2d/AbstractGraphics2D.java123
-rw-r--r--gnu/java/awt/java2d/ScanlineConverter.java113
-rw-r--r--gnu/java/awt/java2d/ShapeCache.java5
3 files changed, 131 insertions, 110 deletions
diff --git a/gnu/java/awt/java2d/AbstractGraphics2D.java b/gnu/java/awt/java2d/AbstractGraphics2D.java
index f6c5ff0cb..0b1dd8d6e 100644
--- a/gnu/java/awt/java2d/AbstractGraphics2D.java
+++ b/gnu/java/awt/java2d/AbstractGraphics2D.java
@@ -78,7 +78,6 @@ import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.awt.image.renderable.RenderableImage;
import java.text.AttributedCharacterIterator;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@@ -156,13 +155,6 @@ public abstract class AbstractGraphics2D
private static final Font FONT = new Font("SansSerif", Font.PLAIN, 12);
/**
- * Accuracy of the sampling in the anti-aliasing shape filler.
- * Lower values give more speed, while higher values give more quality.
- * It is advisable to choose powers of two.
- */
- private static final int AA_SAMPLING = 8;
-
- /**
* Caches certain shapes to avoid massive creation of such Shapes in
* the various draw* and fill* methods.
*/
@@ -227,17 +219,6 @@ public abstract class AbstractGraphics2D
private WritableRaster destinationRaster;
/**
- * Stores the alpha values for a scanline in the anti-aliasing shape
- * renderer.
- */
- private transient int[] alpha;
-
- /**
- * The edge table for the scanline conversion algorithms.
- */
- private transient ArrayList[] edgeTable;
-
- /**
* Indicates if certain graphics primitives can be rendered in an optimized
* fashion. This will be the case if the following conditions are met:
* - The transform may only be a translation, no rotation, shearing or
@@ -1352,8 +1333,16 @@ public abstract class AbstractGraphics2D
public void drawPolyline(int[] xPoints, int[] yPoints, int npoints)
{
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
+ ShapeCache sc = getShapeCache();
+ if (sc.polyline == null)
+ sc.polyline = new GeneralPath();
+ GeneralPath p = sc.polyline;
+ p.reset();
+ if (npoints > 0)
+ p.moveTo(xPoints[0], yPoints[0]);
+ for (int i = 1; i < npoints; i++)
+ p.lineTo(xPoints[i], yPoints[i]);
+ fill(p);
}
/**
@@ -1364,6 +1353,7 @@ public abstract class AbstractGraphics2D
ShapeCache sc = getShapeCache();
if (sc.polygon == null)
sc.polygon = new Polygon();
+ sc.polygon.reset();
sc.polygon.xpoints = xPoints;
sc.polygon.ypoints = yPoints;
sc.polygon.npoints = npoints;
@@ -1378,6 +1368,7 @@ public abstract class AbstractGraphics2D
ShapeCache sc = getShapeCache();
if (sc.polygon == null)
sc.polygon = new Polygon();
+ sc.polygon.reset();
sc.polygon.xpoints = xPoints;
sc.polygon.ypoints = yPoints;
sc.polygon.npoints = npoints;
@@ -1559,10 +1550,9 @@ public abstract class AbstractGraphics2D
if (isFont)
{
Object v = renderingHints.get(RenderingHints.KEY_TEXT_ANTIALIASING);
- // We default to antialiasing on for text as long as we have no
- // good hinting implemented.
- antialias = (v == RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
- //|| v == RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
+ // We default to antialiasing for text rendering.
+ antialias = (v == RenderingHints.VALUE_TEXT_ANTIALIAS_ON
+ || v == RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
}
else
{
@@ -1609,12 +1599,20 @@ public abstract class AbstractGraphics2D
*/
protected void rawDrawLine(int x0, int y0, int x1, int y1)
{
- draw(new Line2D.Float(x0, y0, x1, y1));
+ ShapeCache sc = getShapeCache();
+ if (sc.line == null)
+ sc.line = new Line2D.Float();
+ sc.line.setLine(x0, y0, x1, y1);
+ draw(sc.line);
}
protected void rawDrawRect(int x, int y, int w, int h)
{
- draw(new Rectangle(x, y, w, h));
+ ShapeCache sc = getShapeCache();
+ if (sc.rect == null)
+ sc.rect = new Rectangle();
+ sc.rect.setBounds(x, y, w, h);
+ draw(sc.rect);
}
/**
@@ -1662,7 +1660,11 @@ public abstract class AbstractGraphics2D
*/
protected void rawFillRect(int x, int y, int w, int h)
{
- fill(new Rectangle(x, y, w, h));
+ ShapeCache sc = getShapeCache();
+ if (sc.rect == null)
+ sc.rect = new Rectangle();
+ sc.rect.setBounds(x, y, w, h);
+ fill(sc.rect);
}
/**
@@ -1734,66 +1736,6 @@ public abstract class AbstractGraphics2D
/**
- * Fills a horizontal line between x0 and x1 for anti aliased rendering.
- * the alpha array contains the deltas of the alpha values from one pixel
- * to the next.
- *
- * @param alpha the alpha values in the scanline
- * @param x0 the beginning of the scanline
- * @param yy the y coordinate of the line
- */
- private void fillScanlineAA(int[] alpha, int x0, int yy, int numPixels,
- PaintContext pCtx, int offs)
- {
- CompositeContext cCtx = composite.createContext(pCtx.getColorModel(),
- getColorModel(),
- renderingHints);
- Raster paintRaster = pCtx.getRaster(x0, yy, numPixels, 1);
- //System.err.println("paintColorModel: " + pCtx.getColorModel());
- WritableRaster aaRaster = paintRaster.createCompatibleWritableRaster();
- ColorModel cm = pCtx.getColorModel();
- double lastAlpha = 0.;
- int lastAlphaInt = 0;
-
- Object pixel = null;
- int[] comps = null;
- int x1 = x0 + numPixels;
- for (int x = x0; x < x1; x++)
- {
- int i = x - offs;
- if (alpha[i] != 0)
- {
- lastAlphaInt += alpha[i];
- lastAlpha = (double) lastAlphaInt / (double) AA_SAMPLING;
- alpha[i] = 0;
- }
- pixel = paintRaster.getDataElements(x - x0, 0, pixel);
- comps = cm.getComponents(pixel, comps, 0);
- if (cm.hasAlpha() && ! cm.isAlphaPremultiplied())
- comps[comps.length - 1] *= lastAlpha;
- else
- {
- int max;
- if (cm.hasAlpha())
- max = comps.length - 2;
- else
- max = comps.length - 1;
- for (int j = 0; j < max; j++)
- comps[j] *= lastAlpha;
- }
- pixel = cm.getDataElements(comps, 0, pixel);
- aaRaster.setDataElements(x - x0, 0, pixel);
- }
-
- WritableRaster targetChild =
- destinationRaster.createWritableTranslatedChild(-x0, -yy);
- cCtx.compose(aaRaster, targetChild, targetChild);
- updateRaster(destinationRaster, x0, yy, numPixels, 1);
-
- cCtx.dispose();
- }
-
- /**
* Initializes this graphics object. This must be called by subclasses in
* order to correctly initialize the state of this object.
*/
@@ -1971,4 +1913,9 @@ public abstract class AbstractGraphics2D
}
return sc;
}
+
+ protected void fillScanlineAA(int x0, int x1, int y, int alpha2)
+ {
+ System.err.println("override!");
+ }
}
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);
}
/**
diff --git a/gnu/java/awt/java2d/ShapeCache.java b/gnu/java/awt/java2d/ShapeCache.java
index 034b53cad..89a9ac4ab 100644
--- a/gnu/java/awt/java2d/ShapeCache.java
+++ b/gnu/java/awt/java2d/ShapeCache.java
@@ -42,6 +42,7 @@ import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
+import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.RoundRectangle2D;
@@ -82,4 +83,8 @@ public class ShapeCache
*/
public Polygon polygon;
+ /**
+ * A cached polyline.
+ */
+ public GeneralPath polyline;
}