This adds primitive anti-aliasing to the AbstractGraphics2D scanline
converter and fixes some bits here and there.

2007-05-08  Roman Kennke  <[EMAIL PROTECTED]>

        * 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.

/Roman
-- 
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/java2d/AbstractGraphics2D.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java,v
retrieving revision 1.14
diff -u -1 -5 -r1.14 AbstractGraphics2D.java
--- gnu/java/awt/java2d/AbstractGraphics2D.java	1 Jan 2007 23:28:01 -0000	1.14
+++ gnu/java/awt/java2d/AbstractGraphics2D.java	8 May 2007 13:27:00 -0000
@@ -66,31 +66,30 @@
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Line2D;
 import java.awt.geom.NoninvertibleTransformException;
 import java.awt.geom.RoundRectangle2D;
 import java.awt.image.BufferedImage;
 import java.awt.image.BufferedImageOp;
 import java.awt.image.ColorModel;
 import java.awt.image.DataBuffer;
 import java.awt.image.ImageObserver;
 import java.awt.image.Raster;
 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;
 
 /**
  * This is a 100% Java implementation of the Java2D rendering pipeline. It is
  * meant as a base class for Graphics2D implementations.
  *
  * <h2>Backend interface</h2>
  * <p>
  * The backend must at the very least provide a Raster which the the rendering
  * pipeline can paint into. This must be implemented in
  * [EMAIL PROTECTED] #getDestinationRaster()}. For some backends that might be enough, like
  * when the target surface can be directly access via the raster (like in
  * BufferedImages). Other targets need some way to synchronize the raster with
  * the surface, which can be achieved by implementing the
@@ -144,37 +143,30 @@
  * </p>
  *
  * @author Roman Kennke ([EMAIL PROTECTED])
  */
 public abstract class AbstractGraphics2D
   extends Graphics2D
   implements Cloneable
 {
 
   /**
    * The default font to use on the graphics object.
    */
   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.
    */
   private static final ThreadLocal<ShapeCache> shapeCache =
     new ThreadLocal<ShapeCache>();
 
   /**
    * The scanline converters by thread.
    */
   private static final ThreadLocal<ScanlineConverter> scanlineConverters =
     new ThreadLocal<ScanlineConverter>();
 
   /**
    * The transformation for this Graphics2D instance
    */
@@ -215,41 +207,30 @@
    */
   private Shape clip;
 
   /**
    * The rendering hints.
    */
   private RenderingHints renderingHints;
 
   /**
    * The raster of the destination surface. This is where the painting is
    * performed.
    */
   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
    *   scaling.
    * - The paint must be a solid color.
    * - The composite must be an AlphaComposite.SrcOver.
    * - The clip must be a Rectangle.
    * - The stroke must be a plain BasicStroke().
    *
    * These conditions represent the standard settings of a new
    * AbstractGraphics2D object and will be the most commonly used setting
    * in Swing rendering and should therefore be optimized as much as possible.
    */
   private boolean isOptimized = true;
 
@@ -1340,56 +1321,66 @@
   /**
    * Fills an arc.
    */
   public void fillArc(int x, int y, int width, int height, int arcStart,
                       int arcAngle)
   {
     ShapeCache sc = getShapeCache();
     if (sc.arc == null)
       sc.arc = new Arc2D.Float();
     sc.arc.setArc(x, y, width, height, arcStart, arcAngle, Arc2D.PIE);
     draw(sc.arc);
   }
 
   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);
   }
 
   /**
    * Draws the outline of a polygon.
    */
   public void drawPolygon(int[] xPoints, int[] yPoints, int npoints)
   {
     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;
     draw(sc.polygon);
   }
 
   /**
    * Fills the outline of a polygon.
    */
   public void fillPolygon(int[] xPoints, int[] yPoints, int npoints)
   {
     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;
     fill(sc.polygon);
   }
 
   /**
    * Draws the specified image at the specified location. This forwards
    * to [EMAIL PROTECTED] #drawImage(Image, AffineTransform, ImageObserver)}.
    *
    * @param image the image to render
    * @param x the x location to render to
    * @param y the y location to render to
    * @param observer the image observer to receive notification
    */
