/* AbstractGraphics2D.java -- Abstract Graphics2D implementation
   Copyright (C) 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
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 gnu.java.util.LRUCache;

import java.awt.AWTError;
import java.awt.AlphaComposite;
import java.awt.AWTPermission;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.CompositeContext;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.awt.PaintContext;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.RenderingHints.Key;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
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.FilteredImageSource;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.ReplicateScaleFilter;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.awt.image.renderable.RenderableImage;
import java.text.AttributedCharacterIterator;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.WeakHashMap;

/**
 * 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
 * {@link #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
 * {@link #updateRaster(Raster, int, int, int, int)} method, which always gets
 * called after a chunk of data got painted into the raster.
 * </p>
 * <p>Alternativly the backend can provide a method for filling Shapes by
 * overriding the protected method fillShape(). This can be accomplished
 * by a polygon filling function of the backend. Keep in mind though that
 * Shapes can be quite complex (i.e. non-convex and containing holes, etc)
 * which is not supported by all polygon fillers. Also it must be noted
 * that fillShape() is expected to handle painting and compositing as well as
 * clipping and transformation. If your backend can't support this natively,
 * then you can fallback to the implementation in this class. You'll need
 * to provide a writable Raster then, see above.</p>
 * <p>Another alternative is to implement fillScanline() which only requires
 * the backend to be able to draw horizontal lines in device space,
 * which is usually very cheap.
 * The implementation should still handle painting and compositing,
 * but no more clipping and transformation is required by the backend.</p>
 * <p>The backend is free to provide implementations for the various raw*
 * methods for optimized AWT 1.1 style painting of some primitives. This should
 * accelerate painting of Swing greatly. When doing so, the backend must also
 * keep track of the clip and translation, probably by overriding
 * some clip and translate methods. Don't forget to message super in such a
 * case.</p>
 *
 * <h2>Acceleration options</h2>
 * <p>
 * The fact that it is
 * pure Java makes it a little slow. However, there are several ways of
 * accelerating the rendering pipeline:
 * <ol>
 * <li><em>Optimization hooks for AWT 1.1 - like graphics operations.</em>
 *   The most important methods from the {@link java.awt.Graphics} class
 *   have a corresponding <code>raw*</code> method, which get called when
 *   several optimization conditions are fullfilled. These conditions are
 *   described below. Subclasses can override these methods and delegate
 *   it directly to a native backend.</li>
 * <li><em>Native PaintContexts and CompositeContext.</em> The implementations
 *   for the 3 PaintContexts and AlphaCompositeContext can be accelerated
 *   using native code. These have proved to two of the most performance
 *   critical points in the rendering pipeline and cannot really be done quickly
 *   in plain Java because they involve lots of shuffling around with large
 *   arrays. In fact, you really would want to let the graphics card to the
 *   work, they are made for this.</li>
 * <li>Provide an accelerated implementation for fillShape(). For instance,
 * OpenGL can fill shapes very efficiently. There are some considerations
 * to be made though, see above for details.</li>
 * </ol>
 * </p>
 *
 * @author Roman Kennke (kennke@aicas.com)
 */
