/*

   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.bridge;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.TextAttribute;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.lang.ref.SoftReference;
import java.text.AttributedCharacterIterator;
import java.text.AttributedCharacterIterator.Attribute;
import java.text.AttributedString;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

import org.apache.batik.anim.dom.AbstractSVGAnimatedLength;
import org.apache.batik.anim.dom.AnimatedLiveAttributeValue;
import org.apache.batik.anim.dom.SVGOMAnimatedEnumeration;
import org.apache.batik.anim.dom.SVGOMAnimatedLengthList;
import org.apache.batik.anim.dom.SVGOMAnimatedNumberList;
import org.apache.batik.anim.dom.SVGOMElement;
import org.apache.batik.anim.dom.SVGOMTextPositioningElement;
import org.apache.batik.css.engine.CSSEngineEvent;
import org.apache.batik.css.engine.CSSStylableElement;
import org.apache.batik.css.engine.SVGCSSEngine;
import org.apache.batik.css.engine.StyleMap;
import org.apache.batik.css.engine.value.ListValue;
import org.apache.batik.css.engine.value.Value;
import org.apache.batik.dom.events.NodeEventTarget;
import org.apache.batik.dom.svg.LiveAttributeException;
import org.apache.batik.dom.svg.SVGContext;
import org.apache.batik.dom.svg.SVGTextContent;
import org.apache.batik.dom.util.XLinkSupport;
import org.apache.batik.dom.util.XMLSupport;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.font.GVTFont;
import org.apache.batik.gvt.font.GVTFontFamily;
import org.apache.batik.gvt.font.GVTGlyphMetrics;
import org.apache.batik.gvt.font.GVTGlyphVector;
import org.apache.batik.gvt.font.UnresolvedFontFamily;
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.batik.gvt.text.TextPaintInfo;
import org.apache.batik.gvt.text.TextPath;
import org.apache.batik.util.XMLConstants;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.css.CSSPrimitiveValue;
import org.w3c.dom.css.CSSValue;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.MutationEvent;
import org.w3c.dom.svg.SVGLengthList;
import org.w3c.dom.svg.SVGNumberList;
import org.w3c.dom.svg.SVGTextContentElement;
import org.w3c.dom.svg.SVGTextPositioningElement;

/**
 * Bridge class for the &lt;text&gt; element.
 *
 * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
 * @author <a href="mailto:bill.haneman@ireland.sun.com">Bill Haneman</a>
 * @version $Id$
 */
