/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $Id$ */

package org.apache.xmlgraphics.java2d.ps;

//Java
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
/* java.awt.Font is not imported to avoid confusion with 
      other classes called "Font" */ 
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.TexturePaint;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.io.IOException;

import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
import org.apache.xmlgraphics.java2d.GraphicContext;
import org.apache.xmlgraphics.java2d.StrokingTextHandler;
import org.apache.xmlgraphics.java2d.TextHandler;
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.xmlgraphics.ps.PSImageUtils;

/**
 * This is a concrete implementation of <tt>AbstractGraphics2D</tt> (and
 * therefore of <tt>Graphics2D</tt>) which is able to generate PostScript
 * code.
 *
 * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
 * @version $Id$
 * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D
 */
public class PSGraphics2D extends AbstractGraphics2D {

    private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform();
    
    private static final boolean DEBUG = false;
    
    protected PSGraphics2D rootG2D;
    
    /** the PostScript generator being created */
    protected PSGenerator gen;

    private boolean clippingDisabled = false;

    /** Fallback text handler */
    protected TextHandler fallbackTextHandler = new StrokingTextHandler(this);
    
    /** Custom text handler */
    protected TextHandler customTextHandler;
    
    /**
     * the current colour for use in svg
     */
    protected Color currentColour = new Color(0, 0, 0);

    /**
     * Create a new Graphics2D that generates PostScript code.
     * @param textAsShapes True if text should be rendered as graphics
     * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D#AbstractGraphics2D(boolean)
     */
    public PSGraphics2D(boolean textAsShapes) {
        super(textAsShapes);
    }

    /**
     * Create a new Graphics2D that generates PostScript code.
     * @param textAsShapes True if text should be rendered as graphics
     * @param gen PostScript generator to use for output
     * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D#AbstractGraphics2D(boolean)
     */
    public PSGraphics2D(boolean textAsShapes, PSGenerator gen) {
        this(textAsShapes);
        setPSGenerator(gen);
    }

    /**
     * Constructor for creating copies
     * @param g parent PostScript Graphics2D
     */
    public PSGraphics2D(PSGraphics2D g) {
        super(g);

        this.rootG2D = (g.rootG2D != null ? g.rootG2D : g);
        setPSGenerator(g.gen);
        this.clippingDisabled = g.clippingDisabled;
        this.fallbackTextHandler = g.fallbackTextHandler;
        this.customTextHandler = g.customTextHandler;
        this.currentColour    = g.currentColour;
    }

    /**
     * Sets the PostScript generator
     * @param gen the PostScript generator
     */
    public void setPSGenerator(PSGenerator gen) {
        this.gen = gen;
    }

    /** @return the PostScript generator used by this instance. */
    public PSGenerator getPSGenerator() {
        return this.gen;
    }

    /**
     * Sets the GraphicContext
     * @param c GraphicContext to use
     */
    public void setGraphicContext(GraphicContext c) {
        gc = c;
        //setPrivateHints();
    }

    /** @return the fallback TextHandler implementation */
    public TextHandler getFallbackTextHandler() {
        return this.fallbackTextHandler;
    }

    /** @return the custom TextHandler implementation */
    public TextHandler getCustomTextHandler() {
        return this.customTextHandler;
    }

    /**
     * Sets a custom TextHandler implementation that is responsible for painting text. The default
     * TextHandler paints all text as shapes. A custom implementation can implement text painting
     * using text painting operators.
     * @param handler the custom TextHandler implementation
     */
    public void setCustomTextHandler(TextHandler handler) {
        this.customTextHandler = handler;
    }
    
    /* TODO Add me back at the right place!!!
    private void setPrivateHints() {
        setRenderingHint(RenderingHintsKeyExt.KEY_AVOID_TILE_PAINTING, 
                RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_ON);
    }*/

    /**
     * Creates a new <code>Graphics</code> object that is
     * a copy of this <code>Graphics</code> object.
     * @return     a new graphics context that is a copy of
     * this graphics context.
     */
    public Graphics create() {
        preparePainting();
        return new PSGraphics2D(this);
    }