public abstract class AbstractGraphics2D
  extends Graphics2D
  implements Cloneable, Pixelizer
{
  /**
   * Caches scaled versions of an image.
   *
   * @see #drawImage(Image, int, int, int, int, ImageObserver)
   */
  protected static final WeakHashMap<Image, HashMap<Dimension,Image>> imageCache =
    new WeakHashMap<Image, HashMap<Dimension, Image>>();

  /**
   * Wether we use anti aliasing for rendering text by default or not.
   */
  private static final boolean DEFAULT_TEXT_AA =
    Boolean.getBoolean("gnu.java2d.default_text_aa");

  /**
   * The default font to use on the graphics object.
   */
  private static final Font FONT = new Font("SansSerif", Font.PLAIN, 12);

  /**
   * The size of the LRU cache used for caching GlyphVectors.
   */
  private static final int GV_CACHE_SIZE = 50;

  /**
   * Caches certain shapes to avoid massive creation of such Shapes in
   * the various draw* and fill* methods.
   */
  private static final ShapeCache shapeCache = new ShapeCache();

  /**
   * A pool of scanline converters. It is important to reuse scanline
   * converters because they keep their datastructures in place. We pool them
   * for use in multiple threads.
   */
  private static final LinkedList<ScanlineConverter> scanlineConverters =
    new LinkedList<ScanlineConverter>();

  /**
   * Caches glyph vectors for better drawing performance.
   */
  private static final Map<TextCacheKey,GlyphVector> gvCache =
    Collections.synchronizedMap(new LRUCache<TextCacheKey,GlyphVector>(GV_CACHE_SIZE));

  /**
   * This key is used to search in the gvCache without allocating a new
   * key each time.
   */
  private static final TextCacheKey searchTextKey = new TextCacheKey();

  /**
   * The transformation for this Graphics2D instance
   */
  protected AffineTransform transform;

  /**
   * The foreground.
   */
  private Paint paint;

  /**
   * The paint context during rendering.
   */
  private PaintContext paintContext = null;

  /**
   * The background.
   */
  private Color background = Color.WHITE;

  /**
   * Foreground color, as set by setColor.
   */
  private Color foreground = Color.BLACK;
  private boolean isForegroundColorNull = true;

  /**
   * The current font.
   */
  private Font font;

  /**
   * The current composite setting.
   */
  private Composite composite;

  /**
   * The current stroke setting.
   */
  private Stroke stroke;

  /**
   * The current clip. This clip is in user coordinate space.
   */
  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;

  /**
   * 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;

  private static final BasicStroke STANDARD_STROKE = new BasicStroke();

  private static final HashMap<Key, Object> STANDARD_HINTS;
  static
    {

      HashMap<Key, Object> hints = new HashMap<Key, Object>();
      hints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
      hints.put(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_DEFAULT);

      STANDARD_HINTS = hints;
    }

  /**
   * Creates a new AbstractGraphics2D instance.
   */
  protected AbstractGraphics2D()
  {
    transform = new AffineTransform();
    background = Color.WHITE;
    composite = AlphaComposite.SrcOver;
    stroke = STANDARD_STROKE;
    renderingHints = new RenderingHints(STANDARD_HINTS);
  }

  /**
   * Draws the specified shape. The shape is passed through the current stroke
   * and is then forwarded to {@link #fillShape}.
   *
   * @param shape the shape to draw
   */
  public void draw(Shape shape)
  {
    // Stroke the shape.
    Shape strokedShape = stroke.createStrokedShape(shape);
    // Fill the stroked shape.
    fillShape(strokedShape, false);
  }


  /**
   * Draws the specified image and apply the transform for image space ->
   * user space conversion.
   *
   * This method is implemented to special case RenderableImages and
   * RenderedImages and delegate to
   * {@link #drawRenderableImage(RenderableImage, AffineTransform)} and
   * {@link #drawRenderedImage(RenderedImage, AffineTransform)} accordingly.
   * Other image types are not yet handled.
   *
   * @param image the image to be rendered
   * @param xform the transform from image space to user space
   * @param obs the image observer to be notified
   */
  public boolean drawImage(Image image, AffineTransform xform,
                           ImageObserver obs)
  {
    Rectangle areaOfInterest = new Rectangle(0, 0, image.getWidth(obs),
                                             image.getHeight(obs));
    return drawImageImpl(image, xform, obs, areaOfInterest);
  }

  /**
   * Draws the specified image and apply the transform for image space ->
   * user space conversion. This method only draw the part of the image
   * specified by <code>areaOfInterest</code>.
   *
   * This method is implemented to special case RenderableImages and
   * RenderedImages and delegate to
   * {@link #drawRenderableImage(RenderableImage, AffineTransform)} and
   * {@link #drawRenderedImage(RenderedImage, AffineTransform)} accordingly.
   * Other image types are not yet handled.
   *
   * @param image the image to be rendered
   * @param xform the transform from image space to user space
   * @param obs the image observer to be notified
   * @param areaOfInterest the area in image space that is rendered
   */
  private boolean drawImageImpl(Image image, AffineTransform xform,
                             ImageObserver obs, Rectangle areaOfInterest)
  {
    boolean ret;
    if (image == null)
      {
        ret = true;
      }
    else if (image instanceof RenderedImage)
      {
        // FIXME: Handle the ImageObserver.
        drawRenderedImageImpl((RenderedImage) image, xform, areaOfInterest);
        ret = true;
      }
    else if (image instanceof RenderableImage)
      {
        // FIXME: Handle the ImageObserver.
        drawRenderableImageImpl((RenderableImage) image, xform, areaOfInterest);
        ret = true;
      }
    else
      {
        // FIXME: Implement rendering of other Image types.
        ret = false;
      }
    return ret;
  }

  /**
   * Renders a BufferedImage and applies the specified BufferedImageOp before
   * to filter the BufferedImage somehow. The resulting BufferedImage is then
   * passed on to {@link #drawRenderedImage(RenderedImage, AffineTransform)}
   * to perform the final rendering.
   *
   * @param image the source buffered image
   * @param op the filter to apply to the buffered image before rendering
   * @param x the x coordinate to render the image to
   * @param y the y coordinate to render the image to
   */
  public void drawImage(BufferedImage image, BufferedImageOp op, int x, int y)
  {
    BufferedImage filtered =
      op.createCompatibleDestImage(image, image.getColorModel());
    AffineTransform t = new AffineTransform();
    t.translate(x, y);
    drawRenderedImage(filtered, t);
  }

  /**
   * Renders the specified image to the destination raster. The specified
   * transform is used to convert the image into user space. The transform
   * of this AbstractGraphics2D object is used to transform from user space
   * to device space.
   *
   * The rendering is performed using the scanline algorithm that performs the
   * rendering of other shapes and a custom Paint implementation, that supplies
   * the pixel values of the rendered image.
   *
   * @param image the image to render to the destination raster
   * @param xform the transform from image space to user space
   */
  public void drawRenderedImage(RenderedImage image, AffineTransform xform)
  {
    Rectangle areaOfInterest = new Rectangle(image.getMinX(),
                                             image.getHeight(),
                                             image.getWidth(),
                                             image.getHeight());
    drawRenderedImageImpl(image, xform, areaOfInterest);
  }

  /**
   * Renders the specified image to the destination raster. The specified
   * transform is used to convert the image into user space. The transform
   * of this AbstractGraphics2D object is used to transform from user space
   * to device space. Only the area specified by <code>areaOfInterest</code>
   * is finally rendered to the target.
   *
   * The rendering is performed using the scanline algorithm that performs the
   * rendering of other shapes and a custom Paint implementation, that supplies
   * the pixel values of the rendered image.
   *
   * @param image the image to render to the destination raster
   * @param xform the transform from image space to user space
   */
  private void drawRenderedImageImpl(RenderedImage image,
                                     AffineTransform xform,
                                     Rectangle areaOfInterest)
  {
    // First we compute the transformation. This is made up of 3 parts:
    // 1. The areaOfInterest -> image space transform.
    // 2. The image space -> user space transform.
    // 3. The user space -> device space transform.
    AffineTransform t = new AffineTransform();
    t.translate(- areaOfInterest.x - image.getMinX(),
                - areaOfInterest.y - image.getMinY());
    t.concatenate(xform);
    t.concatenate(transform);
    AffineTransform it = null;
    try
      {
        it = t.createInverse();
      }
    catch (NoninvertibleTransformException ex)
      {
        // Ignore -- we return if the transform is not invertible.
      }
    if (it != null)
      {
        // Transform the area of interest into user space.
        GeneralPath aoi = new GeneralPath(areaOfInterest);
        aoi.transform(xform);
        // Render the shape using the standard renderer, but with a temporary
        // ImagePaint.
        ImagePaint p = new ImagePaint(image, it);
        Paint savedPaint = paint;
        try
          {
            paint = p;
            fillShape(aoi, false);
          }
        finally
          {
            paint = savedPaint;
          }
      }
  }

  /**
   * Renders a renderable image. This produces a RenderedImage, which is
   * then passed to {@link #drawRenderedImage(RenderedImage, AffineTransform)}
   * to perform the final rendering.
   *
   * @param image the renderable image to be rendered
   * @param xform the transform from image space to user space
   */
  public void drawRenderableImage(RenderableImage image, AffineTransform xform)
  {
    Rectangle areaOfInterest = new Rectangle((int) image.getMinX(),
                                             (int) image.getHeight(),
                                             (int) image.getWidth(),
                                             (int) image.getHeight());
    drawRenderableImageImpl(image, xform, areaOfInterest);

  }

  /**
   * Renders a renderable image. This produces a RenderedImage, which is
   * then passed to {@link #drawRenderedImage(RenderedImage, AffineTransform)}
   * to perform the final rendering. Only the area of the image specified
   * by <code>areaOfInterest</code> is rendered.
   *
   * @param image the renderable image to be rendered
   * @param xform the transform from image space to user space
   */
  private void drawRenderableImageImpl(RenderableImage image,
                                       AffineTransform xform,
                                       Rectangle areaOfInterest)
  {
    // TODO: Maybe make more clever usage of a RenderContext here.
    RenderedImage rendered = image.createDefaultRendering();
    drawRenderedImageImpl(rendered, xform, areaOfInterest);
  }

  /**
   * Draws the specified string at the specified location.
   *
   * @param text the string to draw
   * @param x the x location, relative to the bounding rectangle of the text
   * @param y the y location, relative to the bounding rectangle of the text
   */
  public void drawString(String text, int x, int y)
  {
    GlyphVector gv;
    synchronized (searchTextKey)
      {
        TextCacheKey tck = searchTextKey;
        FontRenderContext frc = getFontRenderContext();
        tck.setString(text);
        tck.setFont(font);
        tck.setFontRenderContext(frc);
        if (gvCache.containsKey(tck))
          {
            gv = gvCache.get(tck);
          }
        else
          {
            gv = font.createGlyphVector(frc, text.toCharArray());
            gvCache.put(new TextCacheKey(text, font, frc), gv);
          }
      }
    drawGlyphVector(gv, x, y);
  }

  /**
   * Draws the specified string at the specified location.
   *
   * @param text the string to draw
   * @param x the x location, relative to the bounding rectangle of the text
   * @param y the y location, relative to the bounding rectangle of the text
   */
  public void drawString(String text, float x, float y)
  {
    FontRenderContext ctx = getFontRenderContext();
    GlyphVector gv = font.createGlyphVector(ctx, text.toCharArray());
    drawGlyphVector(gv, x, y);
  }

  /**
   * Draws the specified string (as AttributedCharacterIterator) at the
   * specified location.
   *
   * @param iterator the string to draw
   * @param x the x location, relative to the bounding rectangle of the text
   * @param y the y location, relative to the bounding rectangle of the text
   */
  public void drawString(AttributedCharacterIterator iterator, int x, int y)
  {
    FontRenderContext ctx = getFontRenderContext();
    GlyphVector gv = font.createGlyphVector(ctx, iterator);
    drawGlyphVector(gv, x, y);
  }

  /**
   * Draws the specified string (as AttributedCharacterIterator) at the
   * specified location.
   *
   * @param iterator the string to draw
   * @param x the x location, relative to the bounding rectangle of the text
   * @param y the y location, relative to the bounding rectangle of the text
   */
  public void drawString(AttributedCharacterIterator iterator, float x, float y)
  {
    FontRenderContext ctx = getFontRenderContext();
    GlyphVector gv = font.createGlyphVector(ctx, iterator);
    drawGlyphVector(gv, x, y);
  }

  /**
   * Fills the specified shape with the current foreground.
   *
   * @param shape the shape to fill
   */
  public void fill(Shape shape)
  {
    fillShape(shape, false);
  }

  public boolean hit(Rectangle rect, Shape text, boolean onStroke)
  {
    // FIXME: Implement this.
    throw new UnsupportedOperationException("Not yet implemented");
  }

  /**
   * Sets the composite.
   *
   * @param comp the composite to set
   */
  public void setComposite(Composite comp)
  {
    if (! (comp instanceof AlphaComposite))
      {
        // FIXME: this check is only required "if this Graphics2D
        // context is drawing to a Component on the display screen".
        SecurityManager sm = System.getSecurityManager();
        if (sm != null)
          sm.checkPermission(new AWTPermission("readDisplayPixels"));
      }

    composite = comp;
    if (! (comp.equals(AlphaComposite.SrcOver)))
      isOptimized = false;
    else
      updateOptimization();
  }

  /**
   * Sets the current foreground.
   *
   * @param p the foreground to set.
   */
  public void setPaint(Paint p)
  {
    if (p != null)
      {
        paint = p;

        if (! (paint instanceof Color))
          {
            isOptimized = false;
          }
        else
          {
            this.foreground = (Color) paint;
            isForegroundColorNull = false;
            updateOptimization();
          }
      }
    else
      {
        this.foreground = Color.BLACK;
        isForegroundColorNull = true;
      }

    // free resources if needed, then put the paint context to null
    if (this.paintContext != null)
      this.paintContext.dispose();

    this.paintContext = null;
  }

  /**
   * Sets the stroke for this graphics object.
   *
   * @param s the stroke to set
   */
  public void setStroke(Stroke s)
  {
    stroke = s;
    if (! stroke.equals(new BasicStroke()))
      isOptimized = false;
    else
      updateOptimization();
  }

  /**
   * Sets the specified rendering hint.
   *
   * @param hintKey the key of the rendering hint
   * @param hintValue the value
   */
  public void setRenderingHint(Key hintKey, Object hintValue)
  {
    renderingHints.put(hintKey, hintValue);
  }

  /**
   * Returns the rendering hint for the specified key.
   *
   * @param hintKey the rendering hint key
   *
   * @return the rendering hint for the specified key
   */
  public Object getRenderingHint(Key hintKey)
  {
    return renderingHints.get(hintKey);
  }

  /**
   * Sets the specified rendering hints.
   *
   * @param hints the rendering hints to set
   */
  public void setRenderingHints(Map hints)
  {
    renderingHints.clear();
    renderingHints.putAll(hints);
  }

  /**
   * Adds the specified rendering hints.
   *
   * @param hints the rendering hints to add
   */
  public void addRenderingHints(Map hints)
  {
    renderingHints.putAll(hints);
  }

  /**
   * Returns the current rendering hints.
   *
   * @return the current rendering hints
   */
  public RenderingHints getRenderingHints()
  {
    return (RenderingHints) renderingHints.clone();
  }

  /**
   * Translates the coordinate system by (x, y).
   *
   * @param x the translation X coordinate
   * @param y the translation Y coordinate
   */
  public void translate(int x, int y)
  {
    transform.translate(x, y);

    // Update the clip. We special-case rectangular clips here, because they
    // are so common (e.g. in Swing).
    if (clip != null)
      {
        if (clip instanceof Rectangle)
          {
            Rectangle r = (Rectangle) clip;
            r.x -= x;
            r.y -= y;
            setClip(r);
          }
        else
          {
            AffineTransform clipTransform = new AffineTransform();
            clipTransform.translate(-x, -y);
            updateClip(clipTransform);
          }
      }
  }

  /**
   * Translates the coordinate system by (tx, ty).
   *
   * @param tx the translation X coordinate
   * @param ty the translation Y coordinate
   */
  public void translate(double tx, double ty)
  {
    transform.translate(tx, ty);

    // Update the clip. We special-case rectangular clips here, because they
    // are so common (e.g. in Swing).
    if (clip != null)
      {
        if (clip instanceof Rectangle)
          {
            Rectangle r = (Rectangle) clip;
            r.x -= tx;
            r.y -= ty;
          }
        else
          {
            AffineTransform clipTransform = new AffineTransform();
            clipTransform.translate(-tx, -ty);
            updateClip(clipTransform);
          }
      }
  }

  /**
   * Rotates the coordinate system by <code>theta</code> degrees.
   *
   * @param theta the angle be which to rotate the coordinate system
   */
  public void rotate(double theta)
  {
    transform.rotate(theta);
    if (clip != null)
      {
        AffineTransform clipTransform = new AffineTransform();
        clipTransform.rotate(-theta);
        updateClip(clipTransform);
      }
    updateOptimization();
  }

  /**
   * Rotates the coordinate system by <code>theta</code> around the point
   * (x, y).
   *
   * @param theta the angle by which to rotate the coordinate system
   * @param x the point around which to rotate, X coordinate
   * @param y the point around which to rotate, Y coordinate
   */
  public void rotate(double theta, double x, double y)
  {
    transform.rotate(theta, x, y);
    if (clip != null)
      {
        AffineTransform clipTransform = new AffineTransform();
        clipTransform.rotate(-theta, x, y);
        updateClip(clipTransform);
      }
    updateOptimization();
  }

  /**
   * Scales the coordinate system by the factors <code>scaleX</code> and
   * <code>scaleY</code>.
   *
   * @param scaleX the factor by which to scale the X axis
   * @param scaleY the factor by which to scale the Y axis
   */
  public void scale(double scaleX, double scaleY)
  {
    transform.scale(scaleX, scaleY);
    if (clip != null)
      {
        AffineTransform clipTransform = new AffineTransform();
        clipTransform.scale(1 / scaleX, 1 / scaleY);
        updateClip(clipTransform);
      }
    updateOptimization();
  }

  /**
   * Shears the coordinate system by <code>shearX</code> and
   * <code>shearY</code>.
   *
   * @param shearX the X shearing
   * @param shearY the Y shearing
   */
  public void shear(double shearX, double shearY)
  {
    transform.shear(shearX, shearY);
    if (clip != null)
      {
        AffineTransform clipTransform = new AffineTransform();
        clipTransform.shear(-shearX, -shearY);
        updateClip(clipTransform);
      }
    updateOptimization();
  }

  /**
   * Transforms the coordinate system using the specified transform
   * <code>t</code>.
   *
   * @param t the transform
   */
  public void transform(AffineTransform t)
  {
    transform.concatenate(t);
    try
      {
        AffineTransform clipTransform = t.createInverse();
        updateClip(clipTransform);
      }
    catch (NoninvertibleTransformException ex)
      {
        // TODO: How can we deal properly with this?
        ex.printStackTrace();
      }
    updateOptimization();
  }

  /**
   * Sets the transformation for this Graphics object.
   *
   * @param t the transformation to set
   */
  public void setTransform(AffineTransform t)
  {
    // Transform clip into target space using the old transform.
    updateClip(transform);
    transform.setTransform(t);
    // Transform the clip back into user space using the inverse new transform.
    try
      {
        updateClip(transform.createInverse());
      }
    catch (NoninvertibleTransformException ex)
      {
        // TODO: How can we deal properly with this?
        ex.printStackTrace();
      }
    updateOptimization();
  }

  /**
   * Returns the transformation of this coordinate system.
   *
   * @return the transformation of this coordinate system
   */
  public AffineTransform getTransform()
  {
    return (AffineTransform) transform.clone();
  }

  /**
   * Returns the current foreground.
   *
   * @return the current foreground
   */
  public Paint getPaint()
  {
    return paint;
  }


  /**
   * Returns the current composite.
   *
   * @return the current composite
   */
  public Composite getComposite()
  {
    return composite;
  }

  /**
   * Sets the current background.
   *
   * @param color the background to set.
   */
  public void setBackground(Color color)
  {
    background = color;
  }

  /**
   * Returns the current background.
   *
   * @return the current background
   */
  public Color getBackground()
  {
    return background;
  }

  /**
   * Returns the current stroke.
   *
   * @return the current stroke
   */
  public Stroke getStroke()
  {
    return stroke;
  }

  /**
   * Intersects the clip of this graphics object with the specified clip.
   *
   * @param s the clip with which the current clip should be intersected
   */
  public void clip(Shape s)
  {
    // Initialize clip if not already present.
    if (clip == null)
      setClip(s);

    // This is so common, let's optimize this.
    else if (clip instanceof Rectangle && s instanceof Rectangle)
      {
        Rectangle clipRect = (Rectangle) clip;
        Rectangle r = (Rectangle) s;
        computeIntersection(r.x, r.y, r.width, r.height, clipRect);
        // Call setClip so that subclasses get notified.
        setClip(clipRect);
      }
   else
     {
       Area current;
       if (clip instanceof Area)
         current = (Area) clip;
       else
         current = new Area(clip);

       Area intersect;
       if (s instanceof Area)
         intersect = (Area) s;
       else
         intersect = new Area(s);

       current.intersect(intersect);
       clip = current;
       isOptimized = false;
       // Call setClip so that subclasses get notified.
       setClip(clip);
     }
  }

  public FontRenderContext getFontRenderContext()
  {
    // Protect our own transform from beeing modified.
    AffineTransform tf = new AffineTransform(transform);
    // TODO: Determine antialias and fractionalmetrics parameters correctly.
    return new FontRenderContext(tf, false, true);
  }

  /**
   * Draws the specified glyph vector at the specified location.
   *
   * @param gv the glyph vector to draw
   * @param x the location, x coordinate
   * @param y the location, y coordinate
   */
  public void drawGlyphVector(GlyphVector gv, float x, float y)
  {
    translate(x, y);
    fillShape(gv.getOutline(), true);
    translate(-x, -y);
  }

  /**
   * Creates a copy of this graphics object.
   *
   * @return a copy of this graphics object
   */
  public Graphics create()
  {
    AbstractGraphics2D copy = (AbstractGraphics2D) clone();
    return copy;
  }

  /**
   * Creates and returns a copy of this Graphics object. This should
   * be overridden by subclasses if additional state must be handled when
   * cloning. This is called by {@link #create()}.
   *
   * @return a copy of this Graphics object
   */
  protected Object clone()
  {
    try
      {
        AbstractGraphics2D copy = (AbstractGraphics2D) super.clone();
        // Copy the clip. If it's a Rectangle, preserve that for optimization.
        if (clip instanceof Rectangle)
          copy.clip = new Rectangle((Rectangle) clip);
        else if (clip != null)
          copy.clip = new GeneralPath(clip);
        else
          copy.clip = null;

        copy.renderingHints = new RenderingHints(null);
        copy.renderingHints.putAll(renderingHints);
        copy.transform = new AffineTransform(transform);
        // The remaining state is inmmutable and doesn't need to be copied.
        return copy;
      }
    catch (CloneNotSupportedException ex)
      {
        AWTError err = new AWTError("Unexpected exception while cloning");
        err.initCause(ex);
        throw err;
      }
  }

  /**
   * Returns the current foreground.
   */
  public Color getColor()
  {
    if (isForegroundColorNull)
      return null;

    return this.foreground;
  }

  /**
   * Sets the current foreground.
   *
   * @param color the foreground to set
   */
  public void setColor(Color color)
  {
    this.setPaint(color);
  }

  public void setPaintMode()
  {
    // FIXME: Implement this.
    throw new UnsupportedOperationException("Not yet implemented");
  }

  public void setXORMode(Color color)
  {
    // FIXME: Implement this.
    throw new UnsupportedOperationException("Not yet implemented");
  }

  /**
   * Returns the current font.
   *
   * @return the current font
   */
  public Font getFont()
  {
    return font;
  }

  /**
   * Sets the font on this graphics object. When <code>f == null</code>, the
   * current setting is not changed.
   *
   * @param f the font to set
   */
  public void setFont(Font f)
  {
    if (f != null)
      font = f;
  }

  /**
   * Returns the font metrics for the specified font.
   *
   * @param font the font for which to fetch the font metrics
   *
   * @return the font metrics for the specified font
   */
  public FontMetrics getFontMetrics(Font font)
  {
    return Toolkit.getDefaultToolkit().getFontMetrics(font);
  }

  /**
   * Returns the bounds of the current clip.
   *
   * @return the bounds of the current clip
   */
  public Rectangle getClipBounds()
  {
    Rectangle b = null;
    if (clip != null)
      b = clip.getBounds();
    return b;
  }

  /**
   * Intersects the current clipping region with the specified rectangle.
   *
   * @param x the x coordinate of the rectangle
   * @param y the y coordinate of the rectangle
   * @param width the width of the rectangle
   * @param height the height of the rectangle
   */
  public void clipRect(int x, int y, int width, int height)
  {
    clip(new Rectangle(x, y, width, height));
  }

  /**
   * Sets the clip to the specified rectangle.
   *
   * @param x the x coordinate of the clip rectangle
   * @param y the y coordinate of the clip rectangle
   * @param width the width of the clip rectangle
   * @param height the height of the clip rectangle
   */
  public void setClip(int x, int y, int width, int height)
  {
    setClip(new Rectangle(x, y, width, height));
  }

  /**
   * Returns the current clip.
   *
   * @return the current clip
   */
  public Shape getClip()
  {
    return clip;
  }

  /**
   * Sets the current clipping area to <code>clip</code>.
   *
   * @param c the clip to set
   */
  public void setClip(Shape c)
  {
    clip = c;
    if (! (clip instanceof Rectangle))
      isOptimized = false;
    else
      updateOptimization();
  }

  public void copyArea(int x, int y, int width, int height, int dx, int dy)
  {
    if (isOptimized)
      rawCopyArea(x, y, width, height, dx, dy);
    else
      copyAreaImpl(x, y, width, height, dx, dy);
  }

  /**
   * Draws a line from (x1, y1) to (x2, y2).
   *
   * This implementation transforms the coordinates and forwards the call to
   * {@link #rawDrawLine}.
   */
  public void drawLine(int x1, int y1, int x2, int y2)
  {
    if (isOptimized)
      {
        int tx = (int) transform.getTranslateX();
        int ty = (int) transform.getTranslateY();
        rawDrawLine(x1 + tx, y1 + ty, x2 + tx, y2 + ty);
      }
    else
      {
        ShapeCache sc = shapeCache;
        if (sc.line == null)
          sc.line = new Line2D.Float();
        sc.line.setLine(x1, y1, x2, y2);
        draw(sc.line);
      }
  }

  public void drawRect(int x, int y, int w, int h)
  {
    if (isOptimized)
      {
        int tx = (int) transform.getTranslateX();
        int ty = (int) transform.getTranslateY();
        rawDrawRect(x + tx, y + ty, w, h);
      }
    else
      {
        ShapeCache sc = shapeCache;
        if (sc.rect == null)
          sc.rect = new Rectangle();
        sc.rect.setBounds(x, y, w, h);
        draw(sc.rect);
      }
  }

  /**
   * Fills a rectangle with the current paint.
   *
   * @param x the upper left corner, X coordinate
   * @param y the upper left corner, Y coordinate
   * @param width the width of the rectangle
   * @param height the height of the rectangle
   */
  public void fillRect(int x, int y, int width, int height)
  {
    if (isOptimized)
      {
        rawFillRect(x + (int) transform.getTranslateX(),
                    y + (int) transform.getTranslateY(), width, height);
      }
    else
      {
        ShapeCache sc = shapeCache;
        if (sc.rect == null)
          sc.rect = new Rectangle();
        sc.rect.setBounds(x, y, width, height);
        fill(sc.rect);
      }
  }

  /**
   * Fills a rectangle with the current background color.
   *
   * This implementation temporarily sets the foreground color to the
   * background and forwards the call to {@link #fillRect(int, int, int, int)}.
   *
   * @param x the upper left corner, X coordinate
   * @param y the upper left corner, Y coordinate
   * @param width the width of the rectangle
   * @param height the height of the rectangle
   */
  public void clearRect(int x, int y, int width, int height)
  {
    if (isOptimized)
      rawClearRect(x, y, width, height);
    else
      {
        Paint savedForeground = getPaint();
        setPaint(getBackground());
        fillRect(x, y, width, height);
        setPaint(savedForeground);
      }
  }

  /**
   * Draws a rounded rectangle.
   *
   * @param x the x coordinate of the rectangle
   * @param y the y coordinate of the rectangle
   * @param width the width of the rectangle
   * @param height the height of the rectangle
   * @param arcWidth the width of the arcs
   * @param arcHeight the height of the arcs
   */
  public void drawRoundRect(int x, int y, int width, int height, int arcWidth,
                            int arcHeight)
  {
    ShapeCache sc = shapeCache;
    if (sc.roundRect == null)
      sc.roundRect = new RoundRectangle2D.Float();
    sc.roundRect.setRoundRect(x, y, width, height, arcWidth, arcHeight);
    draw(sc.roundRect);
  }

  /**
   * Fills a rounded rectangle.
   *
   * @param x the x coordinate of the rectangle
   * @param y the y coordinate of the rectangle
   * @param width the width of the rectangle
   * @param height the height of the rectangle
   * @param arcWidth the width of the arcs
   * @param arcHeight the height of the arcs
   */
  public void fillRoundRect(int x, int y, int width, int height, int arcWidth,
                            int arcHeight)
  {
    ShapeCache sc = shapeCache;
    if (sc.roundRect == null)
      sc.roundRect = new RoundRectangle2D.Float();
    sc.roundRect.setRoundRect(x, y, width, height, arcWidth, arcHeight);
    fill(sc.roundRect);
  }

  /**
   * Draws the outline of an oval.
   *
   * @param x the upper left corner of the bounding rectangle of the ellipse
   * @param y the upper left corner of the bounding rectangle of the ellipse
   * @param width the width of the ellipse
   * @param height the height of the ellipse
   */
  public void drawOval(int x, int y, int width, int height)
  {
    ShapeCache sc = shapeCache;
    if (sc.ellipse == null)
      sc.ellipse = new Ellipse2D.Float();
    sc.ellipse.setFrame(x, y, width, height);
    draw(sc.ellipse);
  }

  /**
   * Fills an oval.
   *
   * @param x the upper left corner of the bounding rectangle of the ellipse
   * @param y the upper left corner of the bounding rectangle of the ellipse
   * @param width the width of the ellipse
   * @param height the height of the ellipse
   */
  public void fillOval(int x, int y, int width, int height)
  {
    ShapeCache sc = shapeCache;
    if (sc.ellipse == null)
      sc.ellipse = new Ellipse2D.Float();
    sc.ellipse.setFrame(x, y, width, height);
    fill(sc.ellipse);
  }

  /**
   * Draws an arc.
   */
  public void drawArc(int x, int y, int width, int height, int arcStart,
                      int arcAngle)
  {
    ShapeCache sc = shapeCache;
    if (sc.arc == null)
      sc.arc = new Arc2D.Float();
    sc.arc.setArc(x, y, width, height, arcStart, arcAngle, Arc2D.OPEN);
    draw(sc.arc);
  }

  /**
   * Fills an arc.
   */
  public void fillArc(int x, int y, int width, int height, int arcStart,
                      int arcAngle)
  {
    ShapeCache sc = shapeCache;
    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)
  {
    ShapeCache sc = shapeCache;
    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 = shapeCache;
    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 = shapeCache;
    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 {@link #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
   */
  public boolean drawImage(Image image, int x, int y, ImageObserver observer)
  {
    boolean ret;
    if (isOptimized)
      {
        ret = rawDrawImage(image, x + (int) transform.getTranslateX(),
                           y + (int) transform.getTranslateY(), observer);
      }
    else
      {
        AffineTransform t = new AffineTransform();
        t.translate(x, y);
        ret = drawImage(image, t, observer);
      }
    return ret;
  }

  /**
   * Draws the specified image at the specified location. The image
   * is scaled to the specified width and height. This forwards
   * to {@link #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 width the target width of the image
   * @param height the target height of the image
   * @param observer the image observer to receive notification
   */
  public boolean drawImage(Image image, int x, int y, int width, int height,
                           ImageObserver observer)
  {
    AffineTransform t = new AffineTransform();
    int imWidth = image.getWidth(observer);
    int imHeight = image.getHeight(observer);
    if (imWidth == width && imHeight == height)
      {
        // No need to scale, fall back to non-scaling loops.
        return drawImage(image, x, y, observer);
      }
    else
      {
        Image scaled = prepareImage(image, width, height);
        // Ideally, this should notify the observer about the scaling progress.
        return drawImage(scaled, x, y, observer);
      }
  }

  /**
   * Draws the specified image at the specified location. This forwards
   * to {@link #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 bgcolor the background color to use for transparent pixels
   * @param observer the image observer to receive notification
   */
  public boolean drawImage(Image image, int x, int y, Color bgcolor,
                           ImageObserver observer)
  {
    AffineTransform t = new AffineTransform();
    t.translate(x, y);
    // TODO: Somehow implement the background option.
    return drawImage(image, t, observer);
  }

  /**
   * Draws the specified image at the specified location. The image
   * is scaled to the specified width and height. This forwards
   * to {@link #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 width the target width of the image
   * @param height the target height of the image
   * @param bgcolor the background color to use for transparent pixels
   * @param observer the image observer to receive notification
   */
  public boolean drawImage(Image image, int x, int y, int width, int height,
                           Color bgcolor, ImageObserver observer)
  {
    AffineTransform t = new AffineTransform();
    t.translate(x, y);
    double scaleX = (double) image.getWidth(observer) / (double) width;
    double scaleY = (double) image.getHeight(observer) / (double) height;
    t.scale(scaleX, scaleY);
    // TODO: Somehow implement the background option.
    return drawImage(image, t, observer);
  }

  /**
   * Draws an image fragment to a rectangular area of the target.
   *
   * @param image the image to render
   * @param dx1 the first corner of the destination rectangle
   * @param dy1 the first corner of the destination rectangle
   * @param dx2 the second corner of the destination rectangle
   * @param dy2 the second corner of the destination rectangle
   * @param sx1 the first corner of the source rectangle
   * @param sy1 the first corner of the source rectangle
   * @param sx2 the second corner of the source rectangle
   * @param sy2 the second corner of the source rectangle
   * @param observer the image observer to be notified
   */
  public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
                           int sx1, int sy1, int sx2, int sy2,
                           ImageObserver observer)
  {
    int sx = Math.min(sx1, sx1);
    int sy = Math.min(sy1, sy2);
    int sw = Math.abs(sx1 - sx2);
    int sh = Math.abs(sy1 - sy2);
    int dx = Math.min(dx1, dx1);
    int dy = Math.min(dy1, dy2);
    int dw = Math.abs(dx1 - dx2);
    int dh = Math.abs(dy1 - dy2);

    AffineTransform t = new AffineTransform();
    t.translate(sx - dx, sy - dy);
    double scaleX = (double) sw / (double) dw;
    double scaleY = (double) sh / (double) dh;
    t.scale(scaleX, scaleY);
    Rectangle areaOfInterest = new Rectangle(sx, sy, sw, sh);
    return drawImageImpl(image, t, observer, areaOfInterest);
  }

  /**
   * Draws an image fragment to a rectangular area of the target.
   *
   * @param image the image to render
   * @param dx1 the first corner of the destination rectangle
   * @param dy1 the first corner of the destination rectangle
   * @param dx2 the second corner of the destination rectangle
   * @param dy2 the second corner of the destination rectangle
   * @param sx1 the first corner of the source rectangle
   * @param sy1 the first corner of the source rectangle
   * @param sx2 the second corner of the source rectangle
   * @param sy2 the second corner of the source rectangle
   * @param bgcolor the background color to use for transparent pixels
   * @param observer the image observer to be notified
   */
  public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
                           int sx1, int sy1, int sx2, int sy2, Color bgcolor,
                           ImageObserver observer)
  {
    // FIXME: Do something with bgcolor.
    return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
  }

  /**
   * Disposes this graphics object.
   */
  public void dispose()
  {
    // Nothing special to do here.
  }

  /**
   * Fills the specified shape. Override this if your backend can efficiently
   * fill shapes. This is possible on many systems via a polygon fill
   * 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 for text rendering.
        antialias = v == RenderingHints.VALUE_TEXT_ANTIALIAS_ON
                    || (v == RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT
                         && DEFAULT_TEXT_AA);
      }
    else
      {
        Object v = renderingHints.get(RenderingHints.KEY_ANTIALIASING);
        antialias = (v == RenderingHints.VALUE_ANTIALIAS_ON);
      }
    ScanlineConverter sc = getScanlineConverter();
    int resolution = 0;
    int yRes = 0;
    if (antialias)
      {
        // Adjust resolution according to rendering hints.
        resolution = 2;
        yRes = 4;
      }
    sc.renderShape(this, s, clip, transform, resolution, yRes, renderingHints);
    freeScanlineConverter(sc);
  }

  /**
   * Returns the color model of this Graphics object.
   *
   * @return the color model of this Graphics object
   */
  protected abstract ColorModel getColorModel();

  /**
   * Returns the bounds of the target.
   *
   * @return the bounds of the target
   */
  protected abstract Rectangle getDeviceBounds();

  /**
   * 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)
  {
    ShapeCache sc = shapeCache;
    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)
  {
    ShapeCache sc = shapeCache;
    if (sc.rect == null)
      sc.rect = new Rectangle();
    sc.rect.setBounds(x, y, w, h);
    draw(sc.rect);
  }

  /**
   * Clears a rectangle 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 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 rawClearRect(int x, int y, int w, int h)
  {
    Paint savedForeground = getPaint();
    setPaint(getBackground());
    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)
  {
    ShapeCache sc = shapeCache;
    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)
  {
    AffineTransform t = new AffineTransform();
    t.translate(x, y);
    return drawImage(image, t, obs);
  }

  /**
   * Copies a rectangular region to another location.
   *
   * @param x the upper left corner, X coordinate
   * @param y the upper left corner, Y coordinate
   * @param w the width
   * @param h the height
   * @param dx
   * @param dy
   */
  protected void rawCopyArea(int x, int y, int w, int h, int dx, int dy)
  {
    copyAreaImpl(x, y, w, h, dx, dy);
  }

  // Private implementation methods.

  /**
   * Copies a rectangular area of the target raster to a different location.
   */
  private void copyAreaImpl(int x, int y, int w, int h, int dx, int dy)
  {
    // FIXME: Implement this properly.
    throw new UnsupportedOperationException("Not implemented yet.");
  }

  /**
   * Paints a scanline between x0 and x1. Override this when your backend
   * can efficiently draw/fill horizontal lines.
   *
   * @param x0 the left offset
   * @param x1 the right offset
   * @param y the scanline
   */
  public void renderScanline(int y, ScanlineCoverage c)
  {
    PaintContext pCtx = getPaintContext();

    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.Iterator iter = c.iterate();
    while (iter.hasNext())
      {
        ScanlineCoverage.Range range = iter.next();
        coverageAlpha = range.getCoverage() / maxCoverage;
        if (coverageAlpha < 1.0)
          {
            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);
              }
          }
      }
    ColorModel paintColorModel = pCtx.getColorModel();
    CompositeContext cCtx = composite.createContext(paintColorModel,
                                                    getColorModel(),
                                                    renderingHints);
    WritableRaster raster = getDestinationRaster();
    WritableRaster targetChild = raster.createWritableTranslatedChild(-x0, -y);

    cCtx.compose(paintRaster, targetChild, targetChild);
    updateRaster(raster, 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.
   */
  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
   * {@link #updateRaster}.
   *
   * @return the destination raster
   */
  protected WritableRaster getDestinationRaster()
  {
    // TODO: Ideally we would fetch the xdrawable's surface pixels for
    // initialization of the raster.
    Rectangle db = getDeviceBounds();
    if (destinationRaster == null)
      {
        int[] bandMasks = new int[]{ 0xFF0000, 0xFF00, 0xFF };
        destinationRaster = Raster.createPackedRaster(DataBuffer.TYPE_INT,
                                                      db.width, db.height,
                                                      bandMasks, null);
        // Initialize raster with white.
        int x0 = destinationRaster.getMinX();
        int x1 = destinationRaster.getWidth() + x0;
        int y0 = destinationRaster.getMinY();
        int y1 = destinationRaster.getHeight() + y0;
        int numBands = destinationRaster.getNumBands();
        for (int y = y0; y < y1; y++)
          {
            for (int x = x0; x < x1; x++)
              {
                for (int b = 0; b < numBands; b++)
                  destinationRaster.setSample(x, y, b, 255);
              }
          }
      }
    return destinationRaster;
  }

  /**
   * Notifies the backend that the raster has changed in the specified
   * rectangular area. The raster that is provided in this method is always
   * the same as the one returned in {@link #getDestinationRaster}.
   * Backends that reflect changes to this raster directly don't need to do
   * anything here.
   *
   * @param raster the updated raster, identical to the raster returned
   *        by {@link #getDestinationRaster()}
   * @param x the upper left corner of the updated region, X coordinate
   * @param y the upper lef corner of the updated region, Y coordinate
   * @param w the width of the updated region
   * @param h the height of the updated region
   */
  protected void updateRaster(Raster raster, int x, int y, int w, int h)
  {
    // Nothing to do here. Backends that need to update their surface
    // to reflect the change should override this method.
  }

  // Some helper methods.

  /**
   * Helper method to check and update the optimization conditions.
   */
  private void updateOptimization()
  {
    int transformType = transform.getType();
    boolean optimizedTransform = false;
    if (transformType == AffineTransform.TYPE_IDENTITY
        || transformType == AffineTransform.TYPE_TRANSLATION)
      optimizedTransform = true;

    boolean optimizedClip = (clip == null || clip instanceof Rectangle);
    isOptimized = optimizedClip
                  && optimizedTransform && paint instanceof Color
                  && composite == AlphaComposite.SrcOver
                  && stroke.equals(new BasicStroke());
  }

  /**
   * Calculates the intersection of two rectangles. The result is stored
   * in <code>rect</code>. This is basically the same
   * like {@link Rectangle#intersection(Rectangle)}, only that it does not
   * create new Rectangle instances. The tradeoff is that you loose any data in
   * <code>rect</code>.
   *
   * @param x upper-left x coodinate of first rectangle
   * @param y upper-left y coodinate of first rectangle
   * @param w width of first rectangle
   * @param h height of first rectangle
   * @param rect a Rectangle object of the second rectangle
   *
   * @throws NullPointerException if rect is null
   *
   * @return a rectangle corresponding to the intersection of the
   *         two rectangles. An empty rectangle is returned if the rectangles
   *         do not overlap
   */
  private static Rectangle computeIntersection(int x, int y, int w, int h,
                                               Rectangle rect)
  {
    int x2 = rect.x;
    int y2 = rect.y;
    int w2 = rect.width;
    int h2 = rect.height;

    int dx = (x > x2) ? x : x2;
    int dy = (y > y2) ? y : y2;
    int dw = (x + w < x2 + w2) ? (x + w - dx) : (x2 + w2 - dx);
    int dh = (y + h < y2 + h2) ? (y + h - dy) : (y2 + h2 - dy);

    if (dw >= 0 && dh >= 0)
      rect.setBounds(dx, dy, dw, dh);
    else
      rect.setBounds(0, 0, 0, 0);

    return rect;
  }

  /**
   * Helper method to transform the clip. This is called by the various
   * transformation-manipulation methods to update the clip (which is in
   * userspace) accordingly.
   *
   * The transform usually is the inverse transform that was applied to the
   * graphics object.
   *
   * @param t the transform to apply to the clip
   */
  private void updateClip(AffineTransform t)
  {
    if (! (clip instanceof GeneralPath))
      clip = new GeneralPath(clip);

    GeneralPath p = (GeneralPath) clip;
    p.transform(t);
  }

  /**
   * Returns a free scanline converter from the pool.
   *
   * @return a scanline converter
   */
  private ScanlineConverter getScanlineConverter()
  {
    synchronized (scanlineConverters)
      {
        ScanlineConverter sc;
        if (scanlineConverters.size() > 0)
          {
            sc = scanlineConverters.removeFirst();
          }
        else
          {
            sc = new ScanlineConverter();
          }
        return sc;
      }
  }

  /**
   * Puts a scanline converter back in the pool.
   *
   * @param sc
   */
  private void freeScanlineConverter(ScanlineConverter sc)
  {
    synchronized (scanlineConverters)
      {
        scanlineConverters.addLast(sc);
      }
  }

  private PaintContext getPaintContext()
  {
    if (this.paintContext == null)
      {
        this.paintContext =
          this.foreground.createContext(getColorModel(),
                                        getDeviceBounds(),
                                        getClipBounds(),
                                        getTransform(),
                                        getRenderingHints());
      }

    return this.paintContext;
  }

  /**
   * Scales an image to the specified width and height. This should also
   * be used to implement
   * {@link Toolkit#prepareImage(Image, int, int, ImageObserver)}.
   * This uses {@link Toolkit#createImage(ImageProducer)} to create the actual
   * image.
   *
   * @param image the image to prepare
   * @param w the width
   * @param h the height
   *
   * @return the scaled image
   */
  public static Image prepareImage(Image image, int w, int h)
  {
    // Try to find cached scaled image.
    HashMap<Dimension,Image> scaledTable = imageCache.get(image);
    Dimension size = new Dimension(w, h);
    Image scaled = null;
    if (scaledTable != null)
      {
        scaled = scaledTable.get(size);
      }
    if (scaled == null)
      {
        // No cached scaled image. Start scaling image now.
        ImageProducer source = image.getSource();
        ReplicateScaleFilter scaler = new ReplicateScaleFilter(w, h);
        FilteredImageSource filteredSource =
          new FilteredImageSource(source, scaler);
        // Ideally, this should asynchronously scale the image.
        Image scaledImage =
          Toolkit.getDefaultToolkit().createImage(filteredSource);
        scaled = scaledImage;
        // Put scaled image in cache.
        if (scaledTable == null)
          {
            scaledTable = new HashMap<Dimension,Image>();
            imageCache.put(image, scaledTable);
          }
        scaledTable.put(size, scaledImage);
      }
    return scaled;
  }

}