@@ -1547,34 +1538,33 @@
    * method or something similar. But keep in mind that Shapes can be quite
    * complex (non-convex, with holes etc), which is not necessarily supported
    * by all polygon fillers. Also note that you must perform clipping
    * before filling the shape.
    *
    * @param s the shape to fill
    * @param isFont <code>true</code> if the shape is a font outline
    */
   protected void fillShape(Shape s, boolean isFont)
   {
     // Determine if we need to antialias stuff.
     boolean antialias = false;
     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
       {
         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);
@@ -1597,36 +1587,44 @@
     return destinationRaster.getBounds();
   }
 
   /**
    * Draws a line in optimization mode. The implementation should respect the
    * clip and translation. It can assume that the clip is a rectangle and that
    * the transform is only a translating transform.
    *
    * @param x0 the starting point, X coordinate
    * @param y0 the starting point, Y coordinate
    * @param x1 the end point, X coordinate 
    * @param y1 the end point, Y coordinate
    */
   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);
   }
 
   /**
    * Draws a string in optimization mode. The implementation should respect the
    * clip and translation. It can assume that the clip is a rectangle and that
    * the transform is only a translating transform.
    *
    * @param text the string to be drawn
    * @param x the start of the baseline, X coordinate
    * @param y the start of the baseline, Y coordinate
    */
   protected void rawDrawString(String text, int x, int y)
   {
     FontRenderContext ctx = getFontRenderContext();
     GlyphVector gv = font.createGlyphVector(ctx, text.toCharArray());
@@ -1650,31 +1648,35 @@
     rawFillRect(x, y, w, h);
     setPaint(savedForeground);
   }
 
   /**
    * Fills a rectangle in optimization mode. The implementation should respect
    * the clip but can assume that it is a rectangle.
    *
    * @param x the upper left corner, X coordinate
    * @param y the upper left corner, Y coordinate
    * @param w the width
    * @param h the height
    */
   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);
   }
 
   /**
    * Draws an image in optimization mode. The implementation should respect
    * the clip but can assume that it is a rectangle.
    *
    * @param image the image to be painted
    * @param x the location, X coordinate
    * @param y the location, Y coordinate
    * @param obs the image observer to be notified
    *
    * @return <code>true</code> when the image is painted completely,
    *         <code>false</code> if it is still rendered
    */
   protected boolean rawDrawImage(Image image, int x, int y, ImageObserver obs)
@@ -1722,90 +1724,30 @@
   {
     PaintContext pCtx = paintContext;
     Raster paintRaster = pCtx.getRaster(x0, y, x1 - x0, 1);
     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();
   }
 
 
   /**
-   * 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.
    */
   protected void init()
   {
     setPaint(Color.BLACK);
     setFont(FONT);
     isOptimized = true;
   }
 
   /**
    * Returns a WritableRaster that is used by this class to perform the
    * rendering in. It is not necessary that the target surface immediately
    * reflects changes in the raster. Updates to the raster are notified via
    * [EMAIL PROTECTED] #updateRaster}.
@@ -1959,16 +1901,21 @@
   /**
    * Returns the scanline converter for this thread.
    *
    * @return the scanline converter for this thread
    */
   private ScanlineConverter getScanlineConverter()
   {
     ScanlineConverter sc = scanlineConverters.get();
     if (sc == null)
       {
         sc = new ScanlineConverter();
         scanlineConverters.set(sc);
       }
     return sc;
   }
+
+  protected void fillScanlineAA(int x0, int x1, int y, int alpha2)
+  {
+    System.err.println("override!");
+  }
 }
Index: gnu/java/awt/java2d/ScanlineConverter.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/java2d/ScanlineConverter.java,v
retrieving revision 1.1
diff -u -1 -5 -r1.1 ScanlineConverter.java
--- gnu/java/awt/java2d/ScanlineConverter.java	1 Jan 2007 23:28:01 -0000	1.1
+++ gnu/java/awt/java2d/ScanlineConverter.java	8 May 2007 13:27:00 -0000
@@ -75,218 +75,283 @@
 
   /**
    * The upper bounds which correspond to the index 0 in the scanline array.
    *
    * This is a fixed point value.
    */
   private int upperBounds;
 
   /**
    * The resolution of the scanline converter.
    *
    * This is a fixed point value.
    */
   private int resolution;
 