    /**
     * Central handler for IOExceptions for this class.
     * @param ioe IOException to handle
     */
    public void handleIOException(IOException ioe) {
        //TODO Surely, there's a better way to do this.
        ioe.printStackTrace();
    }

    /**
     * This method is used by AbstractPSDocumentGraphics2D to prepare a new page if
     * necessary.
     */
    public void preparePainting() {
        //nop, used by AbstractPSDocumentGraphics2D
        if (rootG2D != null) {
            rootG2D.preparePainting();
        }
    }

    /**
     * Draws as much of the specified image as is currently available.
     * The image is drawn with its top-left corner at
     * (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's coordinate
     * space. Transparent pixels in the image do not affect whatever
     * pixels are already there.
     * <p>
     * This method returns immediately in all cases, even if the
     * complete image has not yet been loaded, and it has not been dithered
     * and converted for the current output device.
     * <p>
     * If the image has not yet been completely loaded, then
     * <code>drawImage</code> returns <code>false</code>. As more of
     * the image becomes available, the process that draws the image notifies
     * the specified image observer.
     * @param    img the specified image to be drawn.
     * @param    x   the <i>x</i> coordinate.
     * @param    y   the <i>y</i> coordinate.
     * @param    observer    object to be notified as more of
     * the image is converted.
     * @return True if the image has been fully drawn/loaded
     * @see      java.awt.Image
     * @see      java.awt.image.ImageObserver
     * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
     */
    public boolean drawImage(Image img, int x, int y,
                             ImageObserver observer) {
        preparePainting();
        if (DEBUG) {
            System.out.println("drawImage: " + x + ", " + y + " " + img.getClass().getName());
        }

        final int width = img.getWidth(observer);
        final int height = img.getHeight(observer);
        if (width == -1 || height == -1) {
            return false;
        }

        Dimension size = new Dimension(width, height);
        BufferedImage buf = buildBufferedImage(size);

        java.awt.Graphics2D g = buf.createGraphics();
        g.setComposite(AlphaComposite.SrcOver);
        g.setBackground(new Color(1, 1, 1, 0));
        g.setPaint(new Color(1, 1, 1, 0));
        g.fillRect(0, 0, width, height);
        g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight()));

        if (!g.drawImage(img, 0, 0, observer)) {
            return false;
        }
        g.dispose();

        try {
            AffineTransform at = getTransform();
            gen.saveGraphicsState();
            gen.concatMatrix(at);
            Shape imclip = getClip();
            writeClip(imclip);
            PSImageUtils.renderBitmapImage(buf, 
                x, y, width, height, gen);
            gen.restoreGraphicsState();
        } catch (IOException ioe) {
            handleIOException(ioe);
        }

        return true;
    }

    /**
     * Creates a buffered image.
     * @param size dimensions of the image to be created
     * @return the buffered image
     */
    public BufferedImage buildBufferedImage(Dimension size) {
        return new BufferedImage(size.width, size.height,
                                 BufferedImage.TYPE_INT_ARGB);
    }

    /**
     * Draws as much of the specified image as has already been scaled
     * to fit inside the specified rectangle.
     * <p>
     * The image is drawn inside the specified rectangle of this
     * graphics context's coordinate space, and is scaled if
     * necessary. Transparent pixels do not affect whatever pixels
     * are already there.
     * <p>
     * This method returns immediately in all cases, even if the
     * entire image has not yet been scaled, dithered, and converted
     * for the current output device.
     * If the current output representation is not yet complete, then
     * <code>drawImage</code> returns <code>false</code>. As more of
     * the image becomes available, the process that draws the image notifies
     * the image observer by calling its <code>imageUpdate</code> method.
     * <p>
     * A scaled version of an image will not necessarily be
     * available immediately just because an unscaled version of the
     * image has been constructed for this output device.  Each size of
     * the image may be cached separately and generated from the original
     * data in a separate image production sequence.
     * @param    img    the specified image to be drawn.
     * @param    x      the <i>x</i> coordinate.
     * @param    y      the <i>y</i> coordinate.
     * @param    width  the width of the rectangle.
     * @param    height the height of the rectangle.
     * @param    observer    object to be notified as more of
     * the image is converted.
     * @return   True if the image has been fully loaded/drawn
     * @see      java.awt.Image
     * @see      java.awt.image.ImageObserver
     * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
     */
    public boolean drawImage(Image img, int x, int y, int width, int height,
                             ImageObserver observer) {
        preparePainting();
        System.err.println("NYI: drawImage");
        return true;
    }

    /**
     * Disposes of this graphics context and releases
     * any system resources that it is using.
     * A <code>Graphics</code> object cannot be used after
     * <code>dispose</code>has been called.
     * <p>
     * When a Java program runs, a large number of <code>Graphics</code>
     * objects can be created within a short time frame.
     * Although the finalization process of the garbage collector
     * also disposes of the same system resources, it is preferable
     * to manually free the associated resources by calling this
     * method rather than to rely on a finalization process which
     * may not run to completion for a long period of time.
     * <p>
     * Graphics objects which are provided as arguments to the
     * <code>paint</code> and <code>update</code> methods
     * of components are automatically released by the system when
     * those methods return. For efficiency, programmers should
     * call <code>dispose</code> when finished using
     * a <code>Graphics</code> object only if it was created
     * directly from a component or another <code>Graphics</code> object.
     * @see         java.awt.Graphics#finalize
     * @see         java.awt.Component#paint
     * @see         java.awt.Component#update
     * @see         java.awt.Component#getGraphics
     * @see         java.awt.Graphics#create
     */
    public void dispose() {
        this.gen = null;
        this.fallbackTextHandler = null;
        this.customTextHandler = null;
        this.currentColour = null;
    }

    /**
     * Processes a path iterator generating the nexessary painting operations.
     * @param iter PathIterator to process
     * @throws IOException In case of an I/O problem.
     */
    public void processPathIterator(PathIterator iter) throws IOException {
        double[] vals = new double[6];
        while (!iter.isDone()) {
            int type = iter.currentSegment(vals);
            switch (type) {
            case PathIterator.SEG_CUBICTO:
                gen.writeln(gen.formatDouble(vals[0]) + " "
                                 + gen.formatDouble(vals[1]) + " "
                                 + gen.formatDouble(vals[2]) + " "
                                 + gen.formatDouble(vals[3]) + " "
                                 + gen.formatDouble(vals[4]) + " "
                                 + gen.formatDouble(vals[5])
                                 + " curveto");
                break;
            case PathIterator.SEG_LINETO:
                gen.writeln(gen.formatDouble(vals[0]) + " "
                                 + gen.formatDouble(vals[1])
                                 + " lineto");
                break;
            case PathIterator.SEG_MOVETO:
                gen.writeln(gen.formatDouble(vals[0]) + " "
                                 + gen.formatDouble(vals[1])
                                 + " M");
                break;
            case PathIterator.SEG_QUADTO:
                gen.writeln(gen.formatDouble(vals[0]) + " " 
                          + gen.formatDouble(vals[1]) + " " 
                          + gen.formatDouble(vals[2]) + " " 
                          + gen.formatDouble(vals[3]) + " QUADTO ");
                break;
            case PathIterator.SEG_CLOSE:
                gen.writeln("closepath");
                break;
            default:
                break;
            }
            iter.next();
        }
    }

    /**
     * Strokes the outline of a <code>Shape</code> using the settings of the
     * current <code>Graphics2D</code> context.  The rendering attributes
     * applied include the <code>Clip</code>, <code>Transform</code>,
     * <code>Paint</code>, <code>Composite</code> and
     * <code>Stroke</code> attributes.
     * @param s the <code>Shape</code> to be rendered
     * @see #setStroke
     * @see #setPaint
     * @see java.awt.Graphics#setColor
     * @see #transform
     * @see #setTransform
     * @see #clip
     * @see #setClip
     * @see #setComposite
     */
    public void draw(Shape s) {
        preparePainting();
        try {
            gen.saveGraphicsState();
            
            AffineTransform trans = getTransform();
            boolean newTransform = gen.getCurrentState().checkTransform(trans)
                    && !trans.isIdentity();

            if (newTransform) {
                gen.concatMatrix(trans);
            }
            Shape imclip = getClip();
            writeClip(imclip);
            establishColor(getColor());

            applyPaint(getPaint(), false);
            applyStroke(getStroke());

            gen.writeln("newpath");
            PathIterator iter = s.getPathIterator(IDENTITY_TRANSFORM);
            processPathIterator(iter);
            doDrawing(false, true, false);
            gen.restoreGraphicsState();
        } catch (IOException ioe) {
            handleIOException(ioe);
        }
    }

    /**
     * Establishes a clipping region
     * @param s Shape defining the clipping region
     */
    public void writeClip(Shape s) {
        if (s == null) {
            return;
        }
        if (!this.clippingDisabled) {
            preparePainting();
            try {
                gen.writeln("newpath");
                PathIterator iter = s.getPathIterator(IDENTITY_TRANSFORM);
                processPathIterator(iter);
                // clip area
                gen.writeln("clip");
            } catch (IOException ioe) {
                handleIOException(ioe);
            }
        }
    }

    /**
     * Applies a new Paint object.
     * @param paint Paint object to use
     * @param fill True if to be applied for filling
     */
    protected void applyPaint(Paint paint, boolean fill) {
        preparePainting();
        if (paint instanceof GradientPaint) {
            System.err.println("NYI: Gradient paint");
        } else if (paint instanceof TexturePaint) {
            System.err.println("NYI: texture paint");
        }
    }

    /**
     * Applies a new Stroke object.
     * @param stroke Stroke object to use
     */
    protected void applyStroke(Stroke stroke) {
        preparePainting();
        try {
            if (stroke instanceof BasicStroke) {
                BasicStroke bs = (BasicStroke)stroke;

                float[] da = bs.getDashArray();
                if (da != null) {
                    gen.write("[");
                    for (int count = 0; count < da.length; count++) {
                        gen.write(gen.formatDouble(da[count]));
                        if (count < da.length - 1) {
                            gen.write(" ");
                        }
                    }
                    gen.write("] ");
                    float offset = bs.getDashPhase();
                    gen.writeln(gen.formatDouble(offset) + " setdash");
                }
                int ec = bs.getEndCap();
                switch (ec) {
                case BasicStroke.CAP_BUTT:
                    gen.writeln("0 setlinecap");
                    break;
                case BasicStroke.CAP_ROUND:
                    gen.writeln("1 setlinecap");
                    break;
                case BasicStroke.CAP_SQUARE:
                    gen.writeln("2 setlinecap");
                    break;
                default: System.err.println("Unsupported line cap: " + ec);
                }

                int lj = bs.getLineJoin();
                switch (lj) {
                case BasicStroke.JOIN_MITER:
                    gen.writeln("0 setlinejoin");
                    float ml = bs.getMiterLimit();
                    gen.writeln(gen.formatDouble(ml >= -1 ? ml : 1) + " setmiterlimit");
                    break;
                case BasicStroke.JOIN_ROUND:
                    gen.writeln("1 setlinejoin");
                    break;
                case BasicStroke.JOIN_BEVEL:
                    gen.writeln("2 setlinejoin");
                    break;
                default: System.err.println("Unsupported line join: " + lj);
                }
                float lw = bs.getLineWidth();
                gen.writeln(gen.formatDouble(lw) + " setlinewidth");
            }
        } catch (IOException ioe) {
            handleIOException(ioe);
        }
    }

    /**
     * Renders a {@link RenderedImage},
     * applying a transform from image
     * space into user space before drawing.
     * The transformation from user space into device space is done with
     * the current <code>Transform</code> in the <code>Graphics2D</code>.
     * The specified transformation is applied to the image before the
     * transform attribute in the <code>Graphics2D</code> context is applied.
     * The rendering attributes applied include the <code>Clip</code>,
     * <code>Transform</code>, and <code>Composite</code> attributes. Note
     * that no rendering is done if the specified transform is
     * noninvertible.
     * @param img the image to be rendered
     * @param xform the transformation from image space into user space
     * @see #transform
     * @see #setTransform
     * @see #setComposite
     * @see #clip
     * @see #setClip
     */
    public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
        preparePainting();
        System.err.println("NYI: drawRenderedImage");
    }

    /**
     * Renders a
     * {@link RenderableImage},
     * applying a transform from image space into user space before drawing.
     * The transformation from user space into device space is done with
     * the current <code>Transform</code> in the <code>Graphics2D</code>.
     * The specified transformation is applied to the image before the
     * transform attribute in the <code>Graphics2D</code> context is applied.
     * The rendering attributes applied include the <code>Clip</code>,
     * <code>Transform</code>, and <code>Composite</code> attributes. Note
     * that no rendering is done if the specified transform is
     * noninvertible.
     * <p>
     * Rendering hints set on the <code>Graphics2D</code> object might
     * be used in rendering the <code>RenderableImage</code>.
     * If explicit control is required over specific hints recognized by a
     * specific <code>RenderableImage</code>, or if knowledge of which hints
     * are used is required, then a <code>RenderedImage</code> should be
     * obtained directly from the <code>RenderableImage</code>
     * and rendered using
     * {@link #drawRenderedImage(RenderedImage, AffineTransform) drawRenderedImage}.
     * @param img the image to be rendered
     * @param xform the transformation from image space into user space
     * @see #transform
     * @see #setTransform
     * @see #setComposite
     * @see #clip
     * @see #setClip
     * @see #drawRenderedImage
     */
    public void drawRenderableImage(RenderableImage img,
                                    AffineTransform xform) {
        preparePainting();
        System.err.println("NYI: drawRenderableImage");
    }

    /**
     * Establishes the given color in the PostScript interpreter.
     * @param c the color to set
     * @throws IOException In case of an I/O problem
     */
    public void establishColor(Color c) throws IOException {
        gen.useColor(c);
    }

    /**
     * Renders the text specified by the specified <code>String</code>,
     * using the current <code>Font</code> and <code>Paint</code> attributes
     * in the <code>Graphics2D</code> context.
     * The baseline of the first character is at position
     * (<i>x</i>,&nbsp;<i>y</i>) in the User Space.
     * The rendering attributes applied include the <code>Clip</code>,
     * <code>Transform</code>, <code>Paint</code>, <code>Font</code> and
     * <code>Composite</code> attributes. For characters in script systems
     * such as Hebrew and Arabic, the glyphs can be rendered from right to
     * left, in which case the coordinate supplied is the location of the
     * leftmost character on the baseline.
     * @param s the <code>String</code> to be rendered
     * @param x the x-coordinate where the <code>String</code>
     * should be rendered
     * @param y the y-coordinate where the <code>String</code>
     * should be rendered
     * @see #setPaint
     * @see java.awt.Graphics#setColor
     * @see java.awt.Graphics#setFont
     * @see #setTransform
     * @see #setComposite
     * @see #setClip
     */
    public void drawString(String s, float x, float y) {
        try {
            if (customTextHandler != null && !textAsShapes) {
                customTextHandler.drawString(s, x, y);
            } else {
                fallbackTextHandler.drawString(s, x, y);
            }
        } catch (IOException ioe) {
            handleIOException(ioe);
        }
    }

    /**
     * Fills the interior of a <code>Shape</code> using the settings of the
     * <code>Graphics2D</code> context. The rendering attributes applied
     * include the <code>Clip</code>, <code>Transform</code>,
     * <code>Paint</code>, and <code>Composite</code>.
     * @param s the <code>Shape</code> to be filled
     * @see #setPaint
     * @see java.awt.Graphics#setColor
     * @see #transform
     * @see #setTransform
     * @see #setComposite
     * @see #clip
     * @see #setClip
     */
    public void fill(Shape s) {
        preparePainting();
        try {
            gen.saveGraphicsState();
            
            AffineTransform trans = getTransform();
            boolean newTransform = gen.getCurrentState().checkTransform(trans)
                    && !trans.isIdentity();
            
            if (newTransform) {
                gen.concatMatrix(trans);
            }
            Shape imclip = getClip();
            writeClip(imclip);
            
            establishColor(getColor());

            applyPaint(getPaint(), true);

            gen.writeln("newpath");
            PathIterator iter = s.getPathIterator(IDENTITY_TRANSFORM);
            processPathIterator(iter);
            doDrawing(true, false,
                      iter.getWindingRule() == PathIterator.WIND_EVEN_ODD);
            gen.restoreGraphicsState();
        } catch (IOException ioe) {
            handleIOException(ioe);
        }
    }

    /**
     * Commits a painting operation.
     * @param fill filling
     * @param stroke stroking
     * @param nonzero true if the non-zero winding rule should be used when filling
     * @exception IOException In case of an I/O problem
     */
    protected void doDrawing(boolean fill, boolean stroke, boolean nonzero) 
                throws IOException {
        preparePainting();
        if (fill) {
            if (stroke) {
                if (!nonzero) {
                    gen.writeln("gsave fill grestore stroke");
                } else {
                    gen.writeln("gsave eofill grestore stroke");
                }
            } else {
                if (!nonzero) {
                    gen.writeln("fill");
                } else {
                    gen.writeln("eofill");
                }
            }
        } else {
            // if(stroke)
            gen.writeln("stroke");
        }
    }

    /**
     * Returns the device configuration associated with this
     * <code>Graphics2D</code>.
     * @return the device configuration
     */
    public GraphicsConfiguration getDeviceConfiguration() {
        return GraphicsEnvironment.getLocalGraphicsEnvironment().
                getDefaultScreenDevice().getDefaultConfiguration();
    }

    /**
     * Used to create proper font metrics
     */
    private Graphics2D fmg;

    {
        BufferedImage bi = new BufferedImage(1, 1,
                                             BufferedImage.TYPE_INT_ARGB);

        fmg = bi.createGraphics();
    }

    /**
     * Gets the font metrics for the specified font.
     * @return    the font metrics for the specified font.
     * @param     f the specified font
     * @see       java.awt.Graphics#getFont
     * @see       java.awt.FontMetrics
     * @see       java.awt.Graphics#getFontMetrics()
     */
    public java.awt.FontMetrics getFontMetrics(java.awt.Font f) {
        return fmg.getFontMetrics(f);
    }

    /**
     * Sets the paint mode of this graphics context to alternate between
     * this graphics context's current color and the new specified color.
     * This specifies that logical pixel operations are performed in the
     * XOR mode, which alternates pixels between the current color and
     * a specified XOR color.
     * <p>
     * When drawing operations are performed, pixels which are the
     * current color are changed to the specified color, and vice versa.
     * <p>
     * Pixels that are of colors other than those two colors are changed
     * in an unpredictable but reversible manner; if the same figure is
     * drawn twice, then all pixels are restored to their original values.
     * @param     c1 the XOR alternation color
     */
    public void setXORMode(Color c1) {
        System.err.println("NYI: setXORMode");
    }


    /**
     * Copies an area of the component by a distance specified by
     * <code>dx</code> and <code>dy</code>. From the point specified
     * by <code>x</code> and <code>y</code>, this method
     * copies downwards and to the right.  To copy an area of the
     * component to the left or upwards, specify a negative value for
     * <code>dx</code> or <code>dy</code>.
     * If a portion of the source rectangle lies outside the bounds
     * of the component, or is obscured by another window or component,
     * <code>copyArea</code> will be unable to copy the associated
     * pixels. The area that is omitted can be refreshed by calling
     * the component's <code>paint</code> method.
     * @param       x the <i>x</i> coordinate of the source rectangle.
     * @param       y the <i>y</i> coordinate of the source rectangle.
     * @param       width the width of the source rectangle.
     * @param       height the height of the source rectangle.
     * @param       dx the horizontal distance to copy the pixels.
     * @param       dy the vertical distance to copy the pixels.
     */
    public void copyArea(int x, int y, int width, int height, int dx,
                         int dy) {
        System.err.println("NYI: copyArea");
    }

    /* --- for debugging
    public void transform(AffineTransform tx) {
        System.out.println("transform(" + toArray(tx) + ")");
        super.transform(zx);
    }

    public void scale(double sx, double sy) {
        System.out.println("scale(" + sx + ", " + sy + ")");
        super.scale(sx, sy);
    }

    public void translate(double tx, double ty) {
        System.out.println("translate(double " + tx + ", " + ty + ")");
        super.translate(tx, ty);
    }

    public void translate(int tx, int ty) {
        System.out.println("translate(int " + tx + ", " + ty + ")");
        super.translate(tx, ty);
    }
    */

}
