/*

   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.

 */

package org.apache.batik.svggen;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.font.GlyphVector;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ImageObserver;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.AttributedCharacterIterator;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.batik.ext.awt.g2d.AbstractGraphics2D;
import org.apache.batik.ext.awt.g2d.GraphicContext;

import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * This implementation of the java.awt.Graphics2D abstract class
 * allows users to generate SVG (Scalable Vector Graphics) content
 * from Java code.
 *
 * SVGGraphics2D generates a DOM tree whose root is obtained through
 * the getRoot method. Refer to the DOMTreeManager and DOMGroupManager
 * documentation for details on the structure of the generated
 * DOM tree.
 *
 * The SVGGraphics2D class can produce a DOM tree using any implementation
 * that conforms to the W3C DOM 1.0 specification (see http://www.w3.org).
 * At construction time, the SVGGraphics2D must be given a org.w3.dom.Document
 * instance that is used as a factory to create the various nodes in the
 * DOM tree it generates.
 *
 * The various graphic context attributes (e.g., AffineTransform,
 * Paint) are managed by a GraphicContext object.
 *
 *
 * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
 * @version $Id$
 * @see                org.apache.batik.ext.awt.g2d.GraphicContext
 * @see                org.apache.batik.svggen.DOMTreeManager
 * @see                org.apache.batik.svggen.DOMGroupManager
 * @see                org.apache.batik.svggen.ImageHandler
 * @see                org.apache.batik.svggen.ExtensionHandler
 * @see                org.w3c.dom.Document
 */
public class SVGGraphics2D extends AbstractGraphics2D
    implements Cloneable, SVGSyntax, ErrorConstants {

    /*
     * Constants definitions
     */
    public static final String DEFAULT_XML_ENCODING = "ISO-8859-1";

    /**
     * Controls the policy for grouping nodes. Once the number of attributes
     * overridden by a child element is greater than DEFAULT_MAX_GC_OVERRIDES,
     * a new group is created.
     *
     * @see org.apache.batik.svggen.DOMTreeManager
     */
    public static final int DEFAULT_MAX_GC_OVERRIDES = 3;


    /**
     * The DOMTreeManager manages the process of creating
     * and growing the SVG tree. This SVGGraphics2D relies on
     * the DOMTreeManager to process attributes based on the
     * GraphicContext state and create groups when needed.
     */
    protected DOMTreeManager domTreeManager;

    /**
     * The DOMGroupManager manages additions to the current group
     * node associated for this Graphics2D object. Once a group
     * is complete, the group manager appends it to the DOM tree
     * through the DOMTreeManager.
     * Note that each SVGGraphics2D instance has its own DOMGroupManager
     * (i.e., its own current group) but that all SVGGraphics2D
     * originating from the same SVGGraphics2D through various
     * createGraphics calls share the same DOMTreeManager.
     */
    protected DOMGroupManager domGroupManager;

    /**
     * Contains some information for SVG generation.
     */
    protected SVGGeneratorContext generatorCtx;

    /**
     * Used to convert Java 2D API Shape objects to equivalent SVG
     * elements
     */
    protected SVGShape shapeConverter;

    /**
     * SVG Canvas size
     */
    protected Dimension svgCanvasSize;

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

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

        fmg = bi.createGraphics();
    }

    /**
     * @return SVG Canvas size, as set in the root svg element
     */
    public final Dimension getSVGCanvasSize(){
        return svgCanvasSize;
    }

    /**
     * Set the Canvas size, this is used to set the width and
     * height attributes on the outermost 'svg' element.
     * @param svgCanvasSize SVG Canvas size. May be null (equivalent
     * to 100%, 100%)
     */
    public final void setSVGCanvasSize(Dimension svgCanvasSize) {
        this.svgCanvasSize = new Dimension(svgCanvasSize);
    }

    /**
     * @return the SVGGeneratorContext used by this SVGGraphics2D instance.
     */
    public final SVGGeneratorContext getGeneratorContext() {
        return generatorCtx;
    }

    /**
     * @return the SVGShape used by this SVGGraphics2D instance to
     *         turn Java2D shapes into SVG Shape objects.
     */
    public final SVGShape getShapeConverter() {
        return shapeConverter;
    }

    /**
     * @return the DOMTreeManager used by this SVGGraphics2D instance
     */
    public final DOMTreeManager getDOMTreeManager(){
        return domTreeManager;
    }

    /**
     * Set a DOM Tree manager for the SVGGraphics2D.
     * @param treeMgr the new DOM Tree manager this SVGGraphics2D should use
     */
     protected final void setDOMTreeManager(DOMTreeManager treeMgr) {
        this.domTreeManager = treeMgr;
        generatorCtx.genericImageHandler.setDOMTreeManager(domTreeManager);
    }

     /**
     * @return the DOMGroupManager used by this SVGGraphics2D instance
     */
    protected final DOMGroupManager getDOMGroupManager(){
        return domGroupManager;
    }

    /**
     * Set a new DOM Group manager for this SVGGraphics2D.
     * @param groupMgr the new DOM Group manager this SVGGraphics2D should use
     */
     protected final void setDOMGroupManager(DOMGroupManager groupMgr) {
        this.domGroupManager = groupMgr;
    }

    /**
     * @return the Document used as a DOM object factory by this
     *         SVGGraphics2D instance
     */
    public final Document getDOMFactory(){
        return generatorCtx.domFactory;
    }

    /**
     * @return the ImageHandler used by this SVGGraphics2D instance
     */
    public final ImageHandler getImageHandler(){
        return generatorCtx.imageHandler;
    }

    /**
     * @return the GenericImageHandler used by this SVGGraphics2D instance
     */
    public final GenericImageHandler getGenericImageHandler(){
        return generatorCtx.genericImageHandler;
    }

    /**
     * @return the extension handler used by this SVGGraphics2D instance
     */
    public final ExtensionHandler getExtensionHandler(){
        return generatorCtx.extensionHandler;
    }

    /**
     * @param extensionHandler new extension handler this SVGGraphics2D
     *        should use
     */
    public final void setExtensionHandler(ExtensionHandler extensionHandler) {
        generatorCtx.setExtensionHandler(extensionHandler);
    }

    /**
     * @param domFactory Factory which will produce Elements for the DOM tree
     *        this Graphics2D generates.
     * @exception SVGGraphics2DRuntimeException if domFactory is null.
     */
    public SVGGraphics2D(Document domFactory) {
        this(SVGGeneratorContext.createDefault(domFactory), false);
    }

    /**
     * @param domFactory Factory which will produce Elements for the DOM tree
     *                   this Graphics2D generates.
     * @param imageHandler defines how images are referenced in the
     *                     generated SVG fragment
     * @param extensionHandler defines how Java 2D API extensions map
     *                         to SVG Nodes.
     * @param textAsShapes if true, all text is turned into SVG shapes in the
     *        convertion. No SVG text is output.
     *
     * @exception SVGGraphics2DRuntimeException if domFactory is null.
     */
    public SVGGraphics2D(Document domFactory,
                         ImageHandler imageHandler,
                         ExtensionHandler extensionHandler,
                         boolean textAsShapes) {
        this(buildSVGGeneratorContext(domFactory,
                                      imageHandler,
                                      extensionHandler),
             textAsShapes);
    }

    /**
     * Helper method to create an <code>SVGGeneratorContext</code> from the
     * constructor parameters.
     */
    public static SVGGeneratorContext
        buildSVGGeneratorContext(Document domFactory,
                                 ImageHandler imageHandler,
                                 ExtensionHandler extensionHandler){

        SVGGeneratorContext generatorCtx = new SVGGeneratorContext(domFactory);
        generatorCtx.setIDGenerator(new SVGIDGenerator());
        generatorCtx.setExtensionHandler(extensionHandler);
        generatorCtx.setImageHandler(imageHandler);
        generatorCtx.setStyleHandler(new DefaultStyleHandler());
        generatorCtx.setComment("Generated by the Batik Graphics2D SVG Generator");
        generatorCtx.setErrorHandler(new DefaultErrorHandler());

        return generatorCtx;
    }

    /**
     * Creates a new SVGGraphics2D object.
     * @param generatorCtx the <code>SVGGeneratorContext</code> instance
     * that will provide all useful information to the generator.
     * @param textAsShapes if true, all text is turned into SVG shapes in the
     *        convertion. No SVG text is output.
     *
     * @exception SVGGraphics2DRuntimeException if generatorContext is null.
     */
    public SVGGraphics2D(SVGGeneratorContext generatorCtx,
                         boolean textAsShapes) {
        super(textAsShapes);

        if (generatorCtx == null)
            // no error handler here as we don't have the ctx...
            throw new SVGGraphics2DRuntimeException(ERR_CONTEXT_NULL);

        setGeneratorContext(generatorCtx);
    }

    /**
     * Sets an non null <code>SVGGeneratorContext</code>.
     */
    protected void setGeneratorContext(SVGGeneratorContext generatorCtx) {
        this.generatorCtx = generatorCtx;

        this.gc = new GraphicContext(new AffineTransform());

        SVGGeneratorContext.GraphicContextDefaults gcDefaults =
            generatorCtx.getGraphicContextDefaults();

        if(gcDefaults != null){
            if(gcDefaults.getPaint() != null){
                gc.setPaint(gcDefaults.getPaint());
            }
            if(gcDefaults.getStroke() != null){
                gc.setStroke(gcDefaults.getStroke());
            }
            if(gcDefaults.getComposite() != null){
                gc.setComposite(gcDefaults.getComposite());
            }
            if(gcDefaults.getClip() != null){
                gc.setClip(gcDefaults.getClip());
            }
            if(gcDefaults.getRenderingHints() != null){
                gc.setRenderingHints(gcDefaults.getRenderingHints());
            }
            if(gcDefaults.getFont() != null){
                gc.setFont(gcDefaults.getFont());
            }
            if(gcDefaults.getBackground() != null){
                gc.setBackground(gcDefaults.getBackground());
            }
        }

        this.shapeConverter = new SVGShape(generatorCtx);
        this.domTreeManager = new DOMTreeManager(gc,
                                                 generatorCtx,
                                                 DEFAULT_MAX_GC_OVERRIDES);
        this.domGroupManager = new DOMGroupManager(gc, domTreeManager);
        this.domTreeManager.addGroupManager(domGroupManager);
        generatorCtx.genericImageHandler.setDOMTreeManager(domTreeManager);
    }

    /**
     * This constructor is used in create()
     *
     * @see #create
     */
    public SVGGraphics2D(SVGGraphics2D g) {
        super(g);
        this.generatorCtx = g.generatorCtx;
        this.gc.validateTransformStack();
        this.shapeConverter = g.shapeConverter;
        this.domTreeManager = g.domTreeManager;
        this.domGroupManager = new DOMGroupManager(this.gc, this.domTreeManager);
        this.domTreeManager.addGroupManager(this.domGroupManager);
    }

    /**
     * @param svgFileName name of the file where SVG content
     *        should be written
     */
    public void stream(String svgFileName) throws SVGGraphics2DIOException {
        stream(svgFileName, false);
    }

    /**
     * @param svgFileName name of the file where SVG content
     *        should be written
     * @param useCss defines whether the output SVG should use CSS style
     * properties as opposed to plain attributes.
     */
    public void stream(String svgFileName, boolean useCss)
        throws SVGGraphics2DIOException {
        try {
            OutputStreamWriter writer =
                new OutputStreamWriter(new FileOutputStream(svgFileName),
                                       DEFAULT_XML_ENCODING);
            stream(writer, useCss);
            writer.flush();
            writer.close();
        } catch (SVGGraphics2DIOException io) {
            // this one as already been handled in stream(Writer, boolean)
            // method => rethrow it in all cases
            throw io;
        } catch (IOException e) {
            generatorCtx.errorHandler.
                handleError(new SVGGraphics2DIOException(e));
        }
    }

    /**
     * @param writer used to writer out the SVG content
     */
    public void stream(Writer writer) throws SVGGraphics2DIOException {
        stream(writer, false);
    }

    /**
     * @param writer used to writer out the SVG content
     * @param useCss defines whether the output SVG should use CSS
     * @param escaped defines if the characters will be escaped
     * style properties as opposed to plain attributes.
     */
    public void stream(Writer writer, boolean useCss, boolean escaped)
        throws SVGGraphics2DIOException {
        Element svgRoot = getRoot();
        stream(svgRoot, writer, useCss, escaped);
    }

    /**
     * @param writer used to writer out the SVG content
     * @param useCss defines whether the output SVG should use CSS
     * style properties as opposed to plain attributes.
     */
    public void stream(Writer writer, boolean useCss)
        throws SVGGraphics2DIOException {
        Element svgRoot = getRoot();
        stream(svgRoot, writer, useCss, false);
    }

    /**
     * @param svgRoot root element to stream out
     */
    public void stream(Element svgRoot, Writer writer)
        throws SVGGraphics2DIOException {
        stream(svgRoot, writer, false, false);
    }

    /**
     * @param svgRoot root element to stream out
     * @param writer output
     * @param useCss defines whether the output SVG should use CSS style
     * @param escaped defines if the characters will be escaped
     * properties as opposed to plain attributes.
     */
    public void stream(Element svgRoot, Writer writer, boolean useCss, boolean escaped)
        throws SVGGraphics2DIOException {
        Node rootParent = svgRoot.getParentNode();
        Node nextSibling = svgRoot.getNextSibling();

        try {
            //
            // Enforce that the default and xlink namespace
            // declarations appear on the root element
            //
            svgRoot.setAttributeNS(XMLNS_NAMESPACE_URI,
                                   XMLNS_PREFIX,
                                   SVG_NAMESPACE_URI);

            svgRoot.setAttributeNS(XMLNS_NAMESPACE_URI,
                                   XMLNS_PREFIX + ":" + XLINK_PREFIX,
                                   XLINK_NAMESPACE_URI);

            DocumentFragment svgDocument =
                svgRoot.getOwnerDocument().createDocumentFragment();
            svgDocument.appendChild(svgRoot);

            if (useCss)
                SVGCSSStyler.style(svgDocument);

            XmlWriter.writeXml(svgDocument, writer, escaped);
            writer.flush();
        } catch (SVGGraphics2DIOException e) {
            // this catch prevents from catching an SVGGraphics2DIOException
            // and wrapping it again in another SVGGraphics2DIOException
            // as would do the second catch (XmlWriter throws SVGGraphics2DIO
            // Exception but flush throws IOException)
            generatorCtx.errorHandler.
                handleError(e);
        } catch (IOException io) {
            generatorCtx.errorHandler.
                handleError(new SVGGraphics2DIOException(io));
        } finally {
            // Restore the svgRoot to its original tree position
            if (rootParent != null) {
                if (nextSibling == null) {
                    rootParent.appendChild(svgRoot);
                } else {
                    rootParent.insertBefore(svgRoot, nextSibling);
                }
            }
        }
    }

    /**
     * Invoking this method will return a set of definition element that
     * contain all the definitions referenced by the attributes generated by
     * the various converters. This also resets the converters.
     */
    public java.util.List getDefinitionSet(){
        return domTreeManager.getDefinitionSet();
    }

    /**
     * Invoking this method will return a reference to the topLevelGroup
     * Element managed by this object. It will also cause this object
     * to start working with a new topLevelGroup.
     *
     * @return top level group
     */
    public Element getTopLevelGroup(){
        return getTopLevelGroup(true);
    }

    /**
     * Invoking this method will return a reference to the topLevelGroup
     * Element managed by this object. It will also cause this object
     * to start working with a new topLevelGroup.
     *
     * @param includeDefinitionSet if true, the definition set is included and
     *        the converters are reset (i.e., they start with an empty set
     *        of definitions).
     * @return top level group
     */
    public Element getTopLevelGroup(boolean includeDefinitionSet){
        return domTreeManager.getTopLevelGroup(includeDefinitionSet);
    }

    /**
     * Sets the topLevelGroup to the input element. This will throw an exception
     * if the input element is not of type 'g' or if it is null.
     */
    public void setTopLevelGroup(Element topLevelGroup){
        domTreeManager.setTopLevelGroup(topLevelGroup);
    }

    /**
     * @return the svg root node of the SVG document associated with this
     *         object
     */
    public Element getRoot(){
        return getRoot(null);
    }

    /**
     * This version of the getRoot method will append the input svgRoot
     * and set its attributes.
     *
     * @param svgRoot an SVG element underwhich the content should
     *        be appended.
     * @return the svg root node of the SVG document associated with
     *         this object.
     */
    public Element getRoot(Element svgRoot) {
        svgRoot = domTreeManager.getRoot(svgRoot);
        if (svgCanvasSize != null){
            svgRoot.setAttributeNS(null, SVG_WIDTH_ATTRIBUTE,  String.valueOf( svgCanvasSize.width ) );
            svgRoot.setAttributeNS(null, SVG_HEIGHT_ATTRIBUTE, String.valueOf( svgCanvasSize.height) );
        }
        return svgRoot;
    }

    /**
     * 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(){
        return new SVGGraphics2D(this);
    }


    /**
     * 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) {
        generatorCtx.errorHandler.
            handleError(new SVGGraphics2DRuntimeException(ERR_XOR));
    }

    /**
     * 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 FontMetrics getFontMetrics(Font f){
        return fmg.getFontMetrics(f);
    }

    /**
     * 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){
        // No-op
    }

    /**
     * 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.
     * @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) {
        Element imageElement =
            getGenericImageHandler().createElement(getGeneratorContext());
        AffineTransform xform = getGenericImageHandler().handleImage(
                                                         img, imageElement,
                                                         x, y,
                                                         img.getWidth(null),
                                                         img.getHeight(null),
                                                         getGeneratorContext());

        if (xform == null) {
            domGroupManager.addElement(imageElement);
        } else {
            AffineTransform inverseTransform = null;
            try {
                inverseTransform = xform.createInverse();
            } catch(NoninvertibleTransformException e) {
                // This should never happen since handleImage
                // always returns invertible transform
                throw new SVGGraphics2DRuntimeException(ERR_UNEXPECTED);
            }
            gc.transform(xform);
            domGroupManager.addElement(imageElement);
            gc.transform(inverseTransform);
        }
        return true;
    }

    /**
     * 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.
     * @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){
        Element imageElement =
            getGenericImageHandler().createElement(getGeneratorContext());
        AffineTransform xform
            = getGenericImageHandler().handleImage(
                                       img, imageElement,
                                       x, y,
                                       width, height,
                                       getGeneratorContext());

        if (xform == null) {
            domGroupManager.addElement(imageElement);
        } else {
            AffineTransform inverseTransform = null;
            try {
                inverseTransform = xform.createInverse();
            } catch(NoninvertibleTransformException e) {
                // This should never happen since handleImage
                // always returns invertible transform
                throw new SVGGraphics2DRuntimeException(ERR_UNEXPECTED);
            }
            gc.transform(xform);
            domGroupManager.addElement(imageElement);
            gc.transform(inverseTransform);
        }
        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.domTreeManager.removeGroupManager(this.domGroupManager);
    }

    /**
     * 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(Stroke)
     * @see #setPaint(Paint)
     * @see java.awt.Graphics#setColor
     * @see #setTransform(AffineTransform)
     * @see #setClip(Shape)
     * @see #setComposite(java.awt.Composite)
     */
    public void draw(Shape s) {
        // Only BasicStroke can be converted to an SVG attribute equivalent.
        // If the GraphicContext's Stroke is not an instance of BasicStroke,
        // then the stroked outline is filled.
        Stroke stroke = gc.getStroke();
        if (stroke instanceof BasicStroke) {
            Element svgShape = shapeConverter.toSVG(s);
            if (svgShape != null) {
                domGroupManager.addElement(svgShape, DOMGroupManager.DRAW);
            }
        } else {
            Shape strokedShape = stroke.createStrokedShape(s);
            fill(strokedShape);
        }
    }


    /**
     * Renders an image, 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 <code>Image</code> to be rendered
     * @param xform the transformation from image space into user space
     * @param obs the {@link ImageObserver}
     * to be notified as more of the <code>Image</code>
     * is converted
     * @return <code>true</code> if the <code>Image</code> is
     * fully loaded and completely rendered;
     * <code>false</code> if the <code>Image</code> is still being loaded.
     * @see #setTransform(AffineTransform)
     * @see #setComposite(java.awt.Composite)
     * @see #setClip(Shape)
     */
    public boolean drawImage(Image img,
                             AffineTransform xform,
                             ImageObserver obs){
        boolean retVal = true;

        if (xform == null) {
            retVal = drawImage(img, 0, 0, null);
        } else if(xform.getDeterminant() != 0){
            AffineTransform inverseTransform = null;
            try{
                inverseTransform = xform.createInverse();
            }   catch(NoninvertibleTransformException e){
                // Should never happen since we checked the
                // matrix determinant
                throw new SVGGraphics2DRuntimeException(ERR_UNEXPECTED);
            }

            gc.transform(xform);
            retVal = drawImage(img, 0, 0, null);
            gc.transform(inverseTransform);
        } else {
            AffineTransform savTransform = new AffineTransform(gc.getTransform());
            gc.transform(xform);
            retVal = drawImage(img, 0, 0, null);
            gc.setTransform(savTransform);
        }

        return retVal;

    }


    /**
     * Renders a <code>BufferedImage</code> that is
     * filtered with a
     * {@link BufferedImageOp}.
     * The rendering attributes applied include the <code>Clip</code>,
     * <code>Transform</code>
     * and <code>Composite</code> attributes.  This is equivalent to:
     * <pre>
     * img1 = op.filter(img, null);
     * drawImage(img1, new AffineTransform(1f,0f,0f,1f,x,y), null);
     * </pre>
     * @param op the filter to be applied to the image before rendering
     * @param img the <code>BufferedImage</code> to be rendered
     * @param x the x coordinate in user space where the upper left
     *          corner of the image is rendered
     * @param y the y coordinate in user space where the upper left
     *          corner of the image is rendered
     * @see #setTransform(AffineTransform)
     * @see #setComposite(java.awt.Composite)
     * @see #setClip(Shape)
     */
    public void drawImage(BufferedImage img,
                          BufferedImageOp op,
                          int x,
                          int y){
        //
        // Only convert if the input image is of type sRGB
        // non-premultiplied
        //
        /*if(img.getType() == BufferedImage.TYPE_INT_ARGB){
            //
            // There are two special cases: AffineTransformOp and
            // ColorConvertOp. If the input op is not one of these
            // two, then SVGBufferedImageOp is requested to map the
            // filter to an SVG equivalent.
            //
            if(op instanceof AffineTransformOp){
                AffineTransformOp transformOp = (AffineTransformOp)op;
                AffineTransform transform = transformOp.getTransform();

                if(transform.getDeterminant() != 0){
                    AffineTransform inverseTransform = null;
                    try{
                        inverseTransform = transform.createInverse();
                    }catch(NoninvertibleTransformException e){
                        // This should never happen since we checked the
                        // matrix determinant
                        throw new SVGGraphics2DRuntimeException(ERR_UNEXPECTED);
                    }
                    gc.transform(transform);
                    drawImage(img, x, y, null);
                    gc.transform(inverseTransform);
                }
                else{
                    AffineTransform savTransform =
                    new AffineTransform(gc.getTransform());
                    gc.transform(transform);
                    drawImage(img, x, y, null);
                    gc.setTransform(savTransform);
                }
            }
            else if(op instanceof ColorConvertOp){
                img = op.filter(img, null);
                drawImage(img, x, y, null);
            }
            else{
                //
                // Try and convert to an SVG filter
                //
                SVGFilterDescriptor filterDesc =
                domTreeManager.getFilterConverter().toSVG(op, null);
                if(filterDesc != null){
                //
                // Because other filters may be needed to represent the
                // composite that applies to this image, a group is created that
                // contains the image element.
                //
                Element imageElement =
                getDOMFactory().
                createElementNS(SVG_NAMESPACE_URI, SVG_IMAGE_TAG);
                getImageHandler().handleImage((Image)img, imageElement,
                generatorCtx);
                imageElement.setAttributeNS(null, SVG_X_ATTRIBUTE,
                Integer.toString(x));
                imageElement.setAttributeNS(null, SVG_Y_ATTRIBUTE,
                Integer.toString(y));
                imageElement.setAttributeNS(null, SVG_WIDTH_ATTRIBUTE,
                Integer.toString(img.getWidth(null)));
                imageElement.setAttributeNS(null, SVG_HEIGHT_ATTRIBUTE,
                Integer.toString(img.getHeight(null)));
                imageElement.setAttributeNS(null, SVG_FILTER_ATTRIBUTE,
                filterDesc.getFilterValue());
                Element imageGroup = generatorCtx.domFactory.createElementNS(SVG_NAMESPACE_URI,
                SVG_G_TAG);
                imageGroup.appendChild(imageElement);

                    domGroupManager.addElement(imageGroup);
                }
                else{
                    //
                    // Could not convert to an equivalent SVG filter:
                    // filter now and draw resulting image
                    //
                    img = op.filter(img, null);
                    drawImage(img, x, y, null);
                }
            }
        }
        else{*/
            //
            // Input image is not sRGB non premultiplied.
            // Do not try conversion: apply filter and paint
            //
        img = op.filter(img, null);
        drawImage(img, x, y, null);
            // }
    }


    /**
     * 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 trans2 the transformation from image space into user space
     * @see #setTransform(AffineTransform)
     * @see #setComposite(java.awt.Composite)
     * @see #setClip(Shape)
     */
    public void drawRenderedImage(RenderedImage img,
                                  AffineTransform trans2) {

        Element image =
            getGenericImageHandler().createElement(getGeneratorContext());
        AffineTransform trans1
            = getGenericImageHandler().handleImage(
                                       img, image,
                                       img.getMinX(),
                                       img.getMinY(),
                                       img.getWidth(),
                                       img.getHeight(),
                                       getGeneratorContext());

        AffineTransform xform;

        // Concatenate the transformation we receive from the imageHandler
        // to the user-supplied one. Be aware that both may be null.
        if (trans2 == null) {
            xform = trans1;
        } else {
            if(trans1 == null) {
                xform = trans2;
             } else {
                xform = new AffineTransform(trans2);
                xform.concatenate(trans1);
            }
        }

        if(xform == null) {
            domGroupManager.addElement(image);
        } else if(xform.getDeterminant() != 0){
            AffineTransform inverseTransform = null;
            try{
                inverseTransform = xform.createInverse();
            }catch(NoninvertibleTransformException e){
                // This should never happen since we checked
                // the matrix determinant
                throw new SVGGraphics2DRuntimeException(ERR_UNEXPECTED);
            }
            gc.transform(xform);
            domGroupManager.addElement(image);
            gc.transform(inverseTransform);
        } else {
            AffineTransform savTransform = new AffineTransform(gc.getTransform());
            gc.transform(xform);
            domGroupManager.addElement(image);
            gc.setTransform(savTransform);
        }
    }

    /**
     * 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)}.
     * @param img the image to be rendered
     * @param trans2 the transformation from image space into user space
     * @see #setTransform(AffineTransform)
     * @see #setComposite(java.awt.Composite)
     * @see #setClip(Shape)
     * @see #drawRenderedImage
     */
    public void drawRenderableImage(RenderableImage img,
                                    AffineTransform trans2){

        Element image =
            getGenericImageHandler().createElement(getGeneratorContext());

        AffineTransform trans1 =
            getGenericImageHandler().handleImage(
                                     img, image,
                                     img.getMinX(),
                                     img.getMinY(),
                                     img.getWidth(),
                                     img.getHeight(),
                                     getGeneratorContext());

        AffineTransform xform;

        // Concatenate the transformation we receive from the imageHandler
        // to the user-supplied one. Be aware that both may be null.
        if (trans2 == null) {
            xform = trans1;
        } else {
            if(trans1 == null) {
                xform = trans2;
             } else {
                xform = new AffineTransform(trans2);
                xform.concatenate(trans1);
            }
        }

        if (xform == null) {
            domGroupManager.addElement(image);
        } else if(xform.getDeterminant() != 0){
            AffineTransform inverseTransform = null;
            try{
                inverseTransform = xform.createInverse();
            }catch(NoninvertibleTransformException e){
                // This should never happen because we checked the
                // matrix determinant
                throw new SVGGraphics2DRuntimeException(ERR_UNEXPECTED);
            }
            gc.transform(xform);
            domGroupManager.addElement(image);
            gc.transform(inverseTransform);
        } else {
            AffineTransform savTransform = new AffineTransform(gc.getTransform());
            gc.transform(xform);
            domGroupManager.addElement(image);
            gc.setTransform(savTransform);
        }
    }


    /**
     * 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(Paint)
     * @see java.awt.Graphics#setColor
     * @see java.awt.Graphics#setFont
     * @see #setTransform(AffineTransform)
     * @see #setComposite(java.awt.Composite)
     * @see #setClip(Shape)
     */
    public void drawString(String s, float x, float y) {
        if (textAsShapes)  {
            GlyphVector gv = getFont().
                createGlyphVector(getFontRenderContext(), s);
            drawGlyphVector(gv, x, y);
            return;
        }

        if (generatorCtx.svgFont) {
            // record that the font is being used to draw this
            // string, this is so that the SVG Font element will
            // only create glyphs for the characters that are
            // needed
            domTreeManager.gcConverter.
                getFontConverter().recordFontUsage(s, getFont());
        }

        // Account for the font transform if there is one
        AffineTransform savTxf = getTransform();
        AffineTransform txtTxf = transformText(x, y);

        Element text =
            getDOMFactory().createElementNS(SVG_NAMESPACE_URI, SVG_TEXT_TAG);
        text.setAttributeNS(null, SVG_X_ATTRIBUTE, generatorCtx.doubleString(x));
        text.setAttributeNS(null, SVG_Y_ATTRIBUTE, generatorCtx.doubleString(y));

        text.setAttributeNS(XML_NAMESPACE_URI,
                            XML_SPACE_QNAME,
                            XML_PRESERVE_VALUE);
        text.appendChild(getDOMFactory().createTextNode(s));
        domGroupManager.addElement(text, DOMGroupManager.FILL);

        if (txtTxf != null){
            this.setTransform(savTxf);
        }
    }

    private AffineTransform transformText(float x, float y) {
        AffineTransform txtTxf = null;
        Font font = getFont();
        if (font != null){
            txtTxf = font.getTransform();
            if (txtTxf != null && !txtTxf.isIdentity()){
                //
                // The additional transform applies about the text's origin
                //
                AffineTransform t = new AffineTransform();
                t.translate(x, y);
                t.concatenate(txtTxf);
                t.translate(-x, -y);
                this.transform(t);
            } else {
                txtTxf = null;
            }
        }
        return txtTxf;
    }

    /**
     * Renders the text of the specified iterator, using the
     * <code>Graphics2D</code> context's current <code>Paint</code>. The
     * iterator must specify a font
     * for each character. 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>, 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.<br>
     *
     *
     * @param ati the iterator whose text is to be rendered
     * @param x the x coordinate where the iterator's text is to be rendered
     * @param y the y coordinate where the iterator's text is to be rendered
     * @see #setPaint(Paint)
     * @see java.awt.Graphics#setColor
     * @see #setTransform(AffineTransform)
     * @see #setComposite(java.awt.Composite)
     * @see #setClip(Shape)
     */
    public void drawString(AttributedCharacterIterator ati, float x, float y) {
        if ((textAsShapes) || (usesUnsupportedAttributes(ati))) {
            TextLayout layout = new TextLayout(ati, getFontRenderContext());
            layout.draw(this, x, y);
            return;
        }
        // first we want if there is more than one run in this
        // ati. This will be used to decide if we create tspan
        // Elements under the text Element or not
        boolean multiSpans = false;
        if (ati.getRunLimit() < ati.getEndIndex()) multiSpans = true;

        // create the parent text Element
        Element text = getDOMFactory().createElementNS(SVG_NAMESPACE_URI,
                                                       SVG_TEXT_TAG);
        text.setAttributeNS(null, SVG_X_ATTRIBUTE,
                            generatorCtx.doubleString(x));
        text.setAttributeNS(null, SVG_Y_ATTRIBUTE,
                            generatorCtx.doubleString(y));
        text.setAttributeNS(XML_NAMESPACE_URI, XML_SPACE_QNAME,
                            XML_PRESERVE_VALUE);

        Font  baseFont  = getFont();
        Paint basePaint = getPaint();

        // now iterate through all the runs
        char ch = ati.first();

        setTextElementFill   (ati);
        setTextFontAttributes(ati, baseFont);

        SVGGraphicContext textGC;
        textGC = domTreeManager.getGraphicContextConverter().toSVG(gc);
        domGroupManager.addElement(text, DOMGroupManager.FILL);
        textGC.getContext().put(SVG_STROKE_ATTRIBUTE, SVG_NONE_VALUE);
        textGC.getGroupContext().put(SVG_STROKE_ATTRIBUTE, SVG_NONE_VALUE);

        boolean firstSpan = true;
        AffineTransform savTxf = getTransform();
        AffineTransform txtTxf = null;
        while (ch != AttributedCharacterIterator.DONE) {
            // first get the text Element or create a child Element if
            // we used tspans
            Element tspan = text;
            if (multiSpans) {
                tspan = getDOMFactory().createElementNS
                    (SVG_NAMESPACE_URI, SVG_TSPAN_TAG);
                text.appendChild(tspan);
            }

            // decorate the tspan Element :
            setTextElementFill(ati);
            boolean resetTransform = setTextFontAttributes(ati, baseFont);

            // management of font attributes
            if (resetTransform || firstSpan) {
                // Account for the font transform if there is one
                txtTxf = transformText(x, y);
                firstSpan = false;
            }

            // retrieve the current span of text for the run
            int start = ati.getIndex();
            int end   = ati.getRunLimit()-1;

            StringBuffer buf = new StringBuffer( end - start );
            buf.append(ch);

            for (int i=start; i<end; i++) {
                ch = ati.next();
                buf.append(ch);
            }

            String s = buf.toString();
            if (generatorCtx.isEmbeddedFontsOn()) {
                // record that the font is being used to draw this
                // string, this is so that the SVG Font element will
                // only create glyphs for the characters that are
                // needed
                getDOMTreeManager().getGraphicContextConverter().
                    getFontConverter().recordFontUsage(s, getFont());
            }

            // This must come after registering font usage other
            // wise it doesn't know what chars were used.
            SVGGraphicContext elementGC;
            elementGC = domTreeManager.gcConverter.toSVG(gc);
            elementGC.getGroupContext().put(SVG_STROKE_ATTRIBUTE,
                                            SVG_NONE_VALUE);

            SVGGraphicContext deltaGC;
            deltaGC = DOMGroupManager.processDeltaGC(elementGC, textGC);

            // management of underline, strike attributes, etc..
            setTextElementAttributes(deltaGC, ati);

            domTreeManager.getStyleHandler().
                setStyle(tspan, deltaGC.getContext(),
                         domTreeManager.getGeneratorContext());

            tspan.appendChild(getDOMFactory().createTextNode(s));
            if ((resetTransform || firstSpan) && (txtTxf != null)) {
                this.setTransform(savTxf);
            }
            ch = ati.next();  // get first char of next run.
        }
        setFont(baseFont);
        setPaint(basePaint);
    }

    /**
     * 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(Paint)
     * @see java.awt.Graphics#setColor
     * @see #setTransform(AffineTransform)
     * @see #setComposite(java.awt.Composite)
     * @see #setClip(Shape)
     */
    public void fill(Shape s) {
        Element svgShape = shapeConverter.toSVG(s);
        if (svgShape != null) {
            domGroupManager.addElement(svgShape, DOMGroupManager.FILL);
        }
    }

    /** Set the Element Font and Size attributes, depending on the
     * AttributedCharacterIterator attributes.
     */
    private boolean setTextFontAttributes(AttributedCharacterIterator ati,
                                          Font baseFont) {
        boolean resetTransform = false;
        if ((ati.getAttribute(TextAttribute.FONT) != null) ||
            (ati.getAttribute(TextAttribute.FAMILY) != null) ||
            (ati.getAttribute(TextAttribute.WEIGHT) != null) ||
            (ati.getAttribute(TextAttribute.POSTURE) != null) ||
            (ati.getAttribute(TextAttribute.SIZE) != null)) {
            Map m = ati.getAttributes();
            Font f = baseFont.deriveFont(m);
            setFont(f);
            resetTransform = true;
        }

        return resetTransform;
    }

    /** Set the Element attributes, depending on the AttributedCharacterIterator attributes.
     *  The following attributes are set :
     *  <ul>
     *  <li>underline</li>
     *  <li>weight (bold or plain)</li>
     *  <li>style (italic or normal)</li>
     *  <li>justification (start, end, or middle)</li>
     *  </ul>
     */
    private void setTextElementFill(AttributedCharacterIterator ati) {
        if (ati.getAttribute(TextAttribute.FOREGROUND) != null) {
            Color color = (Color)ati.getAttribute(TextAttribute.FOREGROUND);
            setPaint(color);
        }
    }

    private void setTextElementAttributes(SVGGraphicContext tspanGC,
                                          AttributedCharacterIterator ati) {
        String decoration = "";
        if (isUnderline(ati))
            decoration += CSS_UNDERLINE_VALUE + " ";
        if (isStrikeThrough(ati))
            decoration += CSS_LINE_THROUGH_VALUE + " ";
        int len = decoration.length();
        if (len != 0)
            tspanGC.getContext().put(CSS_TEXT_DECORATION_PROPERTY,
                                     decoration.substring(0, len-1));
    }

    /** Return true if the AttributedCharacterIterator is bold (at its current position).
     */
    private boolean isBold(AttributedCharacterIterator ati) {
        Object weight = ati.getAttribute(TextAttribute.WEIGHT);
        if (weight == null)
            return false;
        if (weight.equals(TextAttribute.WEIGHT_REGULAR))
            return false;
        if (weight.equals(TextAttribute.WEIGHT_DEMILIGHT))
            return false;
        if (weight.equals(TextAttribute.WEIGHT_EXTRA_LIGHT))
            return false;
        if (weight.equals(TextAttribute.WEIGHT_LIGHT))
            return false;
        return true;
    }

    /** Return true if the AttributedCharacterIterator is italic (at
     * its current position).
     */
    private boolean isItalic(AttributedCharacterIterator ati) {
        Object attr = ati.getAttribute(TextAttribute.POSTURE);
        if (TextAttribute.POSTURE_OBLIQUE.equals(attr)) return true;
        return false;
    }

    /** Return true if the AttributedCharacterIterator is underlined
     * (at its current position).
     */
    private boolean isUnderline(AttributedCharacterIterator ati) {
        Object attr = ati.getAttribute(TextAttribute.UNDERLINE);
        return TextAttribute.UNDERLINE_ON.equals(attr);
        // What to do about UNDERLINE_LOW_*?  Right now we don't
        // draw them since we can't really model them...
    }

    /** Return true if the AttributedCharacterIterator is striked
     * through (at its current position).
     */
    private boolean isStrikeThrough(AttributedCharacterIterator ati) {
        Object attr = ati.getAttribute(TextAttribute.STRIKETHROUGH);
        if (TextAttribute.STRIKETHROUGH_ON.equals(attr)) return true;
        return false;
    }

    /**
     * Returns the device configuration associated with this
     * <code>Graphics2D</code>.
     */
    public GraphicsConfiguration getDeviceConfiguration(){
        // TO BE DONE.
        return null;
    }

    /* This is the list of attributes that can't currently be
     * supported by drawString(AttributedCharacterIterator).
     * For accuracy if any of these are present then the
     * text is drawn as outlines.
     */
    protected Set unsupportedAttributes;
    {
        unsupportedAttributes = new HashSet();
        unsupportedAttributes.add(TextAttribute.BACKGROUND);
        unsupportedAttributes.add(TextAttribute.BIDI_EMBEDDING);
        unsupportedAttributes.add(TextAttribute.CHAR_REPLACEMENT);
        unsupportedAttributes.add(TextAttribute.JUSTIFICATION);
        unsupportedAttributes.add(TextAttribute.RUN_DIRECTION);
        unsupportedAttributes.add(TextAttribute.SUPERSCRIPT);
        unsupportedAttributes.add(TextAttribute.SWAP_COLORS);
        unsupportedAttributes.add(TextAttribute.TRANSFORM);
        unsupportedAttributes.add(TextAttribute.WIDTH);
    }

    /**
     * This method let's users indicate that they don't care that
     * certain text attributes will not be properly converted to
     * SVG, in exchange when those attributes are used they will
     * get real SVG text instead of paths.
     *
     * @param attrs The set of attrs to treat as unsupported, and
     *              if present cause text to be drawn as paths.
     *              If null ACI text will be rendered as text
     *              (unless 'textAsShapes' is set).
     */
    public void setUnsupportedAttributes(Set attrs) {
        if (attrs == null) unsupportedAttributes = null;
        else               unsupportedAttributes = new HashSet(attrs);
    }

    public boolean usesUnsupportedAttributes(AttributedCharacterIterator aci){
        if (unsupportedAttributes == null) return false;

        Set      allAttrs = aci.getAllAttributeKeys();
        for (Object allAttr : allAttrs) {
            if (unsupportedAttributes.contains(allAttr)) {
                return true;
            }
        }
        return false;
    }

}