+  private int scanlinesPerPixel;
+
   /**
    * One half step according to the resolution. This is stored to avoid
    * unnecessary operations during rendering.
    */
   private int halfStep;
 
   /**
    * This is used in [EMAIL PROTECTED] #addShape(PathIterator, boolean)} to
    * receive the coordinates of the path.
    */
   private float[] coords;
 
   /**
    * The active edges.
    */
   private ActiveEdges activeEdges;
 
   private PolyEdge edgePool;
   private PolyEdge edgePoolLast;
 
   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.
    */
   ScanlineConverter()
   {
     scanlines = new Scanline[10];
     coords = new float[6];
     activeEdges = new ActiveEdges();
     edgePool = new PolyEdge();
     edgePoolLast = edgePool;
   }
 
   /**
    * Renders the specified shape using the specified clip and transform.
    *
    * @param shape the shape to render
    * @param clip the clip
    * @param trans the transform
    */
   void renderShape(AbstractGraphics2D g, Shape shape, Shape clip,
                    AffineTransform trans, int res)
   {
     // Prepare resolution and upper bounds.
     clear();
     setResolution(res);
 
     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);
       }
 
     setUpperBounds(minY);
 
     PolyEdge edge = edgePool;
     while (edge != edgePoolLast)
       {
         addEdge(edge);
         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.
         index = scanlineIndex(y);
         // If we go outside the scanline array we still need to render the
         // remaining edges until they end.
         scanline = index < scanlines.length ? scanlines[index] : null;
         if (scanline != null)
           {
             edge = scanline.getEdges();
             while (edge != null)
               {
                 activeEdges.add(edge);
                 edge = edge.scanlineNext;
               }
           }
 
         // Then we intersect all active edges with the current scanline
         // and sort them according to their intersection points.
         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;
+
       }
   }
 
   /**
    * Clears all scanlines.
    */
   private void clear()
   {
     // Reset edge pool.
     edgePoolLast = edgePool;
 
     // Reset scanlines.
     for (int i = scanlines.length - 1; i >= 0 ; i--)
       {
         Scanline sl = scanlines[i];
         if (sl != null)
           sl.clear();
       }
 
     // Reset bounds.
     minY = Integer.MAX_VALUE;
     maxY = Integer.MIN_VALUE;
+    minX = Integer.MAX_VALUE;
+    maxX = Integer.MIN_VALUE;
   }
 
   /**
    * Performs the scanlining on the current set of active edges.
    */
   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;
     boolean inShape = false;
     PolyEdge lastEdge = null;
     int numEdges = activeEdges.getNumActiveEdges();
     for (int i = 0; i < numEdges; i++)
       {
         PolyEdge edge = activeEdges.getActiveEdge(i);
         if (inClip && inShape)
           {
             assert lastEdge != null;
             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)
           inClip = ! inClip;
         else
           inShape = ! inShape;
 
         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
    * anti-aliasing. Greater values renders with a resolution of 2 ^ res.
    *
    * @param res the resolution
    */
   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;
   }
 
   /**
    * Sets the vertical bounds of that shape that is beeing rendered.
    *
    * @param y0 the upper bounds
    */
   private void setUpperBounds(int y0)
   {
     upperBounds = fit(y0);
   }
 
   /**
    * Add a shape to the scanline converter.
    *
@@ -297,39 +362,43 @@
   {
     int startX = 0;
     int startY = 0;
     int lastX = 0;
     int lastY = 0;
     while (! path.isDone())
       {
         int type = path.currentSegment(coords);
         switch (type)
           {
             case PathIterator.SEG_MOVETO:
               startX = lastX = Fixed.fixedValue(FIXED_DIGITS, coords[0]);
               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]);
               int y = Fixed.fixedValue(FIXED_DIGITS, coords[1]);
               edgePoolAdd(lastX, lastY, x, y, clip);
               lastX = x;
               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);
               lastX = startX;
               lastY = startY;
               break;
             case PathIterator.SEG_CUBICTO:
             case PathIterator.SEG_QUADTO:
             default:
               assert false;
           }
         path.next();
       }
   }
 
@@ -359,31 +428,31 @@
       }
     scanlines[index].addEdge(edge);
   }
 
   /**
    * Fits an Y coordinate to the grid.
    *
    * @param y the Y coordinate to fit
    *
    * @return the fitted Y coordinate
    */
   private int fit(int y)
   {
     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);
   }
 
   /**
    * Calculates the scanline index for the specified y coordinate.
    *
    * @param y the y coordinate as fixed point value
    *
    * @return the scanline index
    */
   private int scanlineIndex(int y)
   {
     int fitted = fit(y);
     // Cleverly skip the fixed point conversions here.
     return (fitted - upperBounds)/ resolution;
   }
Index: gnu/java/awt/java2d/ShapeCache.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/java2d/ShapeCache.java,v
retrieving revision 1.1
diff -u -1 -5 -r1.1 ShapeCache.java
--- gnu/java/awt/java2d/ShapeCache.java	29 Sep 2006 12:36:33 -0000	1.1
+++ gnu/java/awt/java2d/ShapeCache.java	8 May 2007 13:27:00 -0000
@@ -30,30 +30,31 @@
 terms of your choice, provided that you also meet, for each linked
 independent module, the terms and conditions of the license of that
 module.  An independent module is a module which is not derived from
 or based on this library.  If you modify this library, you may extend
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
 
 package gnu.java.awt.java2d;
 
 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;
 
 /**
  * Caches certain Shape objects for reuse in AbstractGraphics2D. This avoids
  * massive creation of such objects.
  */
 public class ShapeCache
 {
 
   /**
    * A cached Line2D.
    */
   public Line2D line;
 
@@ -70,16 +71,20 @@
   /**
    * A cached Ellipse2D.
    */
   public Ellipse2D ellipse;
 
   /**
    * A cached Arc2D.
    */
   public Arc2D arc;
 
   /**
    * A cached Polygon.
    */
   public Polygon polygon;
 
+  /**
+   * A cached polyline.
+   */
+  public GeneralPath polyline;
 }

Attachment: signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil

Reply via email to