public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
    implements SVGTextContent {

    protected static final Integer ZERO = 0;

    public static final
        AttributedCharacterIterator.Attribute TEXT_COMPOUND_DELIMITER =
        GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER;

    public static final
        AttributedCharacterIterator.Attribute TEXT_COMPOUND_ID =
        GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_ID;

    public static final AttributedCharacterIterator.Attribute PAINT_INFO =
         GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO;

    public static final
        AttributedCharacterIterator.Attribute ALT_GLYPH_HANDLER =
        GVTAttributedCharacterIterator.TextAttribute.ALT_GLYPH_HANDLER;

    public static final
        AttributedCharacterIterator.Attribute TEXTPATH
        = GVTAttributedCharacterIterator.TextAttribute.TEXTPATH;

    public static final
        AttributedCharacterIterator.Attribute ANCHOR_TYPE
        = GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE;

    public static final
        AttributedCharacterIterator.Attribute GVT_FONT_FAMILIES
        = GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES;

    public static final
        AttributedCharacterIterator.Attribute GVT_FONTS
        = GVTAttributedCharacterIterator.TextAttribute.GVT_FONTS;

    public static final
        AttributedCharacterIterator.Attribute BASELINE_SHIFT
        = GVTAttributedCharacterIterator.TextAttribute.BASELINE_SHIFT;

    protected AttributedString laidoutText;

    // This is used to track the TextPainterInfo for each element
    // in this text element.
    protected WeakHashMap elemTPI = new WeakHashMap();

    // This is true if any of the spans of this text element
    // use a 'complex' SVG font (meaning the font uses more
    // and just the 'd' attribute on the glyph element.
    // In this case we need to recreate the font when ever
    // CSS attributes change on the text - so we can capture
    // the effects of CSS inheritence.
    protected boolean usingComplexSVGFont = false;

    /**
     * Constructs a new bridge for the &lt;text&gt; element.
     */
    public SVGTextElementBridge() {}

    /**
     * Returns 'text'.
     */
    public String getLocalName() {
        return SVG_TEXT_TAG;
    }

    /**
     * Returns a new instance of this bridge.
     */
    public Bridge getInstance() {
        return new SVGTextElementBridge();
    }

    protected TextNode getTextNode() {
        return (TextNode)node;
    }
    /**
     * Creates a <code>GraphicsNode</code> according to the specified parameters.
     *
     * @param ctx the bridge context to use
     * @param e the element that describes the graphics node to build
     * @return a graphics node that represents the specified element
     */
    public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
        TextNode node = (TextNode)super.createGraphicsNode(ctx, e);
        if (node == null)
            return null;

        associateSVGContext(ctx, e, node);

        // traverse the children to add context on
        // <tspan>, <tref> and <textPath>
        Node child = getFirstChild(e);
        while (child != null) {
            if (child.getNodeType() == Node.ELEMENT_NODE) {
                addContextToChild(ctx,(Element)child);
            }
            child = getNextSibling(child);
        }

        // specify the text painter to use
        if (ctx.getTextPainter() != null)
            node.setTextPainter(ctx.getTextPainter());

        // 'text-rendering' and 'color-rendering'
        RenderingHints hints = null;
        hints = CSSUtilities.convertColorRendering(e, hints);
        hints = CSSUtilities.convertTextRendering (e, hints);
        if (hints != null)
            node.setRenderingHints(hints);

        node.setLocation(getLocation(ctx, e));

        return node;
    }

    /**
     * Creates the GraphicsNode depending on the GraphicsNodeBridge
     * implementation.
     */
    protected GraphicsNode instantiateGraphicsNode() {
        return new TextNode();
    }

    /**
     * Returns the text node location according to the 'x' and 'y'
     * attributes of the specified text element.
     *
     * @param ctx the bridge context to use
     * @param e the text element
     */
    protected Point2D getLocation(BridgeContext ctx, Element e) {
        try {
            SVGOMTextPositioningElement te = (SVGOMTextPositioningElement) e;

            // 'x' attribute - default is 0
            SVGOMAnimatedLengthList _x = (SVGOMAnimatedLengthList) te.getX();
            _x.check();
            SVGLengthList xs = _x.getAnimVal();
            float x = 0;
            if (xs.getNumberOfItems() > 0) {
                x = xs.getItem(0).getValue();
            }

            // 'y' attribute - default is 0
            SVGOMAnimatedLengthList _y = (SVGOMAnimatedLengthList) te.getY();
            _y.check();
            SVGLengthList ys = _y.getAnimVal();
            float y = 0;
            if (ys.getNumberOfItems() > 0) {
                y = ys.getItem(0).getValue();
            }

            return new Point2D.Float(x, y);
        } catch (LiveAttributeException ex) {
            throw new BridgeException(ctx, ex);
        }
    }

    protected boolean isTextElement(Element e) {
        if (!SVG_NAMESPACE_URI.equals(e.getNamespaceURI()))
            return false;
        String nodeName = e.getLocalName();
        return (nodeName.equals(SVG_TEXT_TAG) ||
                nodeName.equals(SVG_TSPAN_TAG) ||
                nodeName.equals(SVG_ALT_GLYPH_TAG) ||
                nodeName.equals(SVG_A_TAG) ||
                nodeName.equals(SVG_TEXT_PATH_TAG) ||
                nodeName.equals(SVG_TREF_TAG));
    }

    protected boolean isTextChild(Element e) {
        if (!SVG_NAMESPACE_URI.equals(e.getNamespaceURI()))
            return false;
        String nodeName = e.getLocalName();
        return (nodeName.equals(SVG_TSPAN_TAG) ||
                nodeName.equals(SVG_ALT_GLYPH_TAG) ||
                nodeName.equals(SVG_A_TAG) ||
                nodeName.equals(SVG_TEXT_PATH_TAG) ||
                nodeName.equals(SVG_TREF_TAG));
    }

    /**
     * Builds using the specified BridgeContext and element, the
     * specified graphics node.
     *
     * @param ctx the bridge context to use
     * @param e the element that describes the graphics node to build
     * @param node the graphics node to build
     */
    public void buildGraphicsNode(BridgeContext ctx,
                                  Element e,
                                  GraphicsNode node) {
        e.normalize();
        computeLaidoutText(ctx, e, node);

        //
        // DO NOT CALL super, 'opacity' is handle during addPaintAttributes()
        //
        // 'opacity'
        node.setComposite(CSSUtilities.convertOpacity(e));
        // 'filter'
        node.setFilter(CSSUtilities.convertFilter(e, node, ctx));
        // 'mask'
        node.setMask(CSSUtilities.convertMask(e, node, ctx));
        // 'clip-path'
        node.setClip(CSSUtilities.convertClipPath(e, node, ctx));
        // 'pointer-events'
        node.setPointerEventType(CSSUtilities.convertPointerEvents(e));

        initializeDynamicSupport(ctx, e, node);
        if (!ctx.isDynamic()) {
            elemTPI.clear();
        }
    }

    /**
     * Returns false as text is not a container.
     */
    public boolean isComposite() {
        return false;
    }

    // Tree navigation ------------------------------------------------------

    /**
     * Returns the first child node of the given node that should be
     * processed by the text bridge.
     */
    protected Node getFirstChild(Node n) {
        return n.getFirstChild();
    }

    /**
     * Returns the next sibling node of the given node that should be
     * processed by the text bridge.
     */
    protected Node getNextSibling(Node n) {
        return n.getNextSibling();
    }

    /**
     * Returns the parent node of the given node that should be
     * processed by the text bridge.
     */
    protected Node getParentNode(Node n) {
        return n.getParentNode();
    }

    // Listener implementation ----------------------------------------------

    /**
     * The DOM EventListener to receive 'DOMNodeRemoved' event.
     */
    protected DOMChildNodeRemovedEventListener childNodeRemovedEventListener;

    /**
     * The DOM EventListener invoked when a node is removed.
     */
    protected class DOMChildNodeRemovedEventListener implements EventListener {

        /**
         * Handles 'DOMNodeRemoved' event type.
         */
        public void handleEvent(Event evt) {
            handleDOMChildNodeRemovedEvent((MutationEvent)evt);
        }
    }

    /**
     * The DOM EventListener to receive 'DOMSubtreeModified' event.
     */
    protected DOMSubtreeModifiedEventListener subtreeModifiedEventListener;

    /**
     * The DOM EventListener invoked when the subtree is modified.
     */
    protected class DOMSubtreeModifiedEventListener implements EventListener {

        /**
         * Handles 'DOMSubtreeModified' event type.
         */
        public void handleEvent(Event evt) {
            handleDOMSubtreeModifiedEvent((MutationEvent)evt);
        }
    }

    // BridgeUpdateHandler implementation -----------------------------------

    /**
     * This method ensures that any modification to a text
     * element and its children is going to be reflected
     * into the GVT tree.
     */
    protected void initializeDynamicSupport(BridgeContext ctx,
                                            Element e,
                                            GraphicsNode node) {
        super.initializeDynamicSupport(ctx, e, node);

        if (ctx.isDynamic()) {
            // Only add the listeners if we are dynamic.
            addTextEventListeners(ctx, (NodeEventTarget) e);
        }
    }

    /**
     * Adds the DOM listeners for this text bridge.
     */
    protected void addTextEventListeners(BridgeContext ctx, NodeEventTarget e) {
        if (childNodeRemovedEventListener == null) {
            childNodeRemovedEventListener =
                new DOMChildNodeRemovedEventListener();
        }
        if (subtreeModifiedEventListener == null) {
            subtreeModifiedEventListener =
                new DOMSubtreeModifiedEventListener();
        }

        //to be notified when a child is removed from the
        //<text> element.
        e.addEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMNodeRemoved",
             childNodeRemovedEventListener, true, null);
        ctx.storeEventListenerNS
            (e, XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMNodeRemoved",
             childNodeRemovedEventListener, true);

        //to be notified when the modification of the subtree
        //of the <text> element is done
        e.addEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMSubtreeModified",
             subtreeModifiedEventListener, false, null);
        ctx.storeEventListenerNS
            (e, XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMSubtreeModified",
             subtreeModifiedEventListener, false);
    }

    /**
     * Removes the DOM listeners for this text bridge.
     */
    protected void removeTextEventListeners(BridgeContext ctx,
                                            NodeEventTarget e) {
        e.removeEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMNodeRemoved",
             childNodeRemovedEventListener, true);
        e.removeEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMSubtreeModified",
             subtreeModifiedEventListener, false);
    }

    /**
     * Disposes this text element bridge by removing the text event listeners
     * that were added in {@link #initializeDynamicSupport}.
     */
    public void dispose() {
        removeTextEventListeners(ctx, (NodeEventTarget) e);
        super.dispose();
    }

    /**
     * Add to the element children of the node, an
     * <code>SVGContext</code> to support dynamic update. This is
     * recursive, the children of the nodes are also traversed to add
     * to the support elements their context
     *
     * @param ctx a <code>BridgeContext</code> value
     * @param e an <code>Element</code> value
     *
     * @see org.apache.batik.dom.svg.SVGContext
     * @see org.apache.batik.bridge.BridgeUpdateHandler
     */
    protected void addContextToChild(BridgeContext ctx, Element e) {
        if (SVG_NAMESPACE_URI.equals(e.getNamespaceURI())) {
            if (e.getLocalName().equals(SVG_TSPAN_TAG)) {
                ((SVGOMElement)e).setSVGContext
                    (new TspanBridge(ctx, this, e));
            } else if (e.getLocalName().equals(SVG_TEXT_PATH_TAG)) {
                ((SVGOMElement)e).setSVGContext
                    (new TextPathBridge(ctx, this, e));
            } else if (e.getLocalName().equals(SVG_TREF_TAG)) {
                ((SVGOMElement)e).setSVGContext
                    (new TRefBridge(ctx, this, e));
            }
        }

        Node child = getFirstChild(e);
        while (child != null) {
            if (child.getNodeType() == Node.ELEMENT_NODE) {
                addContextToChild(ctx, (Element)child);
            }
            child = getNextSibling(child);
        }
    }

    /**
     * From the <code>SVGContext</code> from the element children of the node.
     *
     * @param ctx the <code>BridgeContext</code> for the document
     * @param e the <code>Element</code> whose subtree's elements will have
     *   threir <code>SVGContext</code>s removed
     *
     * @see org.apache.batik.dom.svg.SVGContext
     * @see org.apache.batik.bridge.BridgeUpdateHandler
     */
    protected void removeContextFromChild(BridgeContext ctx, Element e) {
        if (SVG_NAMESPACE_URI.equals(e.getNamespaceURI())) {
            if (e.getLocalName().equals(SVG_TSPAN_TAG)) {
                ((AbstractTextChildBridgeUpdateHandler)
                    ((SVGOMElement) e).getSVGContext()).dispose();
            } else if (e.getLocalName().equals(SVG_TEXT_PATH_TAG)) {
                ((AbstractTextChildBridgeUpdateHandler)
                    ((SVGOMElement) e).getSVGContext()).dispose();
            } else if (e.getLocalName().equals(SVG_TREF_TAG)) {
                ((AbstractTextChildBridgeUpdateHandler)
                    ((SVGOMElement) e).getSVGContext()).dispose();
            }
        }

        Node child = getFirstChild(e);
        while (child != null) {
            if (child.getNodeType() == Node.ELEMENT_NODE) {
                removeContextFromChild(ctx, (Element)child);
            }
            child = getNextSibling(child);
        }
    }

    /**
     * Invoked when an MutationEvent of type 'DOMNodeInserted' is fired.
     */
    public void handleDOMNodeInsertedEvent(MutationEvent evt) {
        Node childNode = (Node)evt.getTarget();

        //check the type of the node inserted before discard the layout
        //in the case of <title> or <desc> or <metadata>, the layout
        //is unchanged
        switch(childNode.getNodeType()) {
            case Node.TEXT_NODE:        // fall-through is intended
            case Node.CDATA_SECTION_NODE:
                laidoutText = null;
                break;
            case Node.ELEMENT_NODE: {
                Element childElement = (Element)childNode;
                if (isTextChild(childElement)) {
                    addContextToChild(ctx, childElement);
                    laidoutText = null;
                }
                break;
            }
        }
        if (laidoutText == null) {
            computeLaidoutText(ctx, e, getTextNode());
        }
    }

    /**
     * Invoked when an MutationEvent of type 'DOMNodeRemoved' is fired.
     */
    public void handleDOMChildNodeRemovedEvent(MutationEvent evt) {
        Node childNode = (Node)evt.getTarget();

        //check the type of the node inserted before discard the layout
        //in the case of <title> or <desc> or <metadata>, the layout
        //is unchanged
        switch (childNode.getNodeType()) {
            case Node.TEXT_NODE:           // fall-through is intended
            case Node.CDATA_SECTION_NODE:
                //the parent has to be a displayed node
                if (isParentDisplayed(childNode)) {
                    laidoutText = null;
                }
                break;
            case Node.ELEMENT_NODE: {
                Element childElt = (Element) childNode;
                if (isTextChild(childElt)) {
                    laidoutText = null;
                    removeContextFromChild(ctx, childElt);
                }
                break;
            }
            default:
        }
        //if the laidoutText was set to null,
        //then wait for DOMSubtreeChange to recompute it.
    }

    /**
     * Invoked when an MutationEvent of type 'DOMSubtree' is fired.
     */
    public void handleDOMSubtreeModifiedEvent(MutationEvent evt) {
        //an operation occured onto the children of the
        //text element, check if the layout was discarded
        if (laidoutText == null) {
            computeLaidoutText(ctx, e, getTextNode());
        }
    }

    /**
     * Invoked when an MutationEvent of type 'DOMCharacterDataModified'
     * is fired.
     */
    public void handleDOMCharacterDataModified(MutationEvent evt){
        Node childNode = (Node)evt.getTarget();
        //if the parent is displayed, then discard the layout.
        if (isParentDisplayed(childNode)) {
            laidoutText = null;
        }
    }

    /**
     * Indicate of the parent of a node is
     * a displayed element.
     * &lt;title&gt;, &lt;desc&gt; and &lt;metadata&gt;
     * are non displayable elements.
     *
     * @return true if the parent of the node is &lt;text&gt;,
     *   &lt;tspan&gt;, &lt;tref&gt;, &lt;textPath&gt;, &lt;a&gt;,
     *   &lt;altGlyph&gt;
     */
    protected boolean isParentDisplayed(Node childNode) {
        Node parentNode = getParentNode(childNode);
        return isTextElement((Element)parentNode);
    }

    /**
     * Recompute the layout of the &lt;text&gt; node.
     *
     * Assign onto the TextNode pending to the element
     * the new recomputed AttributedString. Also
     * update <code>laidoutText</code> with the new
     * value.
     */
    protected void computeLaidoutText(BridgeContext ctx,
                                      Element e,
                                      GraphicsNode node) {
        TextNode tn = (TextNode)node;
        elemTPI.clear();

        AttributedString as = buildAttributedString(ctx, e);
        if (as == null) {
            tn.setAttributedCharacterIterator(null);
            return;
        }

        addGlyphPositionAttributes(as, e, ctx);
        if (ctx.isDynamic()) {
            laidoutText = new AttributedString(as.getIterator());
        }

        // Install the ACI in the text node.
        tn.setAttributedCharacterIterator(as.getIterator());

        // Now get the real paint into - this needs to
        // wait until the text node is laidout so we can get
        // objectBoundingBox info.
        TextPaintInfo pi = new TextPaintInfo();
        setBaseTextPaintInfo(pi, e, node, ctx);
        // This get's Overline/underline info.
        setDecorationTextPaintInfo(pi, e);
        // Install the attributes.
        addPaintAttributes(as, e, tn, pi, ctx);

        if (usingComplexSVGFont) {
            // Force Complex SVG fonts to be recreated, if we have them.
            tn.setAttributedCharacterIterator(as.getIterator());
        }

        if (ctx.isDynamic()) {
            checkBBoxChange();
        }
    }

    /**
     * This flag bit indicates if a new ACI has been created in
     * response to a CSSEngineEvent.
     * Avoid creating one ShapePainter per CSS property change
     */
    private boolean hasNewACI;

    /**
     * This is the element a CSS property has changed.
     */
    private Element cssProceedElement;

    /**
     * Invoked when the animated value of an animatable attribute has changed.
     */
    public void handleAnimatedAttributeChanged
            (AnimatedLiveAttributeValue alav) {
        if (alav.getNamespaceURI() == null) {
            String ln = alav.getLocalName();
            if (ln.equals(SVG_X_ATTRIBUTE)
                    || ln.equals(SVG_Y_ATTRIBUTE)
                    || ln.equals(SVG_DX_ATTRIBUTE)
                    || ln.equals(SVG_DY_ATTRIBUTE)
                    || ln.equals(SVG_ROTATE_ATTRIBUTE)
                    || ln.equals(SVG_TEXT_LENGTH_ATTRIBUTE)
                    || ln.equals(SVG_LENGTH_ADJUST_ATTRIBUTE)) {
                char c = ln.charAt(0);
                if (c == 'x' || c == 'y') {
                    getTextNode().setLocation(getLocation(ctx, e));
                }
                computeLaidoutText(ctx, e, getTextNode());
                return;
            }
        }
        super.handleAnimatedAttributeChanged(alav);
    }

    /**
     * Invoked when CSS properties have changed on an element.
     *
     * @param evt the CSSEngine event that describes the update
     */
    public void handleCSSEngineEvent(CSSEngineEvent evt) {
        hasNewACI = false;
        int [] properties = evt.getProperties();
        // first try to find CSS properties that change the layout
        for (int property : properties) {
            switch (property) {         // fall-through is intended
                case SVGCSSEngine.BASELINE_SHIFT_INDEX:
                case SVGCSSEngine.DIRECTION_INDEX:
                case SVGCSSEngine.DISPLAY_INDEX:
                case SVGCSSEngine.FONT_FAMILY_INDEX:
                case SVGCSSEngine.FONT_SIZE_INDEX:
                case SVGCSSEngine.FONT_STRETCH_INDEX:
                case SVGCSSEngine.FONT_STYLE_INDEX:
                case SVGCSSEngine.FONT_WEIGHT_INDEX:
                case SVGCSSEngine.GLYPH_ORIENTATION_HORIZONTAL_INDEX:
                case SVGCSSEngine.GLYPH_ORIENTATION_VERTICAL_INDEX:
                case SVGCSSEngine.KERNING_INDEX:
                case SVGCSSEngine.LETTER_SPACING_INDEX:
                case SVGCSSEngine.TEXT_ANCHOR_INDEX:
                case SVGCSSEngine.UNICODE_BIDI_INDEX:
                case SVGCSSEngine.WORD_SPACING_INDEX:
                case SVGCSSEngine.WRITING_MODE_INDEX: {
                    if (!hasNewACI) {
                        hasNewACI = true;
                        computeLaidoutText(ctx, e, getTextNode());
                    }
                    break;
                }
            }
        }
        //optimize the calculation of
        //the painting attributes and decoration
        //by only recomputing the section for the element
        cssProceedElement = evt.getElement();
        // go for the other CSS properties
        super.handleCSSEngineEvent(evt);
        cssProceedElement = null;
    }

    /**
     * Invoked for each CSS property that has changed.
     */
    protected void handleCSSPropertyChanged(int property) {
        switch(property) {                  // fall-through is intended
        case SVGCSSEngine.FILL_INDEX:
        case SVGCSSEngine.FILL_OPACITY_INDEX:
        case SVGCSSEngine.STROKE_INDEX:
        case SVGCSSEngine.STROKE_OPACITY_INDEX:
        case SVGCSSEngine.STROKE_WIDTH_INDEX:
        case SVGCSSEngine.STROKE_LINECAP_INDEX:
        case SVGCSSEngine.STROKE_LINEJOIN_INDEX:
        case SVGCSSEngine.STROKE_MITERLIMIT_INDEX:
        case SVGCSSEngine.STROKE_DASHARRAY_INDEX:
        case SVGCSSEngine.STROKE_DASHOFFSET_INDEX:
        case SVGCSSEngine.TEXT_DECORATION_INDEX:
            rebuildACI();
            break;

        case SVGCSSEngine.VISIBILITY_INDEX:
            rebuildACI();
            super.handleCSSPropertyChanged(property);
            break;
        case SVGCSSEngine.TEXT_RENDERING_INDEX: {
            RenderingHints hints = node.getRenderingHints();
            hints = CSSUtilities.convertTextRendering(e, hints);
            if (hints != null) {
                node.setRenderingHints(hints);
            }
            break;
        }
        case SVGCSSEngine.COLOR_RENDERING_INDEX: {
            RenderingHints hints = node.getRenderingHints();
            hints = CSSUtilities.convertColorRendering(e, hints);
            if (hints != null) {
                node.setRenderingHints(hints);
            }
            break;
        }
        default:
            super.handleCSSPropertyChanged(property);
        }
    }

    protected void rebuildACI() {
        if (hasNewACI)
            return;

        TextNode textNode = getTextNode();
        if (textNode.getAttributedCharacterIterator() == null)
            return;

        TextPaintInfo pi, oldPI;
        if ( cssProceedElement == e ){
            pi = new TextPaintInfo();
            setBaseTextPaintInfo(pi, e, node, ctx);
            setDecorationTextPaintInfo(pi, e);
            oldPI = (TextPaintInfo)elemTPI.get(e);
        } else {
            //if a child CSS property has changed, then
            //retrieve the parent text decoration
            //and only update the section of the AtrtibutedString of
            //the child
            TextPaintInfo parentPI;
            parentPI = getParentTextPaintInfo(cssProceedElement);
            pi = getTextPaintInfo(cssProceedElement, textNode, parentPI, ctx);
            oldPI = (TextPaintInfo)elemTPI.get(cssProceedElement);
        }
        if (oldPI == null) return;

        textNode.swapTextPaintInfo(pi, oldPI);
        if (usingComplexSVGFont)
            // Force Complex SVG fonts to be recreated
            textNode.setAttributedCharacterIterator
                (textNode.getAttributedCharacterIterator());
    }

    int getElementStartIndex(Element element) {
        TextPaintInfo tpi = (TextPaintInfo)elemTPI.get(element);
        if (tpi == null) return -1;
        return tpi.startChar;
    }

    int getElementEndIndex(Element element) {
        TextPaintInfo tpi = (TextPaintInfo)elemTPI.get(element);
        if (tpi == null) return -1;
        return tpi.endChar;
    }

    // -----------------------------------------------------------------------
    // -----------------------------------------------------------------------
    // -----------------------------------------------------------------------
    // -----------------------------------------------------------------------

    /**
     * Creates the attributed string which represents the given text
     * element children.
     *
     * @param ctx the bridge context to use
     * @param element the text element
     */
    protected AttributedString buildAttributedString(BridgeContext ctx,
                                                     Element element) {

        AttributedStringBuffer asb = new AttributedStringBuffer();
        fillAttributedStringBuffer(ctx, element, true, null, null, null, asb);
        return asb.toAttributedString();
    }


    /**
     * This is used to store the end of the last piece of text
     * content from an element with xml:space="preserve".  When
     * we are stripping trailing spaces we need to make sure
     * we don't strip anything before this point.
     */
    protected int endLimit;

    /**
     * Fills the given AttributedStringBuffer.
     */
    protected void fillAttributedStringBuffer(BridgeContext ctx,
                                              Element element,
                                              boolean top,
                                              TextPath textPath,
                                              Integer bidiLevel,
                                              Map initialAttributes,
                                              AttributedStringBuffer asb) {
        // 'requiredFeatures', 'requiredExtensions', 'systemLanguage' &
        // 'display="none".
        if ((!SVGUtilities.matchUserAgent(element, ctx.getUserAgent())) ||
            (!CSSUtilities.convertDisplay(element))) {
            return;
        }

        String s = XMLSupport.getXMLSpace(element);
        boolean preserve = s.equals(SVG_PRESERVE_VALUE);
        boolean prevEndsWithSpace;
        Element nodeElement = element;
        int elementStartChar = asb.length();

        if (top) {
            endLimit = 0;
        }
        if (preserve) {
            endLimit = asb.length();
        }

        Map map = initialAttributes == null
                ? new HashMap()
                : new HashMap(initialAttributes);
        initialAttributes =
            getAttributeMap(ctx, element, textPath, bidiLevel, map);
        Object o = map.get(TextAttribute.BIDI_EMBEDDING);
        Integer subBidiLevel = bidiLevel;
        if (o != null) {
            subBidiLevel = (Integer) o;
        }

        for (Node n = getFirstChild(element);
             n != null;
             n = getNextSibling(n)) {

            if (preserve) {
                prevEndsWithSpace = false;
            } else {
                if (asb.length() == 0) {
                    prevEndsWithSpace = true;
                } else {
                    prevEndsWithSpace = (asb.getLastChar() == ' ');
                }
            }

            switch (n.getNodeType()) {
            case Node.ELEMENT_NODE:
                if (!SVG_NAMESPACE_URI.equals(n.getNamespaceURI()))
                    break;

                nodeElement = (Element)n;

                String ln = n.getLocalName();

                if (ln.equals(SVG_TSPAN_TAG) ||
                    ln.equals(SVG_ALT_GLYPH_TAG)) {
                    int before = asb.count;
                    fillAttributedStringBuffer(ctx,
                                               nodeElement,
                                               false,
                                               textPath,
                                               subBidiLevel,
                                               initialAttributes,
                                               asb);
                    if (asb.count != before) {
                        initialAttributes = null;
                    }
                } else if (ln.equals(SVG_TEXT_PATH_TAG)) {
                    SVGTextPathElementBridge textPathBridge
                        = (SVGTextPathElementBridge)ctx.getBridge(nodeElement);
                    TextPath newTextPath
                        = textPathBridge.createTextPath(ctx, nodeElement);
                    if (newTextPath != null) {
                        int before = asb.count;
                        fillAttributedStringBuffer(ctx,
                                                   nodeElement,
                                                   false,
                                                   newTextPath,
                                                   subBidiLevel,
                                                   initialAttributes,
                                                   asb);
                        if (asb.count != before) {
                            initialAttributes = null;
                        }
                    }
                } else if (ln.equals(SVG_TREF_TAG)) {
                    String uriStr = XLinkSupport.getXLinkHref((Element)n);
                    Element ref = ctx.getReferencedElement((Element)n, uriStr);
                    s = TextUtilities.getElementContent(ref);
                    s = normalizeString(s, preserve, prevEndsWithSpace);
                    if (s.length() != 0) {
                        int trefStart = asb.length();
                        Map m = initialAttributes == null
                                ? new HashMap()
                                : new HashMap(initialAttributes);
                        getAttributeMap
                            (ctx, nodeElement, textPath, bidiLevel, m);
                        asb.append(s, m);
                        int trefEnd = asb.length() - 1;
                        TextPaintInfo tpi;
                        tpi = (TextPaintInfo)elemTPI.get(nodeElement);
                        tpi.startChar = trefStart;
                        tpi.endChar   = trefEnd;
                        initialAttributes = null;
                    }
                } else if (ln.equals(SVG_A_TAG)) {
                    NodeEventTarget target = (NodeEventTarget)nodeElement;
                    UserAgent ua = ctx.getUserAgent();
                    SVGAElementBridge.CursorHolder ch;
                    ch = new SVGAElementBridge.CursorHolder
                        (CursorManager.DEFAULT_CURSOR);
                    EventListener l;
                    l = new SVGAElementBridge.AnchorListener(ua, ch);
                    target.addEventListenerNS
                        (XMLConstants.XML_EVENTS_NAMESPACE_URI,
                         SVG_EVENT_CLICK, l, false, null);
                    ctx.storeEventListenerNS
                        (target, XMLConstants.XML_EVENTS_NAMESPACE_URI,
                         SVG_EVENT_CLICK, l, false);

                    int before = asb.count;
                    fillAttributedStringBuffer(ctx,
                                               nodeElement,
                                               false,
                                               textPath,
                                               subBidiLevel,
                                               initialAttributes,
                                               asb);
                    if (asb.count != before) {
                        initialAttributes = null;
                    }
                }
                break;
            case Node.TEXT_NODE:                     // fall-through is intended
            case Node.CDATA_SECTION_NODE:
                s = n.getNodeValue();
                s = normalizeString(s, preserve, prevEndsWithSpace);
                if (s.length() != 0) {
                    asb.append(s, map);
                    if (preserve) {
                        endLimit = asb.length();
                    }
                    initialAttributes = null;
                }
            }
        }

        if (top) {
            boolean strippedSome = false;
            while ((endLimit < asb.length()) && (asb.getLastChar() == ' ')) {
                asb.stripLast();
                strippedSome = true;
            }
            if (strippedSome) {
                for (Object o1 : elemTPI.values()) {
                    TextPaintInfo tpi = (TextPaintInfo) o1;
                    if (tpi.endChar >= asb.length()) {
                        tpi.endChar = asb.length() - 1;
                        if (tpi.startChar > tpi.endChar)
                            tpi.startChar = tpi.endChar;
                    }
                }
            }
        }
        int elementEndChar = asb.length()-1;
        TextPaintInfo tpi = (TextPaintInfo)elemTPI.get(element);
        tpi.startChar = elementStartChar;
        tpi.endChar   = elementEndChar;
    }

    /**
     * Normalizes the given string.
     */
    protected String normalizeString(String s,
                                     boolean preserve,
                                     boolean stripfirst) {
        StringBuffer sb = new StringBuffer(s.length());
        if (preserve) {
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                switch (c) {                // fall-through is intended
                case 10:
                case 13:
                case '\t':
                    sb.append(' ');
                    break;
                default:
                    sb.append(c);
                }
            }
            return sb.toString();
        }

        int idx = 0;
        if (stripfirst) {
            loop: while (idx < s.length()) {
                switch (s.charAt(idx)) {
                default:
                    break loop;
                case 10:                   // fall-through is intended
                case 13:
                case ' ':
                case '\t':
                    idx++;
                }
            }
        }

        boolean space = false;
        for (int i = idx; i < s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
            case 10:                      // fall-through is intended
            case 13:
                break;
            case ' ':                     // fall-through is intended
            case '\t':
                if (!space) {
                    sb.append(' ');
                    space = true;
                }
                break;
            default:
                sb.append(c);
                space = false;
            }
        }

        return sb.toString();
    }

    /**
     * This class is used to build an AttributedString.
     */
    protected static class AttributedStringBuffer {

        /**
         * The strings.
         */
        protected List strings;

        /**
         * The attributes.
         */
        protected List attributes;

        /**
         * The number of items.
         */
        protected int count;

        /**
         * The length of the attributed string.
         */
        protected int length;

        /**
         * Creates a new empty AttributedStringBuffer.
         */
        public AttributedStringBuffer() {
            strings    = new ArrayList();
            attributes = new ArrayList();
            count      = 0;
            length     = 0;
        }

        /**
         * Tells whether this AttributedStringBuffer is empty.
         */
        public boolean isEmpty() {
            return count == 0;
        }

        /**
         * Returns the length in chars of the current Attributed String
         */
        public int length() {
            return length;
        }

        /**
         * Appends a String and its associated attributes.
         */
        public void append(String s, Map m) {
            if (s.length() == 0) return;
            strings.add(s);
            attributes.add(m);
            count++;
            length += s.length();
        }

        /**
         * Returns the value of the last char or -1.
         */
        public int getLastChar() {
            if (count == 0) {
                return -1;
            }
            String s = (String)strings.get(count - 1);
            return s.charAt(s.length() - 1);
        }

        /**
         * Strips the last string character.
         */
        public void stripFirst() {
            String s = (String)strings.get(0);
            if (s.charAt(s.length() - 1) != ' ')
                return;

            length--;

            if (s.length() == 1) {
                attributes.remove(0);
                strings.remove(0);
                count--;
                return;
            }

            strings.set(0, s.substring(1));
        }

        /**
         * Strips the last string character.
         */
        public void stripLast() {
            String s = (String)strings.get(count - 1);
            if (s.charAt(s.length() - 1) != ' ')
                return;

            length--;

            if (s.length() == 1) {
                attributes.remove(--count);
                strings.remove(count);
                return;
            }

            strings.set(count-1, s.substring(0, s.length() - 1));
        }

        /**
         * Builds an attributed string from the content of this
         * buffer.
         */
        public AttributedString toAttributedString() {
            switch (count) {
            case 0:
                return null;
            case 1:
                return new AttributedString((String)strings.get(0),
                                            (Map)attributes.get(0));
            }

            StringBuffer sb = new StringBuffer( strings.size() * 5 );
            for (Object string : strings) {
                sb.append((String) string);
            }

            AttributedString result = new AttributedString(sb.toString());

            // Set the attributes

            Iterator sit = strings.iterator();
            Iterator ait = attributes.iterator();
            int idx = 0;
            while (sit.hasNext()) {
                String s = (String)sit.next();
                int nidx = idx + s.length();
                Map m = (Map)ait.next();
                Iterator kit = m.keySet().iterator();
                Iterator vit = m.values().iterator();
                while (kit.hasNext()) {
                    Attribute attr = (Attribute)kit.next();
                    Object val = vit.next();
                    result.addAttribute(attr, val, idx, nidx);
                }
                idx = nidx;
            }

            return result;
        }

        public String toString() {
            switch (count) {
            case 0:
                return "";
            case 1:
                return (String)strings.get(0);
            }

            StringBuffer sb = new StringBuffer( strings.size() * 5 );
            for (Object string : strings) {
                sb.append((String) string);
            }
            return sb.toString();
        }
    }

    /**
     * Returns true if node1 is an ancestor of node2
     */
    protected boolean nodeAncestorOf(Node node1, Node node2) {
        if (node2 == null || node1 == null) {
            return false;
        }
        Node parent = getParentNode(node2);
        while (parent != null && parent != node1) {
            parent = getParentNode(parent);
        }
        return (parent == node1);
    }


    /**
     * Adds glyph position attributes to an AttributedString.
     */
    protected void addGlyphPositionAttributes(AttributedString as,
                                              Element element,
                                              BridgeContext ctx) {

        // 'requiredFeatures', 'requiredExtensions' and 'systemLanguage'
        if ((!SVGUtilities.matchUserAgent(element, ctx.getUserAgent())) ||
            (!CSSUtilities.convertDisplay(element))) {
            return;
        }
        if (element.getLocalName().equals(SVG_TEXT_PATH_TAG)) {
            // 'textPath' doesn't support position attributes.
            addChildGlyphPositionAttributes(as, element, ctx);
            return;
        }

        // calculate which chars in the string belong to this element
        int firstChar = getElementStartIndex(element);
        // No match so no chars to annotate.
        if (firstChar == -1) return;

        int lastChar = getElementEndIndex(element);

        // 'a' elements aren't SVGTextPositioningElements, so don't process
        // their positioning attributes on them.
        if (!(element instanceof SVGTextPositioningElement)) {
            addChildGlyphPositionAttributes(as, element, ctx);
            return;
        }

        // get all of the glyph position attribute values
        SVGTextPositioningElement te = (SVGTextPositioningElement) element;

        try {
            SVGOMAnimatedLengthList _x =
                (SVGOMAnimatedLengthList) te.getX();
            _x.check();
            SVGOMAnimatedLengthList _y =
                (SVGOMAnimatedLengthList) te.getY();
            _y.check();
            SVGOMAnimatedLengthList _dx =
                (SVGOMAnimatedLengthList) te.getDx();
            _dx.check();
            SVGOMAnimatedLengthList _dy =
                (SVGOMAnimatedLengthList) te.getDy();
            _dy.check();
            SVGOMAnimatedNumberList _rotate =
                (SVGOMAnimatedNumberList) te.getRotate();
            _rotate.check();

            SVGLengthList xs  = _x.getAnimVal();
            SVGLengthList ys  = _y.getAnimVal();
            SVGLengthList dxs = _dx.getAnimVal();
            SVGLengthList dys = _dy.getAnimVal();
            SVGNumberList rs  = _rotate.getAnimVal();

            int len;

            // process the x attribute
            len = xs.getNumberOfItems();
            for (int i = 0; i < len && firstChar + i <= lastChar; i++) {
                as.addAttribute
                    (GVTAttributedCharacterIterator.TextAttribute.X,
                            xs.getItem(i).getValue(), firstChar + i,
                               firstChar + i + 1);
            }

            // process the y attribute
            len = ys.getNumberOfItems();
            for (int i = 0; i < len && firstChar + i <= lastChar; i++) {
                as.addAttribute
                    (GVTAttributedCharacterIterator.TextAttribute.Y,
                            ys.getItem(i).getValue(), firstChar + i,
                               firstChar + i + 1);
            }

            // process dx attribute
            len = dxs.getNumberOfItems();
            for (int i = 0; i < len && firstChar + i <= lastChar; i++) {
                as.addAttribute
                    (GVTAttributedCharacterIterator.TextAttribute.DX,
                            dxs.getItem(i).getValue(), firstChar + i,
                               firstChar + i + 1);
            }

            // process dy attribute
            len = dys.getNumberOfItems();
            for (int i = 0; i < len && firstChar + i <= lastChar; i++) {
                as.addAttribute
                    (GVTAttributedCharacterIterator.TextAttribute.DY,
                            dys.getItem(i).getValue(), firstChar + i,
                               firstChar + i + 1);
            }

            // process rotate attribute
            len = rs.getNumberOfItems();
            if (len == 1) {  // not a list
                // each char will have the same rotate value
                Float rad = (float) Math.toRadians(rs.getItem(0).getValue());
                as.addAttribute
                    (GVTAttributedCharacterIterator.TextAttribute.ROTATION,
                     rad, firstChar, lastChar + 1);

            } else if (len > 1) {  // it's a list
                // set each rotate value from the list
                for (int i = 0; i < len && firstChar + i <= lastChar; i++) {
                    Float rad = (float) Math.toRadians(rs.getItem(i).getValue());
                    as.addAttribute
                        (GVTAttributedCharacterIterator.TextAttribute.ROTATION,
                         rad, firstChar + i, firstChar + i + 1);
                }
            }

            addChildGlyphPositionAttributes(as, element, ctx);
        } catch (LiveAttributeException ex) {
            throw new BridgeException(ctx, ex);
        }
    }

    protected void addChildGlyphPositionAttributes(AttributedString as,
                                                   Element element,
                                                   BridgeContext ctx) {
        // do the same for each child element
        for (Node child = getFirstChild(element);
             child != null;
             child = getNextSibling(child)) {
            if (child.getNodeType() != Node.ELEMENT_NODE) continue;

            Element childElement = (Element)child;
            if (isTextChild(childElement)) {
                addGlyphPositionAttributes(as, childElement, ctx);
            }
        }
    }

    /**
     * Adds painting attributes to an AttributedString.
     */
    protected void addPaintAttributes(AttributedString as,
                                      Element element,
                                      TextNode node,
                                      TextPaintInfo pi,
                                      BridgeContext ctx) {
        // 'requiredFeatures', 'requiredExtensions' and 'systemLanguage'
        if ((!SVGUtilities.matchUserAgent(element, ctx.getUserAgent())) ||
            (!CSSUtilities.convertDisplay(element))) {
            return;
        }
        Object o = elemTPI.get(element);
        if (o != null) {
            node.swapTextPaintInfo(pi, (TextPaintInfo)o);
        }
        addChildPaintAttributes(as, element, node, pi, ctx);
    }

    protected void addChildPaintAttributes(AttributedString as,
                                           Element element,
                                           TextNode node,
                                           TextPaintInfo parentPI,
                                           BridgeContext ctx) {
        // Add Paint attributres for children of text element
        for (Node child = getFirstChild(element);
             child != null;
             child = getNextSibling(child)) {
            if (child.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            Element childElement = (Element)child;
            if (isTextChild(childElement)) {
                TextPaintInfo pi = getTextPaintInfo(childElement, node,
                                                        parentPI, ctx);
                addPaintAttributes(as, childElement, node, pi, ctx);
            }
        }
    }

    /**
     * This method adds all the font related properties to <code>result</code>
     * It also builds a List of the GVTFonts and returns it.
     */
    protected List getFontList(BridgeContext ctx,
                               Element       element,
                               Map           result) {

        // Unique value for text element - used for run identification.
        result.put(TEXT_COMPOUND_ID, new SoftReference(element));

        Float fsFloat = TextUtilities.convertFontSize(element);
        float fontSize = fsFloat;
        // Font size.
        result.put(TextAttribute.SIZE, fsFloat);

        // Font stretch
        result.put(TextAttribute.WIDTH,
                TextUtilities.convertFontStretch(element));

        // Font style
        result.put(TextAttribute.POSTURE,
                TextUtilities.convertFontStyle(element));

        // Font weight
        result.put(TextAttribute.WEIGHT,
                TextUtilities.convertFontWeight(element));

        // Font weight
        Value v = CSSUtilities.getComputedStyle
            (element, SVGCSSEngine.FONT_WEIGHT_INDEX);
        String fontWeightString = v.getCssText();

        // Font style
        String fontStyleString = CSSUtilities.getComputedStyle
            (element, SVGCSSEngine.FONT_STYLE_INDEX).getStringValue();

        // Needed for SVG fonts (also for dynamic documents).
        result.put(TEXT_COMPOUND_DELIMITER, element);

        //  make a list of GVTFont objects
        Value val = CSSUtilities.getComputedStyle
            (element, SVGCSSEngine.FONT_FAMILY_INDEX);
        List fontFamilyList = new ArrayList();
        List fontList = new ArrayList();
        int len = val.getLength();
        for (int i = 0; i < len; i++) {
            Value it = val.item(i);
            String fontFamilyName = it.getStringValue();
            GVTFontFamily fontFamily;
            fontFamily = SVGFontUtilities.getFontFamily(element, ctx, fontFamilyName,
                    fontWeightString, fontStyleString);
            if (fontFamily != null && fontFamily instanceof UnresolvedFontFamily) {
                fontFamily = ctx.getFontFamilyResolver().resolve(fontFamily.getFamilyName());
            }
            if (fontFamily == null) {
                continue;
            }
            fontFamilyList.add(fontFamily);
            if (fontFamily.isComplex()) {
                usingComplexSVGFont = true;
            }
            GVTFont ft = fontFamily.deriveFont(fontSize, result);
            fontList.add(ft);
        }

        // Eventually this will need to go for SVG fonts it
        // holds hard ref to DOM.
        result.put(GVT_FONT_FAMILIES, fontFamilyList);

        if (!ctx.isDynamic()) {
            // Only leave this in the map for dynamic documents.
            // Otherwise it will cause the whole DOM to stay when
            // we don't really need it.
            result.remove(TEXT_COMPOUND_DELIMITER);
        }
        return fontList;
    }

    /**
     * Returns the map to pass to the current characters.
     *
     * @param ctx the BridgeContext to use for throwing exceptions
     * @param element the text element whose attributes are being collected
     * @param textPath the text path that the characters of <code>element</code>
     *     will be placed along
     * @param bidiLevel the bidi level of <code>element</code>
     * @param result a Map into which the attributes of <code>element</code>'s
     *     characters will be stored
     * @return a new Map that contains the attributes that must be inherited
     *     into a child element if the given element has no characters before
     *     the child element
     */
    protected Map getAttributeMap(BridgeContext ctx,
                                  Element element,
                                  TextPath textPath,
                                  Integer bidiLevel,
                                  Map result) {
        SVGTextContentElement tce = null;
        if (element instanceof SVGTextContentElement) {
            // 'a' elements aren't SVGTextContentElements, so they shouldn't
            // be checked for 'textLength' or 'lengthAdjust' attributes.
            tce = (SVGTextContentElement) element;
        }

        Map inheritMap = null;
        String s;

        if (SVG_NAMESPACE_URI.equals(element.getNamespaceURI()) &&
            element.getLocalName().equals(SVG_ALT_GLYPH_TAG)) {
            result.put(ALT_GLYPH_HANDLER,
                       new SVGAltGlyphHandler(ctx, element));
        }

        // Add null TPI objects to the text (after we set it on the
        // Text we will swap in the correct values.
        TextPaintInfo pi = new TextPaintInfo();
        // Set some basic props so we can get bounds info for complex paints.
        pi.visible   = true;
        pi.fillPaint = Color.black;
        result.put(PAINT_INFO, pi);
        elemTPI.put(element, pi);

        if (textPath != null) {
            result.put(TEXTPATH, textPath);
        }

        // Text-anchor
        TextNode.Anchor a = TextUtilities.convertTextAnchor(element);
        result.put(ANCHOR_TYPE, a);

        // Font family
        List fontList = getFontList(ctx, element, result);
        result.put(GVT_FONTS, fontList);


        // Text baseline adjustment.
        Object bs = TextUtilities.convertBaselineShift(element);
        if (bs != null) {
            result.put(BASELINE_SHIFT, bs);
        }

        // Unicode-bidi mode
        Value val =  CSSUtilities.getComputedStyle
            (element, SVGCSSEngine.UNICODE_BIDI_INDEX);
        s = val.getStringValue();
        if (s.charAt(0) == 'n') {
            if (bidiLevel != null)
                result.put(TextAttribute.BIDI_EMBEDDING, bidiLevel);
        } else {

            // Text direction
            // XXX: this needs to coordinate with the unicode-bidi
            // property, so that when an explicit reversal
            // occurs, the BIDI_EMBEDDING level is
            // appropriately incremented or decremented.
            // Note that direction is implicitly handled by unicode
            // BiDi algorithm in most cases, this property
            // is only needed when one wants to override the
            // normal writing direction for a string/substring.

            val = CSSUtilities.getComputedStyle
                (element, SVGCSSEngine.DIRECTION_INDEX);
            String rs = val.getStringValue();
            int cbidi = 0;
            if (bidiLevel != null) cbidi = bidiLevel;

            // We don't care if it was embed or override we just want
            // it's level here. So map override to positive value.
            if (cbidi < 0) cbidi = -cbidi;

            switch (rs.charAt(0)) {
            case 'l':
                result.put(TextAttribute.RUN_DIRECTION,
                           TextAttribute.RUN_DIRECTION_LTR);
                if ((cbidi & 0x1) == 1) cbidi++; // was odd now even
                else                    cbidi+=2; // next greater even number
                break;
            case 'r':
                result.put(TextAttribute.RUN_DIRECTION,
                           TextAttribute.RUN_DIRECTION_RTL);
                if ((cbidi & 0x1) == 1) cbidi+=2; // next greater odd number
                else                    cbidi++; // was even now odd
                break;
            }

            switch (s.charAt(0)) {
            case 'b': // bidi-override
                cbidi = -cbidi; // For bidi-override we want a negative number.
                break;
            }

            result.put(TextAttribute.BIDI_EMBEDDING, cbidi);
        }

        // Writing mode

        val = CSSUtilities.getComputedStyle
            (element, SVGCSSEngine.WRITING_MODE_INDEX);
        s = val.getStringValue();
        switch (s.charAt(0)) {
        case 'l':
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.WRITING_MODE,
                       GVTAttributedCharacterIterator.
                       TextAttribute.WRITING_MODE_LTR);
            break;
        case 'r':
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.WRITING_MODE,
                       GVTAttributedCharacterIterator.
                       TextAttribute.WRITING_MODE_RTL);
            break;
        case 't':
                result.put(GVTAttributedCharacterIterator.
                       TextAttribute.WRITING_MODE,
                       GVTAttributedCharacterIterator.
                       TextAttribute.WRITING_MODE_TTB);
            break;
        }

        // glyph-orientation-vertical

        val = CSSUtilities.getComputedStyle
            (element, SVGCSSEngine.GLYPH_ORIENTATION_VERTICAL_INDEX);
        int primitiveType = val.getPrimitiveType();
        switch ( primitiveType ) {
        case CSSPrimitiveValue.CSS_IDENT: // auto
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.VERTICAL_ORIENTATION,
                       GVTAttributedCharacterIterator.
                       TextAttribute.ORIENTATION_AUTO);
            break;
        case CSSPrimitiveValue.CSS_DEG:
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.VERTICAL_ORIENTATION,
                       GVTAttributedCharacterIterator.
                       TextAttribute.ORIENTATION_ANGLE);
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.VERTICAL_ORIENTATION_ANGLE,
                    val.getFloatValue());
            break;
        case CSSPrimitiveValue.CSS_RAD:
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.VERTICAL_ORIENTATION,
                       GVTAttributedCharacterIterator.
                       TextAttribute.ORIENTATION_ANGLE);
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.VERTICAL_ORIENTATION_ANGLE,
                    (float) Math.toDegrees(val.getFloatValue()));
            break;
        case CSSPrimitiveValue.CSS_GRAD:
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.VERTICAL_ORIENTATION,
                       GVTAttributedCharacterIterator.
                       TextAttribute.ORIENTATION_ANGLE);
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.VERTICAL_ORIENTATION_ANGLE,
                    val.getFloatValue() * 9 / 5);
            break;
        default:
            // Cannot happen
            throw new IllegalStateException("unexpected primitiveType (V):" + primitiveType );
        }

        // glyph-orientation-horizontal

        val = CSSUtilities.getComputedStyle
            (element, SVGCSSEngine.GLYPH_ORIENTATION_HORIZONTAL_INDEX);
        primitiveType = val.getPrimitiveType();
        switch ( primitiveType ) {
        case CSSPrimitiveValue.CSS_DEG:
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.HORIZONTAL_ORIENTATION_ANGLE,
                    val.getFloatValue());
            break;
        case CSSPrimitiveValue.CSS_RAD:
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.HORIZONTAL_ORIENTATION_ANGLE,
                    (float) Math.toDegrees(val.getFloatValue()));
            break;
        case CSSPrimitiveValue.CSS_GRAD:
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.HORIZONTAL_ORIENTATION_ANGLE,
                    val.getFloatValue() * 9 / 5);
            break;
        default:
            // Cannot happen
            throw new IllegalStateException("unexpected primitiveType (H):" + primitiveType );
        }

        // text spacing properties...

        // Letter Spacing
        Float sp = TextUtilities.convertLetterSpacing(element);
        if (sp != null) {
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.LETTER_SPACING,
                       sp);
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.CUSTOM_SPACING,
                       Boolean.TRUE);
        }

        // Word spacing
        sp = TextUtilities.convertWordSpacing(element);
        if (sp != null) {
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.WORD_SPACING,
                       sp);
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.CUSTOM_SPACING,
                       Boolean.TRUE);
        }

        // Kerning
        sp = TextUtilities.convertKerning(element);
        if (sp != null) {
            result.put(GVTAttributedCharacterIterator.TextAttribute.KERNING,
                       sp);
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.CUSTOM_SPACING,
                       Boolean.TRUE);
        }

        if (tce == null) {
            return inheritMap;
        }

        try {
            // textLength
            AbstractSVGAnimatedLength textLength =
                (AbstractSVGAnimatedLength) tce.getTextLength();
            if (textLength.isSpecified()) {
                if (inheritMap == null) {
                    inheritMap = new HashMap();
                }

                Object value = textLength.getCheckedValue();
                result.put
                    (GVTAttributedCharacterIterator.TextAttribute.BBOX_WIDTH,
                     value);
                inheritMap.put
                    (GVTAttributedCharacterIterator.TextAttribute.BBOX_WIDTH,
                     value);

                // lengthAdjust
                SVGOMAnimatedEnumeration _lengthAdjust =
                    (SVGOMAnimatedEnumeration) tce.getLengthAdjust();
                if (_lengthAdjust.getCheckedVal() ==
                        SVGTextContentElement.LENGTHADJUST_SPACINGANDGLYPHS) {
                    result.put(GVTAttributedCharacterIterator.
                               TextAttribute.LENGTH_ADJUST,
                               GVTAttributedCharacterIterator.
                               TextAttribute.ADJUST_ALL);
                    inheritMap.put(GVTAttributedCharacterIterator.
                                   TextAttribute.LENGTH_ADJUST,
                                   GVTAttributedCharacterIterator.
                                   TextAttribute.ADJUST_ALL);
                } else {
                    result.put(GVTAttributedCharacterIterator.
                               TextAttribute.LENGTH_ADJUST,
                               GVTAttributedCharacterIterator.
                               TextAttribute.ADJUST_SPACING);
                    inheritMap.put(GVTAttributedCharacterIterator.
                                   TextAttribute.LENGTH_ADJUST,
                                   GVTAttributedCharacterIterator.
                                   TextAttribute.ADJUST_SPACING);
                    result.put(GVTAttributedCharacterIterator.
                               TextAttribute.CUSTOM_SPACING,
                               Boolean.TRUE);
                    inheritMap.put(GVTAttributedCharacterIterator.
                                   TextAttribute.CUSTOM_SPACING,
                                   Boolean.TRUE);
                }
            }
        } catch (LiveAttributeException ex) {
            throw new BridgeException(ctx, ex);
        }

        return inheritMap;
    }


    /**
     * Retrieve in the AttributeString the closest parent
     * of the node 'child' and extract the text decorations
     * of the parent.
     *
     * @param child an <code>Element</code> value
     * @return a <code>TextDecoration</code> value
     */
    protected TextPaintInfo getParentTextPaintInfo(Element child) {
        Node parent = getParentNode(child);
        while (parent != null) {
            TextPaintInfo tpi = (TextPaintInfo)elemTPI.get(parent);
            if (tpi != null) return tpi;
            parent = getParentNode(parent);
        }
        return null;
    }

    /**
     * Constructs a TextDecoration object for the specified element. This will
     * contain all of the decoration properties to be used when drawing the
     * text.
     */
    protected TextPaintInfo getTextPaintInfo(Element element,
                                             GraphicsNode node,
                                             TextPaintInfo parentTPI,
                                             BridgeContext ctx) {
        // Force the engine to update stuff..
        CSSUtilities.getComputedStyle
            (element, SVGCSSEngine.TEXT_DECORATION_INDEX);

        TextPaintInfo pi = new TextPaintInfo(parentTPI);

        // Was text-decoration explicity set on this element?
        StyleMap sm = ((CSSStylableElement)element).getComputedStyleMap(null);
        if ((sm.isNullCascaded(SVGCSSEngine.TEXT_DECORATION_INDEX)) &&
            (sm.isNullCascaded(SVGCSSEngine.FILL_INDEX)) &&
            (sm.isNullCascaded(SVGCSSEngine.STROKE_INDEX)) &&
            (sm.isNullCascaded(SVGCSSEngine.STROKE_WIDTH_INDEX)) &&
            (sm.isNullCascaded(SVGCSSEngine.OPACITY_INDEX))) {
            // If not, keep the same decorations.
            return pi;
        }

        setBaseTextPaintInfo(pi, element, node, ctx);

        if (!sm.isNullCascaded(SVGCSSEngine.TEXT_DECORATION_INDEX))
            setDecorationTextPaintInfo(pi, element);

        return pi;
    }

    public void setBaseTextPaintInfo(TextPaintInfo pi, Element element,
                                     GraphicsNode node, BridgeContext ctx) {
        if (!element.getLocalName().equals(SVG_TEXT_TAG))
            pi.composite    = CSSUtilities.convertOpacity   (element);
        else
            pi.composite    = AlphaComposite.SrcOver;

        pi.visible      = CSSUtilities.convertVisibility(element);
        pi.fillPaint    = PaintServer.convertFillPaint  (element, node, ctx);
        pi.strokePaint  = PaintServer.convertStrokePaint(element, node, ctx);
        pi.strokeStroke = PaintServer.convertStroke     (element);
    }

    public void setDecorationTextPaintInfo(TextPaintInfo pi, Element element) {
        Value val = CSSUtilities.getComputedStyle
            (element, SVGCSSEngine.TEXT_DECORATION_INDEX);

        switch (val.getCssValueType()) {
        case CSSValue.CSS_VALUE_LIST:
            ListValue lst = (ListValue)val;

            int len = lst.getLength();
            for (int i = 0; i < len; i++) {
                Value v = lst.item(i);
                String s = v.getStringValue();
                switch (s.charAt(0)) {
                case 'u':
                    if (pi.fillPaint != null) {
                        pi.underlinePaint = pi.fillPaint;
                    }
                    if (pi.strokePaint != null) {
                        pi.underlineStrokePaint = pi.strokePaint;
                    }
                    if (pi.strokeStroke != null) {
                        pi.underlineStroke = pi.strokeStroke;
                    }
                    break;
                case 'o':
                    if (pi.fillPaint != null) {
                        pi.overlinePaint = pi.fillPaint;
                    }
                    if (pi.strokePaint != null) {
                        pi.overlineStrokePaint = pi.strokePaint;
                    }
                    if (pi.strokeStroke != null) {
                        pi.overlineStroke = pi.strokeStroke;
                    }
                    break;
                case 'l':
                    if (pi.fillPaint != null) {
                        pi.strikethroughPaint = pi.fillPaint;
                    }
                    if (pi.strokePaint != null) {
                        pi.strikethroughStrokePaint = pi.strokePaint;
                    }
                    if (pi.strokeStroke != null) {
                        pi.strikethroughStroke = pi.strokeStroke;
                    }
                    break;
                }
            }
            break;

        default: // None
            pi.underlinePaint = null;
            pi.underlineStrokePaint = null;
            pi.underlineStroke = null;

            pi.overlinePaint = null;
            pi.overlineStrokePaint = null;
            pi.overlineStroke = null;

            pi.strikethroughPaint = null;
            pi.strikethroughStrokePaint = null;
            pi.strikethroughStroke = null;
            break;
        }
    }

    /**
     * Implementation of <code>SVGContext</code> for
     * the children of &lt;text&gt;
     */
    public abstract class AbstractTextChildSVGContext
            extends AnimatableSVGBridge {

        /** Text bridge parent */
        protected SVGTextElementBridge textBridge;

        /**
         * Initialize the <code>SVGContext</code> implementation
         * with the bridgeContext, the parent bridge, and the
         * element supervised by this context
         */
        public AbstractTextChildSVGContext(BridgeContext ctx,
                                           SVGTextElementBridge parent,
                                           Element e) {
            this.ctx = ctx;
            this.textBridge = parent;
            this.e = e;
        }

        /**
         * Returns the namespace URI of the element this <code>Bridge</code> is
         * dedicated to.
         */
        public String getNamespaceURI() {
            return null;
        }

        /**
         * Returns the local name of the element this <code>Bridge</code> is dedicated
         * to.
         */
        public String getLocalName() {
            return null;
        }

        /**
         * Returns a new instance of this bridge.
         */
        public Bridge getInstance() {
            return null;
        }

        public SVGTextElementBridge getTextBridge() { return textBridge; }

        /**
         * Returns the size of a px CSS unit in millimeters.
         */
        public float getPixelUnitToMillimeter() {
            return ctx.getUserAgent().getPixelUnitToMillimeter();
        }

        /**
         * Returns the size of a px CSS unit in millimeters.
         * This will be removed after next release.
         * @see #getPixelUnitToMillimeter()
         */
        public float getPixelToMM() {
            return getPixelUnitToMillimeter();

        }
        /**
         * Returns the tight bounding box in current user space (i.e.,
         * after application of the transform attribute, if any) on the
         * geometry of all contained graphics elements, exclusive of
         * stroke-width and filter effects).
         */
        public Rectangle2D getBBox() {
            //text children does not support getBBox
            //return textBridge.getBBox();
            return null;
        }

        /**
         * Returns the transformation matrix from current user units
         * (i.e., after application of the transform attribute, if any) to
         * the viewport coordinate system for the nearestViewportElement.
         */
        public AffineTransform getCTM() {
            // text children does not support transform attribute
            //return textBridge.getCTM();
            return null;
        }

        /**
         * Returns the global transformation matrix from the current
         * element to the root.
         */
        public AffineTransform getGlobalTransform() {
            //return node.getGlobalTransform();
            return null;
        }

        /**
         * Returns the transformation matrix from the userspace of
         * the root element to the screen.
         */
        public AffineTransform getScreenTransform() {
            //return node.getScreenTransform();
            return null;
        }

        /**
         * Sets the transformation matrix to be used from the
         * userspace of the root element to the screen.
         */
        public void setScreenTransform(AffineTransform at) {
            //return node.setScreenTransform(at);
            return;
        }

        /**
         * Returns the width of the viewport which directly contains the
         * given element.
         */
        public float getViewportWidth() {
            return ctx.getBlockWidth(e);
        }

        /**
         * Returns the height of the viewport which directly contains the
         * given element.
         */
        public float getViewportHeight() {
            return ctx.getBlockHeight(e);
        }

        /**
         * Returns the font-size on the associated element.
         */
        public float getFontSize() {
            return CSSUtilities.getComputedStyle
                (e, SVGCSSEngine.FONT_SIZE_INDEX).getFloatValue();
        }
    }

    /**
     * Implementation for the <code>BridgeUpdateHandler</code>
     * for the child elements of &lt;text&gt;.
     * This implementation relies on the parent bridge
     * which contains the <code>TextNode</code>
     * representing the node this context supervised.
     * All operations are done by the parent bridge
     * <code>SVGTextElementBridge</code> which can determine
     * the impact of a change of one of its children for the others.
     */
    protected abstract class AbstractTextChildBridgeUpdateHandler
        extends AbstractTextChildSVGContext implements BridgeUpdateHandler {

        /**
         * Initialize the BridgeUpdateHandler implementation.
         */
        protected AbstractTextChildBridgeUpdateHandler
            (BridgeContext ctx,
             SVGTextElementBridge parent,
             Element e) {

            super(ctx,parent,e);
        }

        /**
         * Invoked when an MutationEvent of type 'DOMAttrModified' is fired.
         */
        public void handleDOMAttrModifiedEvent(MutationEvent evt) {
            //nothing to do
        }

        /**
         * Invoked when an MutationEvent of type 'DOMNodeInserted' is fired.
         */
        public void handleDOMNodeInsertedEvent(MutationEvent evt) {
            textBridge.handleDOMNodeInsertedEvent(evt);
        }

        /**
         * Invoked when an MutationEvent of type 'DOMNodeRemoved' is fired.
         */
        public void handleDOMNodeRemovedEvent(MutationEvent evt) {
        }

        /**
         * Invoked when an MutationEvent of type 'DOMCharacterDataModified'
         * is fired.
         */
        public void handleDOMCharacterDataModified(MutationEvent evt) {
            textBridge.handleDOMCharacterDataModified(evt);
        }

        /**
         * Invoked when an CSSEngineEvent is fired.
         */
        public void handleCSSEngineEvent(CSSEngineEvent evt) {
            textBridge.handleCSSEngineEvent(evt);
        }

        /**
         * Invoked when the animated value of an animatable attribute has
         * changed.
         */
        public void handleAnimatedAttributeChanged
                (AnimatedLiveAttributeValue alav) {
        }

        /**
         * Invoked when an 'other' animation value has changed.
         */
        public void handleOtherAnimationChanged(String type) {
        }

        /**
         * Disposes this BridgeUpdateHandler and releases all resources.
         */
        public void dispose(){
            ((SVGOMElement)e).setSVGContext(null);
            elemTPI.remove(e);
        }
    }

    protected class AbstractTextChildTextContent
        extends AbstractTextChildBridgeUpdateHandler
        implements SVGTextContent {

        /**
         * Initialize the AbstractTextChildBridgeUpdateHandler implementation.
         */
        protected AbstractTextChildTextContent
            (BridgeContext ctx,
             SVGTextElementBridge parent,
             Element e) {

            super(ctx,parent,e);
        }

        //Implementation of TextContent

        public int getNumberOfChars(){
            return textBridge.getNumberOfChars(e);
        }

        public Rectangle2D getExtentOfChar(int charnum ){
            return textBridge.getExtentOfChar(e,charnum);
        }

        public Point2D getStartPositionOfChar(int charnum){
            return textBridge.getStartPositionOfChar(e,charnum);
        }

        public Point2D getEndPositionOfChar(int charnum){
            return textBridge.getEndPositionOfChar(e,charnum);
        }

        public void selectSubString(int charnum, int nchars){
            textBridge.selectSubString(e,charnum,nchars);
        }

        public float getRotationOfChar(int charnum){
            return textBridge.getRotationOfChar(e,charnum);
        }

        public float getComputedTextLength(){
            return textBridge.getComputedTextLength(e);
        }

        public float getSubStringLength(int charnum, int nchars){
            return textBridge.getSubStringLength(e,charnum,nchars);
        }

        public int getCharNumAtPosition(float x , float y){
            return textBridge.getCharNumAtPosition(e,x,y);
        }
    }

    /**
     * BridgeUpdateHandle for &lt;tref&gt; element.
     */
    protected class TRefBridge
        extends AbstractTextChildTextContent {

        protected TRefBridge(BridgeContext ctx,
                          SVGTextElementBridge parent,
                          Element e) {
            super(ctx,parent,e);
        }

        /**
         * Invoked when the animated value of an animatable attribute has
         * changed on a 'tref' element.
         */
        public void handleAnimatedAttributeChanged
                (AnimatedLiveAttributeValue alav) {
            if (alav.getNamespaceURI() == null) {
                String ln = alav.getLocalName();
                if (ln.equals(SVG_X_ATTRIBUTE)
                        || ln.equals(SVG_Y_ATTRIBUTE)
                        || ln.equals(SVG_DX_ATTRIBUTE)
                        || ln.equals(SVG_DY_ATTRIBUTE)
                        || ln.equals(SVG_ROTATE_ATTRIBUTE)
                        || ln.equals(SVG_TEXT_LENGTH_ATTRIBUTE)
                        || ln.equals(SVG_LENGTH_ADJUST_ATTRIBUTE)) {
                    // Recompute the layout of the text node.
                    textBridge.computeLaidoutText(ctx, textBridge.e,
                                                  textBridge.getTextNode());
                    return;
                }
            }
            super.handleAnimatedAttributeChanged(alav);
        }
    }

    /**
     * BridgeUpdateHandle for &lt;textPath&gt; element.
     */
    protected class TextPathBridge
        extends AbstractTextChildTextContent{

        protected TextPathBridge(BridgeContext ctx,
                              SVGTextElementBridge parent,
                              Element e){
            super(ctx,parent,e);
        }
    }

    /**
     * BridgeUpdateHandle for &lt;tspan&gt; element.
     */
    protected class TspanBridge
        extends AbstractTextChildTextContent {

        protected TspanBridge(BridgeContext ctx,
                           SVGTextElementBridge parent,
                           Element e){
            super(ctx,parent,e);
        }

        /**
         * Invoked when the animated value of an animatable attribute has
         * changed on a 'tspan' element.
         */
        public void handleAnimatedAttributeChanged
                (AnimatedLiveAttributeValue alav) {
            if (alav.getNamespaceURI() == null) {
                String ln = alav.getLocalName();
                if (ln.equals(SVG_X_ATTRIBUTE)
                        || ln.equals(SVG_Y_ATTRIBUTE)
                        || ln.equals(SVG_DX_ATTRIBUTE)
                        || ln.equals(SVG_DY_ATTRIBUTE)
                        || ln.equals(SVG_ROTATE_ATTRIBUTE)
                        || ln.equals(SVG_TEXT_LENGTH_ATTRIBUTE)
                        || ln.equals(SVG_LENGTH_ADJUST_ATTRIBUTE)) {
                    // Recompute the layout of the text node.
                    textBridge.computeLaidoutText(ctx, textBridge.e,
                                                  textBridge.getTextNode());
                    return;
                }
            }
            super.handleAnimatedAttributeChanged(alav);
        }
    }

    //Implementation of TextContent
    public int getNumberOfChars(){
        return getNumberOfChars(e);
    }

    public Rectangle2D getExtentOfChar(int charnum ){
        return getExtentOfChar(e,charnum);
    }

    public Point2D getStartPositionOfChar(int charnum){
        return getStartPositionOfChar(e,charnum);
    }

    public Point2D getEndPositionOfChar(int charnum){
        return getEndPositionOfChar(e,charnum);
    }

    public void selectSubString(int charnum, int nchars){
        selectSubString(e,charnum,nchars);
    }

    public float getRotationOfChar(int charnum){
        return getRotationOfChar(e,charnum);
    }

    public float getComputedTextLength(){
        return getComputedTextLength(e);
    }

    public float getSubStringLength(int charnum, int nchars){
        return getSubStringLength(e,charnum,nchars);
    }

    public int getCharNumAtPosition(float x , float y){
        return getCharNumAtPosition(e,x,y);
    }

    /**
     * Implementation of {@link
     * org.w3c.dom.svg.SVGTextContentElement#getNumberOfChars()}.
     */
    protected int getNumberOfChars(Element element){

        AttributedCharacterIterator aci;
        aci = getTextNode().getAttributedCharacterIterator();
        if (aci == null)
            return 0;

        //get the index in the aci for the first character
        //of the element
        int firstChar = getElementStartIndex(element);

        if (firstChar == -1)
            return 0; // Element not part of aci (no chars in elem usually)

        int lastChar = getElementEndIndex(element);

        return( lastChar - firstChar + 1 );
    }


    /**
     * Implementation of {@link
     * org.w3c.dom.svg.SVGTextContentElement#getExtentOfChar(int charnum)}.
     */
    protected Rectangle2D getExtentOfChar(Element element,int charnum ){
        TextNode textNode = getTextNode();

        AttributedCharacterIterator aci;
        aci = textNode.getAttributedCharacterIterator();
        if (aci == null) return null;

        int firstChar = getElementStartIndex(element);

        if ( firstChar == -1 )
            return null;

        //retrieve the text run for the text node
        List list = getTextRuns(textNode);

        //find the character 'charnum' in the text run
        CharacterInformation info;
        info = getCharacterInformation(list, firstChar,charnum, aci);

        if ( info == null )
            return null;

        //retrieve the glyphvector containing the glyph
        //for 'charnum'
        GVTGlyphVector it = info.layout.getGlyphVector();

        Shape b = null;

        if (info.glyphIndexStart == info.glyphIndexEnd) {
            if (it.isGlyphVisible(info.glyphIndexStart)) {
                b = it.getGlyphCellBounds(info.glyphIndexStart);
            }
        } else {
            GeneralPath path = null;
            for (int k = info.glyphIndexStart; k <= info.glyphIndexEnd; k++) {
                if (it.isGlyphVisible(k)) {
                    Rectangle2D gb = it.getGlyphCellBounds(k);
                    if (path == null) {
                        path = new GeneralPath(gb);
                    } else {
                        path.append(gb, false);
                    }
                }
            }
            b = path;
        }

        if (b == null) {
            return null;
        }

        //return the bounding box of the outline
        return b.getBounds2D();
    }


    /**
     * Implementation of {@link
     * org.w3c.dom.svg.SVGTextContentElement#getStartPositionOfChar(int charnum)}.
     */
    protected Point2D getStartPositionOfChar(Element element,int charnum){
        TextNode textNode = getTextNode();

        AttributedCharacterIterator aci;
        aci = textNode.getAttributedCharacterIterator();
        if (aci == null)
            return null;

        int firstChar = getElementStartIndex(element);
        if ( firstChar == -1 )
            return null;

        //retrieve the text run for the text node
        List list = getTextRuns(textNode);

        //find the character 'charnum' in the text run
        CharacterInformation info;
        info = getCharacterInformation(list, firstChar,charnum, aci);

        if ( info == null )
            return null;

        return getStartPoint( info );
    }

    protected Point2D getStartPoint(CharacterInformation info){

        GVTGlyphVector it = info.layout.getGlyphVector();
        if (!it.isGlyphVisible(info.glyphIndexStart))
            return null;

        Point2D b = it.getGlyphPosition(info.glyphIndexStart);

        AffineTransform glyphTransform;
        glyphTransform = it.getGlyphTransform(info.glyphIndexStart);


        //glyph are defined starting at position (0,0)
        Point2D.Float result = new Point2D.Float(0, 0);
        if ( glyphTransform != null )
            //apply the glyph transformation to the start point
            glyphTransform.transform(result,result);

        result.x += b.getX();
        result.y += b.getY();
        return result;
    }

    /**
     * Implementation of {@link
     * org.w3c.dom.svg.SVGTextContentElement#getEndPositionOfChar(int charnum)}.
     */
    protected Point2D getEndPositionOfChar(Element element,int charnum ){
        TextNode textNode = getTextNode();

        AttributedCharacterIterator aci;
        aci = textNode.getAttributedCharacterIterator();
        if (aci == null)
            return null;

        int firstChar = getElementStartIndex(element);
        if ( firstChar == -1 )
            return null;

        //retrieve the text run for the text node
        List list = getTextRuns(textNode);

        //find the glyph information for the character 'charnum'
        CharacterInformation info;
        info = getCharacterInformation(list, firstChar,charnum, aci);

        if ( info == null )
            return null;
        return getEndPoint(info);
    }

    protected Point2D getEndPoint(CharacterInformation info){

        GVTGlyphVector it = info.layout.getGlyphVector();
        if (!it.isGlyphVisible(info.glyphIndexEnd))
            return null;

        Point2D b = it.getGlyphPosition(info.glyphIndexEnd);

        AffineTransform glyphTransform;
        glyphTransform = it.getGlyphTransform(info.glyphIndexEnd);

        GVTGlyphMetrics metrics = it.getGlyphMetrics(info.glyphIndexEnd);


        Point2D.Float result = new Point2D.Float
            (metrics.getHorizontalAdvance(), 0);

        if ( glyphTransform != null )
            glyphTransform.transform(result,result);

        result.x += b.getX();
        result.y += b.getY();
        return result;
    }

    /**
     * Implementation of {@link
     * org.w3c.dom.svg.SVGTextContentElement#getRotationOfChar(int charnum)}.
     */
    protected float getRotationOfChar(Element element, int charnum){
        TextNode textNode = getTextNode();

        AttributedCharacterIterator aci;
        aci = textNode.getAttributedCharacterIterator();
        if (aci == null)
            return 0;

        //first the first character for the element
        int firstChar = getElementStartIndex(element);
        if ( firstChar == -1 )
            return 0;

        //retrieve the text run for the text node
        List list = getTextRuns(textNode);

        //find the glyph information for the character 'charnum'
        CharacterInformation info;
        info = getCharacterInformation(list, firstChar,charnum, aci);

        double angle = 0.0;
        int nbGlyphs = 0;

        if ( info != null ){
            GVTGlyphVector it = info.layout.getGlyphVector();

            for( int k = info.glyphIndexStart ;
                 k <= info.glyphIndexEnd ;
                 k++ ){
                if (!it.isGlyphVisible(k)) continue;

                nbGlyphs++;

                //the glyph transform contains only a scale and a rotate.
                AffineTransform glyphTransform = it.getGlyphTransform(k);
                if ( glyphTransform == null ) continue;

                double glyphAngle = 0.0;
                double cosTheta = glyphTransform.getScaleX();
                double sinTheta = glyphTransform.getShearX();

                //extract the angle
                if ( cosTheta == 0.0 ){
                    if ( sinTheta > 0 ) glyphAngle = Math.PI;
                    else                glyphAngle = -Math.PI;
                } else {
                    glyphAngle = Math.atan(sinTheta/cosTheta);    // todo is this safe??
                    if ( cosTheta < 0 )
                        glyphAngle += Math.PI;
                }
                //get a degrees value for the angle
                //SVG angle are clock wise java anticlockwise

                glyphAngle = (Math.toDegrees( - glyphAngle ) ) % 360.0;

                //remove the orientation from the value
                angle += glyphAngle - info.getComputedOrientationAngle();
            }
        }
        if (nbGlyphs == 0) return 0;
        return (float)(angle / nbGlyphs );
    }

    /**
     * Implementation of {@link
     * org.w3c.dom.svg.SVGTextContentElement#getComputedTextLength()}.
     */
    protected float getComputedTextLength(Element e) {
        return getSubStringLength(e,0,getNumberOfChars(e));
    }

    /**
     * Implementation of {@link
     * org.w3c.dom.svg.SVGTextContentElement#getSubStringLength(int charnum,int nchars)}.
     */
    protected float getSubStringLength(Element element,
                                       int charnum,
                                       int nchars){
        if (nchars == 0) {
            return 0;
        }

        float length = 0;

        TextNode textNode = getTextNode();

        AttributedCharacterIterator aci;
        aci = textNode.getAttributedCharacterIterator();
        if (aci == null)
            return -1;

        int firstChar = getElementStartIndex(element);

        if ( firstChar == -1 )
            return -1;

        List list = getTextRuns(textNode);

        CharacterInformation currentInfo;
        currentInfo = getCharacterInformation(list, firstChar,charnum,aci);
        CharacterInformation lastCharacterInRunInfo = null;
        int chIndex = currentInfo.characterIndex+1;
        GVTGlyphVector vector = currentInfo.layout.getGlyphVector();
        float [] advs = currentInfo.layout.getGlyphAdvances();
        boolean [] glyphTrack = new boolean[advs.length];
        for( int k = charnum +1; k < charnum +nchars ; k++) {
            if (currentInfo.layout.isOnATextPath() ){
                for (int gi = currentInfo.glyphIndexStart;
                     gi <= currentInfo.glyphIndexEnd; gi++) {
                    if ((vector.isGlyphVisible(gi)) && !glyphTrack[gi])
                        length += advs[gi+1]-advs[gi];
                    glyphTrack[gi] = true;
                }
                CharacterInformation newInfo;
                newInfo = getCharacterInformation(list, firstChar, k, aci);
                if (newInfo.layout != currentInfo.layout) {
                    vector = newInfo.layout.getGlyphVector();
                    advs = newInfo.layout.getGlyphAdvances();
                    glyphTrack = new boolean[advs.length];
                    chIndex = currentInfo.characterIndex+1;
                }
                currentInfo = newInfo;
            } else {
                //reach the next run
                if ( currentInfo.layout.hasCharacterIndex(chIndex) ){
                    chIndex++;
                    continue;
                }

                lastCharacterInRunInfo = getCharacterInformation
                    (list,firstChar,k-1,aci);

                //if the text run change compute the distance between the
                //first character of the run and the last
                length += distanceFirstLastCharacterInRun
                    (currentInfo,lastCharacterInRunInfo);

                currentInfo = getCharacterInformation(list,firstChar,k,aci);
                chIndex = currentInfo.characterIndex+1;
                vector  = currentInfo.layout.getGlyphVector();
                advs    = currentInfo.layout.getGlyphAdvances();
                glyphTrack = new boolean[advs.length];
                lastCharacterInRunInfo = null;
            }
        }

        if (currentInfo.layout.isOnATextPath() ){
            for (int gi = currentInfo.glyphIndexStart;
                 gi <= currentInfo.glyphIndexEnd; gi++) {
                if ((vector.isGlyphVisible(gi)) && !glyphTrack[gi])
                    length += advs[gi+1]-advs[gi];
                glyphTrack[gi] = true;
            }
        } else {
            if ( lastCharacterInRunInfo == null ){
                lastCharacterInRunInfo = getCharacterInformation
                    (list,firstChar,charnum+nchars-1,aci);
            }
            //add the length between the end position of the last character
            //and the first character in the run
            length += distanceFirstLastCharacterInRun
                (currentInfo,lastCharacterInRunInfo);
        }

        return length;
    }

    protected float distanceFirstLastCharacterInRun
        (CharacterInformation first, CharacterInformation last){

        float [] advs = first.layout.getGlyphAdvances();

        int firstStart = first.glyphIndexStart;
        int firstEnd   = first.glyphIndexEnd;
        int lastStart  = last.glyphIndexStart;
        int lastEnd    = last.glyphIndexEnd;

        int start = (firstStart<lastStart)?firstStart:lastStart;
        int end   = (firstEnd<lastEnd)?lastEnd:firstEnd;
        return advs[end+1] - advs[start];
    }

    protected float distanceBetweenRun
        (CharacterInformation last, CharacterInformation first){

        float distance;
        Point2D startPoint;
        Point2D endPoint;
        CharacterInformation info = new CharacterInformation();

        //determine where the last run stops

        info.layout = last.layout;
        info.glyphIndexEnd = last.layout.getGlyphCount()-1;

        startPoint = getEndPoint(info);

        //determine where the next run starts
        info.layout = first.layout;
        info.glyphIndexStart = 0;

        endPoint = getStartPoint(info);

        if( first.isVertical() ){
            distance = (float)(endPoint.getY() - startPoint.getY());
        }
        else{
            distance = (float)(endPoint.getX() - startPoint.getX());
        }

        return distance;
    }


    /**
     * Select an ensemble of characters for that element.
     *
     * TODO : report the selection to the selection
     *  manager in JSVGComponent.
     */
    protected void selectSubString(Element element, int charnum, int nchars) {
        TextNode textNode = getTextNode();

        AttributedCharacterIterator aci;
        aci = textNode.getAttributedCharacterIterator();
        if (aci == null)
            return;

        int firstChar = getElementStartIndex(element);

        if ( firstChar == -1 )
            return;

        List list = getTextRuns(textNode);

        int lastChar = getElementEndIndex(element);

        CharacterInformation firstInfo, lastInfo;
        firstInfo = getCharacterInformation(list, firstChar,charnum,aci);
        lastInfo  = getCharacterInformation(list, firstChar,charnum+nchars-1,aci);

        Mark firstMark, lastMark;
        firstMark = textNode.getMarkerForChar(firstInfo.characterIndex,true);

        if ( lastInfo != null && lastInfo.characterIndex <= lastChar ){
            lastMark = textNode.getMarkerForChar(lastInfo.characterIndex,false);
        }
        else{
            lastMark = textNode.getMarkerForChar(lastChar,false);
        }

        ctx.getUserAgent().setTextSelection(firstMark,lastMark);
    }

    protected int getCharNumAtPosition(Element e, float x, float y){
        TextNode textNode = getTextNode();

        AttributedCharacterIterator aci;
        aci = textNode.getAttributedCharacterIterator();
        if (aci == null)
            return -1;

        //check if there is an hit
        List list = getTextRuns(textNode);

        //going backward in the list to catch the last character
        // displayed at that position
        TextHit hit = null;

        for( int i = list.size()-1 ; i>= 0 && hit == null; i-- ){
            StrokingTextPainter.TextRun textRun;
            textRun = (StrokingTextPainter.TextRun)list.get(i);
            hit = textRun.getLayout().hitTestChar(x,y);
        }

        if ( hit == null )
            return -1;


        //found an hit, check if it belong to the element
        int first = getElementStartIndex( e );
        int last  = getElementEndIndex( e );

        int hitIndex = hit.getCharIndex();

        if ( hitIndex >= first && hitIndex <= last )
            return hitIndex - first;

        return -1;
    }

    /**
     * Retrieve the list of layout for the
     * text node.
     */
    protected List getTextRuns(TextNode node){
        //System.out.println(node.getTextRuns());
        if ( node.getTextRuns() == null ){
            //TODO : need to work out a solution
            //to compute the text runs
            node.getPrimitiveBounds();
        }
        //System.out.println(node.getTextRuns());
        return node.getTextRuns();
    }

    /**
     * Retrieve the information about a character
     * of en element. The element first character in
     * the ACI is 'firstChar' and the character
     * look for is the charnum th character in the
     * element
     *
     * @param list list of the layouts
     * @param startIndex index in the ACI of the first
     *   character for the element
     * @param charnum index of the character (among the
     *   characters of the element) looked for.
     *
     * @return information about the glyph representing the
     *  character
     */
    protected CharacterInformation getCharacterInformation
        (List list,int startIndex, int charnum,
         AttributedCharacterIterator aci)
    {
        CharacterInformation info = new CharacterInformation();
        info.characterIndex = startIndex+charnum;

        for (Object aList : list) {
            StrokingTextPainter.TextRun run;
            run = (StrokingTextPainter.TextRun) aList;

            if (!run.getLayout().hasCharacterIndex(info.characterIndex))
                continue;

            info.layout = run.getLayout();

            aci.setIndex(info.characterIndex);

            //check is it is a altGlyph
            if (aci.getAttribute(ALT_GLYPH_HANDLER) != null) {
                info.glyphIndexStart = 0;
                info.glyphIndexEnd = info.layout.getGlyphCount() - 1;
            } else {
                info.glyphIndexStart = info.layout.getGlyphIndex
                        (info.characterIndex);

                //special case when the glyph does not have a unicode
                //associated to it, it will return -1
                if (info.glyphIndexStart == -1) {
                    info.glyphIndexStart = 0;
                    info.glyphIndexEnd = info.layout.getGlyphCount() - 1;
                } else {
                    info.glyphIndexEnd = info.glyphIndexStart;
                }
            }
            return info;
        }
        return null;
    }

    /**
     * Helper class to collect information about one Glyph
     * in the GlyphVector
     */
    protected static class CharacterInformation{
        ///layout associated to the Glyph
        TextSpanLayout layout;
        ///GlyphIndex in the vector
        int glyphIndexStart;

        int glyphIndexEnd;

        ///Character index in the ACI.
        int characterIndex;

        /// Indicates is the glyph is vertical
        public boolean isVertical(){
            return layout.isVertical();
        }
        /// Retrieve the orientation angle for the Glyph
        public double getComputedOrientationAngle(){
            return layout.getComputedOrientationAngle(characterIndex);
        }
    }


    public Set getTextIntersectionSet(AffineTransform at,
                                       Rectangle2D rect) {
        Set elems = new HashSet();

        TextNode tn = getTextNode();

        List list = tn.getTextRuns();
        if (list == null)
            return elems;

        for (Object aList : list) {
            StrokingTextPainter.TextRun run;
            run = (StrokingTextPainter.TextRun) aList;
            TextSpanLayout layout = run.getLayout();
            AttributedCharacterIterator aci = run.getACI();
            aci.first();
            SoftReference sr;
            sr = (SoftReference) aci.getAttribute(TEXT_COMPOUND_ID);
            Element elem = (Element) sr.get();

            if (elem == null) continue;
            if (elems.contains(elem)) continue;
            if (!isTextSensitive(elem)) continue;

            Rectangle2D glBounds = layout.getBounds2D();
            if (glBounds != null) {
                glBounds = at.createTransformedShape(glBounds).getBounds2D();

                if (!rect.intersects(glBounds)) {
                    continue;
                }
            }

            GVTGlyphVector gv = layout.getGlyphVector();
            for (int g = 0; g < gv.getNumGlyphs(); g++) {
                Shape gBounds = gv.getGlyphLogicalBounds(g);
                if (gBounds != null) {
                    gBounds = at.createTransformedShape
                            (gBounds).getBounds2D();

                    if (gBounds.intersects(rect)) {
                        elems.add(elem);
                        break;
                    }
                }
            }
        }
        return elems;
    }

    public Set getTextEnclosureSet(AffineTransform at,
                                    Rectangle2D rect) {
        TextNode tn = getTextNode();

        Set elems = new HashSet();
        List list = tn.getTextRuns();
        if (list == null)
            return elems;

        Set reject = new HashSet();
        for (Object aList : list) {
            StrokingTextPainter.TextRun run;
            run = (StrokingTextPainter.TextRun) aList;
            TextSpanLayout layout = run.getLayout();
            AttributedCharacterIterator aci = run.getACI();
            aci.first();
            SoftReference sr;
            sr = (SoftReference) aci.getAttribute(TEXT_COMPOUND_ID);
            Element elem = (Element) sr.get();

            if (elem == null) continue;
            if (reject.contains(elem)) continue;
            if (!isTextSensitive(elem)) {
                reject.add(elem);
                continue;
            }

            Rectangle2D glBounds = layout.getBounds2D();
            if (glBounds == null) {
                continue;
            }

            glBounds = at.createTransformedShape(glBounds).getBounds2D();

            if (rect.contains(glBounds)) {
                elems.add(elem);
            } else {
                reject.add(elem);
                elems.remove(elem);
            }
        }

        return elems;
    }

    public static boolean getTextIntersection(BridgeContext ctx,
                                              Element elem,
                                              AffineTransform ati,
                                              Rectangle2D rect,
                                              boolean checkSensitivity) {
        SVGContext svgCtx = null;
        if (elem instanceof SVGOMElement)
            svgCtx  = ((SVGOMElement)elem).getSVGContext();
        if (svgCtx == null) return false;

        SVGTextElementBridge txtBridge = null;
        if (svgCtx instanceof SVGTextElementBridge)
            txtBridge = (SVGTextElementBridge)svgCtx;
        else if (svgCtx instanceof AbstractTextChildSVGContext) {
            AbstractTextChildSVGContext childCtx;
            childCtx = (AbstractTextChildSVGContext)svgCtx;
            txtBridge = childCtx.getTextBridge();
        }
        if (txtBridge == null) return false;

        TextNode tn = txtBridge.getTextNode();
        List list = tn.getTextRuns();
        if (list == null)
            return false;

        Element  txtElem = txtBridge.e;

        AffineTransform at = tn.getGlobalTransform();
        at.preConcatenate(ati);

        Rectangle2D tnRect;
        tnRect = tn.getBounds();
        tnRect = at.createTransformedShape(tnRect).getBounds2D();
        if (!rect.intersects(tnRect)) return false;

        for (Object aList : list) {
            StrokingTextPainter.TextRun run;
            run = (StrokingTextPainter.TextRun) aList;
            TextSpanLayout layout = run.getLayout();
            AttributedCharacterIterator aci = run.getACI();
            aci.first();
            SoftReference sr;
            sr = (SoftReference) aci.getAttribute(TEXT_COMPOUND_ID);
            Element runElem = (Element) sr.get();
            if (runElem == null) continue;

            // Only consider runElem if it is sensitive.
            if (checkSensitivity && !isTextSensitive(runElem)) continue;

            Element p = runElem;
            while ((p != null) && (p != txtElem) && (p != elem)) {
                p = (Element) txtBridge.getParentNode(p);
            }
            if (p != elem) continue;

            // runElem is a child of elem so check it out.
            Rectangle2D glBounds = layout.getBounds2D();
            if (glBounds == null) continue;
            glBounds = at.createTransformedShape(glBounds).getBounds2D();
            if (!rect.intersects(glBounds)) continue;

            GVTGlyphVector gv = layout.getGlyphVector();
            for (int g = 0; g < gv.getNumGlyphs(); g++) {
                Shape gBounds = gv.getGlyphLogicalBounds(g);
                if (gBounds != null) {
                    gBounds = at.createTransformedShape
                            (gBounds).getBounds2D();

                    if (gBounds.intersects(rect)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public static Rectangle2D getTextBounds(BridgeContext ctx, Element elem,
                                            boolean checkSensitivity) {
        SVGContext svgCtx = null;
        if (elem instanceof SVGOMElement)
            svgCtx  = ((SVGOMElement)elem).getSVGContext();
        if (svgCtx == null) return null;

        SVGTextElementBridge txtBridge = null;
        if (svgCtx instanceof SVGTextElementBridge)
            txtBridge = (SVGTextElementBridge)svgCtx;
        else if (svgCtx instanceof AbstractTextChildSVGContext) {
            AbstractTextChildSVGContext childCtx;
            childCtx = (AbstractTextChildSVGContext)svgCtx;
            txtBridge = childCtx.getTextBridge();
        }
        if (txtBridge == null) return null;

        TextNode tn = txtBridge.getTextNode();
        List list = tn.getTextRuns();
        if (list == null)
            return null;

        Element  txtElem = txtBridge.e;
        Rectangle2D ret = null;

        for (Object aList : list) {
            StrokingTextPainter.TextRun run;
            run = (StrokingTextPainter.TextRun) aList;
            TextSpanLayout layout = run.getLayout();
            AttributedCharacterIterator aci = run.getACI();
            aci.first();
            SoftReference sr;
            sr = (SoftReference) aci.getAttribute(TEXT_COMPOUND_ID);
            Element runElem = (Element) sr.get();
            if (runElem == null) continue;

            // Only consider runElem if it is sensitive.
            if (checkSensitivity && !isTextSensitive(runElem)) continue;

            Element p = runElem;
            while ((p != null) && (p != txtElem) && (p != elem)) {
                p = (Element) txtBridge.getParentNode(p);
            }
            if (p != elem) continue;

            // runElem is a child of elem so include it's bounds.
            Rectangle2D glBounds = layout.getBounds2D();
            if (glBounds != null) {
                if (ret == null) ret = (Rectangle2D) glBounds.clone();
                else ret.add(glBounds);
            }
        }
        return ret;
    }


    public static boolean isTextSensitive(Element e) {
        int     ptrEvts = CSSUtilities.convertPointerEvents(e);
        switch (ptrEvts) {
        case GraphicsNode.VISIBLE_PAINTED:   // fall-through is intended
        case GraphicsNode.VISIBLE_FILL:
        case GraphicsNode.VISIBLE_STROKE:
        case GraphicsNode.VISIBLE:
            return CSSUtilities.convertVisibility(e);
        case GraphicsNode.PAINTED:
        case GraphicsNode.FILL:              // fall-through is intended
        case GraphicsNode.STROKE:
        case GraphicsNode.ALL:
            return true;
        case GraphicsNode.NONE:
        default:
            return false;
        }
    }
}
