You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by jm...@apache.org on 2013/10/08 16:03:25 UTC
[10/62] [abbrv] [partial] Merged Apache Flex 4.9.0 release branch
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGTextElementBridge.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGTextElementBridge.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGTextElementBridge.java
index 8036e20..bdf9ec2 100644
--- a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGTextElementBridge.java
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGTextElementBridge.java
@@ -1,10 +1,11 @@
/*
- Copyright 2001-2004 The Apache Software Foundation
-
- Licensed 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
+ 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
@@ -19,16 +20,14 @@ package org.apache.flex.forks.batik.bridge;
import java.awt.AlphaComposite;
import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Shape;
-import java.awt.Stroke;
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.AttributedString;
import java.text.AttributedCharacterIterator.Attribute;
@@ -39,8 +38,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.Vector;
import java.util.WeakHashMap;
import org.apache.flex.forks.batik.css.engine.CSSEngineEvent;
@@ -49,16 +46,27 @@ import org.apache.flex.forks.batik.css.engine.SVGCSSEngine;
import org.apache.flex.forks.batik.css.engine.StyleMap;
import org.apache.flex.forks.batik.css.engine.value.ListValue;
import org.apache.flex.forks.batik.css.engine.value.Value;
+import org.apache.flex.forks.batik.dom.events.NodeEventTarget;
+import org.apache.flex.forks.batik.dom.svg.AbstractSVGAnimatedLength;
+import org.apache.flex.forks.batik.dom.svg.AnimatedLiveAttributeValue;
+import org.apache.flex.forks.batik.dom.svg.LiveAttributeException;
import org.apache.flex.forks.batik.dom.svg.SVGContext;
+import org.apache.flex.forks.batik.dom.svg.SVGOMAnimatedEnumeration;
+import org.apache.flex.forks.batik.dom.svg.SVGOMAnimatedLengthList;
+import org.apache.flex.forks.batik.dom.svg.SVGOMAnimatedNumberList;
import org.apache.flex.forks.batik.dom.svg.SVGOMElement;
+import org.apache.flex.forks.batik.dom.svg.SVGOMTextPositioningElement;
import org.apache.flex.forks.batik.dom.svg.SVGTextContent;
import org.apache.flex.forks.batik.dom.util.XLinkSupport;
import org.apache.flex.forks.batik.dom.util.XMLSupport;
import org.apache.flex.forks.batik.gvt.GraphicsNode;
import org.apache.flex.forks.batik.gvt.TextNode;
+import org.apache.flex.forks.batik.gvt.font.FontFamilyResolver;
+import org.apache.flex.forks.batik.gvt.font.GVTFont;
import org.apache.flex.forks.batik.gvt.font.GVTFontFamily;
import org.apache.flex.forks.batik.gvt.font.GVTGlyphMetrics;
import org.apache.flex.forks.batik.gvt.font.GVTGlyphVector;
+import org.apache.flex.forks.batik.gvt.font.UnresolvedFontFamily;
import org.apache.flex.forks.batik.gvt.renderer.StrokingTextPainter;
import org.apache.flex.forks.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.flex.forks.batik.gvt.text.Mark;
@@ -66,38 +74,66 @@ import org.apache.flex.forks.batik.gvt.text.TextHit;
import org.apache.flex.forks.batik.gvt.text.TextPaintInfo;
import org.apache.flex.forks.batik.gvt.text.TextPath;
import org.apache.flex.forks.batik.gvt.text.TextSpanLayout;
+import org.apache.flex.forks.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.EventTarget;
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 <text> 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: SVGTextElementBridge.java,v 1.106 2005/03/27 08:58:30 cam Exp $
+ * @version $Id: SVGTextElementBridge.java 593421 2007-11-09 05:01:44Z cam $
*/
-public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
+public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
implements SVGTextContent {
- protected final static Integer ZERO = new Integer(0);
+ protected static final Integer ZERO = new Integer(0);
- public static final
+ 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
+ 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;
@@ -105,7 +141,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
// in this text element.
protected WeakHashMap elemTPI = new WeakHashMap();
- // This s true if any of the spans of this text element
+ // 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
@@ -132,6 +168,9 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
return new SVGTextElementBridge();
}
+ protected TextNode getTextNode() {
+ return (TextNode)node;
+ }
/**
* Creates a <tt>GraphicsNode</tt> according to the specified parameters.
*
@@ -144,6 +183,18 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
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());
@@ -176,27 +227,31 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
* @param e the text element
*/
protected Point2D getLocation(BridgeContext ctx, Element e) {
- UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, 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();
+ }
- // 'x' attribute - default is 0
- String s = e.getAttributeNS(null, SVG_X_ATTRIBUTE);
- float x = 0;
- if (s.length() != 0) {
- StringTokenizer st = new StringTokenizer(s, ", ", false);
- x = UnitProcessor.svgHorizontalCoordinateToUserSpace
- (st.nextToken(), SVG_X_ATTRIBUTE, uctx);
- }
+ // '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();
+ }
- // 'y' attribute - default is 0
- s = e.getAttributeNS(null, SVG_Y_ATTRIBUTE);
- float y = 0;
- if (s.length() != 0) {
- StringTokenizer st = new StringTokenizer(s, ", ", false);
- y = UnitProcessor.svgVerticalCoordinateToUserSpace
- (st.nextToken(), SVG_Y_ATTRIBUTE, uctx);
+ return new Point2D.Float(x, y);
+ } catch (LiveAttributeException ex) {
+ throw new BridgeException(ctx, ex);
}
-
- return new Point2D.Float(x, y);
}
protected boolean isTextElement(Element e) {
@@ -251,6 +306,9 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
node.setPointerEventType(CSSUtilities.convertPointerEvents(e));
initializeDynamicSupport(ctx, e, node);
+ if (!ctx.isDynamic()) {
+ elemTPI.clear();
+ }
}
/**
@@ -260,13 +318,38 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
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 =
- new DOMChildNodeRemovedEventListener();
+ protected DOMChildNodeRemovedEventListener childNodeRemovedEventListener;
/**
* The DOM EventListener invoked when a node is removed.
@@ -277,15 +360,14 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
* Handles 'DOMNodeRemoved' event type.
*/
public void handleEvent(Event evt) {
- handleDOMChildNodeRemovedEvent((MutationEvent)evt);
+ handleDOMChildNodeRemovedEvent((MutationEvent)evt);
}
}
/**
* The DOM EventListener to receive 'DOMSubtreeModified' event.
*/
- protected DOMSubtreeModifiedEventListener subtreeModifiedEventListener =
- new DOMSubtreeModifiedEventListener();
+ protected DOMSubtreeModifiedEventListener subtreeModifiedEventListener;
/**
* The DOM EventListener invoked when the subtree is modified.
@@ -303,50 +385,79 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
// BridgeUpdateHandler implementation -----------------------------------
/**
- * This method insures that any modification to a text
- * element and its children is going to be reflected
+ * 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())
- return; // Only add the listeners if we are dynamic
+ super.initializeDynamicSupport(ctx, e, node);
+ if (ctx.isDynamic()) {
+ // Only add the listeners if we are dynamic.
+ addTextEventListeners(ctx, (NodeEventTarget) e);
+ }
+ }
- EventTarget evtTarget = (EventTarget)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
+ //to be notified when a child is removed from the
//<text> element.
- evtTarget.addEventListener
- ("DOMNodeRemoved", childNodeRemovedEventListener, true);
- ctx.storeEventListener
- (evtTarget, "DOMNodeRemoved", childNodeRemovedEventListener, true);
-
+ 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
- evtTarget.addEventListener
- ("DOMSubtreeModified", subtreeModifiedEventListener, false);
- ctx.storeEventListener
- (evtTarget, "DOMSubtreeModified", subtreeModifiedEventListener, false);
+ e.addEventListenerNS
+ (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMSubtreeModified",
+ subtreeModifiedEventListener, false, null);
+ ctx.storeEventListenerNS
+ (e, XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMSubtreeModified",
+ subtreeModifiedEventListener, false);
+ }
- // traverse the children to add context on
- // <tspan>, <tref> and <textPath>
- Node child = e.getFirstChild();
- while (child != null) {
- if (child.getNodeType() == Node.ELEMENT_NODE) {
- addContextToChild(ctx,(Element)child);
- }
- child = child.getNextSibling();
- }
+ /**
+ * 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);
}
/**
- * Add to the element children of the node, a
- * <code>SVGContext</code> to support dynamic updated . This is
- * recurssive, the children of the nodes are also traversed to add
+ * 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
@@ -355,7 +466,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
* @see org.apache.flex.forks.batik.dom.svg.SVGContext
* @see org.apache.flex.forks.batik.bridge.BridgeUpdateHandler
*/
- protected void addContextToChild(BridgeContext ctx,Element e) {
+ protected void addContextToChild(BridgeContext ctx, Element e) {
if (SVG_NAMESPACE_URI.equals(e.getNamespaceURI())) {
if (e.getLocalName().equals(SVG_TSPAN_TAG)) {
((SVGOMElement)e).setSVGContext
@@ -369,12 +480,45 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
}
}
- Node child = e.getFirstChild();
+ Node child = getFirstChild(e);
while (child != null) {
if (child.getNodeType() == Node.ELEMENT_NODE) {
addContextToChild(ctx, (Element)child);
- }
- child = child.getNextSibling();
+ }
+ 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.flex.forks.batik.dom.svg.SVGContext
+ * @see org.apache.flex.forks.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);
}
}
@@ -383,45 +527,30 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
*/
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:
- case Node.CDATA_SECTION_NODE:
- laidoutText = null;
- break;
- case Node.ELEMENT_NODE: {
- Element childElement = (Element)childNode;
- if (isTextChild(childElement)) {
- addContextToChild( ctx, childElement);
+ 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;
}
}
- break;
- default:
- }
if (laidoutText == null) {
- computeLaidoutText(ctx, e, node);
+ computeLaidoutText(ctx, e, getTextNode());
}
}
/**
- * Invoked when an MutationEvent of type 'DOMNodeInserted' is fired.
- */
- public void handleDOMNodeRemovedEvent(MutationEvent evt) {
- EventTarget evtTarget = evt.getTarget();
- evtTarget.removeEventListener("DOMNodeRemoved",
- childNodeRemovedEventListener,
- true);
- evtTarget.removeEventListener("DOMSubtreeModified",
- subtreeModifiedEventListener,
- false);
- super.handleDOMNodeRemovedEvent(evt);
- }
-
- /**
* Invoked when an MutationEvent of type 'DOMNodeRemoved' is fired.
*/
public void handleDOMChildNodeRemovedEvent(MutationEvent evt) {
@@ -431,18 +560,21 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
//in the case of <title> or <desc> or <metadata>, the layout
//is unchanged
switch (childNode.getNodeType()) {
- case Node.TEXT_NODE:
+ case Node.TEXT_NODE: // fall-through is intended
case Node.CDATA_SECTION_NODE:
//the parent has to be a displayed node
- if (isParentDisplayed( childNode)) {
+ if (isParentDisplayed(childNode)) {
laidoutText = null;
}
break;
- case Node.ELEMENT_NODE:
- if (isTextChild((Element)childNode)) {
+ 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,
@@ -452,16 +584,16 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
/**
* Invoked when an MutationEvent of type 'DOMSubtree' is fired.
*/
- public void handleDOMSubtreeModifiedEvent(MutationEvent evt){
+ 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, node);
+ computeLaidoutText(ctx, e, getTextNode());
}
}
/**
- * Invoked when an MutationEvent of type 'DOMCharacterDataModified'
+ * Invoked when an MutationEvent of type 'DOMCharacterDataModified'
* is fired.
*/
public void handleDOMCharacterDataModified(MutationEvent evt){
@@ -478,12 +610,12 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
* <title>, <desc> and <metadata>
* are non displayable elements.
*
- * @return true if the parent of the node is <text>,
+ * @return true if the parent of the node is <text>,
* <tspan>, <tref>, <textPath>, <a>,
* <altGlyph>
*/
protected boolean isParentDisplayed(Node childNode) {
- Node parentNode = childNode.getParentNode();
+ Node parentNode = getParentNode(childNode);
return isTextElement((Element)parentNode);
}
@@ -491,23 +623,26 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
* Recompute the layout of the <text> node.
*
* Assign onto the TextNode pending to the element
- * the new recomputed AtrributedString. Also
+ * the new recomputed AttributedString. Also
* update <code>laidoutText</code> with the new
* value.
*/
- protected void computeLaidoutText(BridgeContext ctx,
- Element e,
- GraphicsNode node) {
+ 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());
}
- TextNode tn = (TextNode)node;
- elemTPI.clear();
- // Add null TPI objects to the text (after we set it on the
- // Text we will swap in the correct values.
- addNullPaintAttributes(as, e, ctx);
// Install the ACI in the text node.
tn.setAttributedCharacterIterator(as.getIterator());
@@ -526,55 +661,9 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
// Force Complex SVG fonts to be recreated, if we have them.
tn.setAttributedCharacterIterator(as.getIterator());
}
- }
-
- /**
- * This creates 'dummy' TPI objects for each element and records
- * them in the elemTPI map so we can later update them with
- * the correct paint attributes.
- */
- protected void addNullPaintAttributes(AttributedString as,
- Element element,
- BridgeContext ctx) {
- // 'requiredFeatures', 'requiredExtensions' and 'systemLanguage'
- if ((!SVGUtilities.matchUserAgent(element, ctx.getUserAgent())) ||
- (!CSSUtilities.convertDisplay(element))) {
- return;
- }
-
- AttributedCharacterIterator aci = as.getIterator();
-
- // calculate which chars in the string belong to this element
- int firstChar = getElementStartIndex(aci, element);
- if (firstChar == -1)
- return; // Element not part of aci (no chars in elem usually)
-
- int lastChar = getElementEndIndex(aci, element);
- TextPaintInfo pi = new TextPaintInfo();
- // Set some basic props so we can get bounds info for complex paints.
- pi.visible = true;
- pi.fillPaint = Color.black;
-
- as.addAttribute(PAINT_INFO, pi, firstChar, lastChar+1);
- elemTPI.put(element, pi);
-
- addChildNullPaintAttributes(as, element, ctx);
- }
-
- protected void addChildNullPaintAttributes(AttributedString as,
- Element element,
- BridgeContext ctx) {
- // Add Paint attributres for children of text element
- for (Node child = element.getFirstChild();
- child != null;
- child = child.getNextSibling()) {
- if (child.getNodeType() != Node.ELEMENT_NODE)
- continue;
- Element childElement = (Element)child;
- if (isTextChild(childElement)) {
- addNullPaintAttributes(as, childElement, ctx);
- }
+ if (ctx.isDynamic()) {
+ checkBBoxChange();
}
}
@@ -591,26 +680,28 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
private Element cssProceedElement;
/**
- * Invoked when an MutationEvent of type 'DOMAttrModified' is fired.
+ * Invoked when the animated value of an animatable attribute has changed.
*/
- public void handleDOMAttrModifiedEvent(MutationEvent evt) {
- String attrName = evt.getAttrName();
- if (attrName.equals(SVG_X_ATTRIBUTE) ||
- attrName.equals(SVG_Y_ATTRIBUTE) ||
- attrName.equals(SVG_DX_ATTRIBUTE) ||
- attrName.equals(SVG_DY_ATTRIBUTE) ||
- attrName.equals(SVG_ROTATE_ATTRIBUTE) ){
-
- if ( attrName.equals(SVG_X_ATTRIBUTE) ||
- attrName.equals(SVG_Y_ATTRIBUTE)){
- ((TextNode)node).setLocation(getLocation(ctx, e));
+ 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;
}
-
- computeLaidoutText(ctx, e, node);
- }
- else{
- super.handleDOMAttrModifiedEvent(evt);
}
+ super.handleAnimatedAttributeChanged(alav);
}
/**
@@ -623,7 +714,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
int [] properties = evt.getProperties();
// first try to find CSS properties that change the layout
for (int i=0; i < properties.length; ++i) {
- switch(properties[i]) {
+ switch(properties[i]) { // fall-through is intended
case SVGCSSEngine.BASELINE_SHIFT_INDEX:
case SVGCSSEngine.DIRECTION_INDEX:
case SVGCSSEngine.DISPLAY_INDEX:
@@ -634,7 +725,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
case SVGCSSEngine.FONT_WEIGHT_INDEX:
case SVGCSSEngine.GLYPH_ORIENTATION_HORIZONTAL_INDEX:
case SVGCSSEngine.GLYPH_ORIENTATION_VERTICAL_INDEX:
- case SVGCSSEngine.KERNING_INDEX:
+ case SVGCSSEngine.KERNING_INDEX:
case SVGCSSEngine.LETTER_SPACING_INDEX:
case SVGCSSEngine.TEXT_ANCHOR_INDEX:
case SVGCSSEngine.UNICODE_BIDI_INDEX:
@@ -642,7 +733,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
case SVGCSSEngine.WRITING_MODE_INDEX: {
if (!hasNewACI) {
hasNewACI = true;
- computeLaidoutText(ctx, e, node);
+ computeLaidoutText(ctx, e, getTextNode());
}
break;
}
@@ -661,7 +752,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
* Invoked for each CSS property that has changed.
*/
protected void handleCSSPropertyChanged(int property) {
- switch(property) {
+ switch(property) { // fall-through is intended
case SVGCSSEngine.FILL_INDEX:
case SVGCSSEngine.FILL_OPACITY_INDEX:
case SVGCSSEngine.STROKE_INDEX:
@@ -675,8 +766,8 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
case SVGCSSEngine.TEXT_DECORATION_INDEX:
rebuildACI();
break;
-
- case SVGCSSEngine.VISIBILITY_INDEX:
+
+ case SVGCSSEngine.VISIBILITY_INDEX:
rebuildACI();
super.handleCSSPropertyChanged(property);
break;
@@ -695,7 +786,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
node.setRenderingHints(hints);
}
break;
- }
+ }
default:
super.handleCSSPropertyChanged(property);
}
@@ -705,7 +796,9 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
if (hasNewACI)
return;
- TextNode tn = (TextNode)node;
+ TextNode textNode = getTextNode();
+ if (textNode.getAttributedCharacterIterator() == null)
+ return;
TextPaintInfo pi, oldPI;
if ( cssProceedElement == e ){
@@ -719,46 +812,29 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
//and only update the section of the AtrtibutedString of
//the child
TextPaintInfo parentPI;
- parentPI = getParentTextPaintInfo
- (tn.getAttributedCharacterIterator(), cssProceedElement);
- pi = getTextPaintInfo(cssProceedElement, tn, parentPI, ctx);
+ parentPI = getParentTextPaintInfo(cssProceedElement);
+ pi = getTextPaintInfo(cssProceedElement, textNode, parentPI, ctx);
oldPI = (TextPaintInfo)elemTPI.get(cssProceedElement);
}
if (oldPI == null) return;
- tn.swapTextPaintInfo(pi, oldPI);
- if (usingComplexSVGFont)
+ textNode.swapTextPaintInfo(pi, oldPI);
+ if (usingComplexSVGFont)
// Force Complex SVG fonts to be recreated
- tn.setAttributedCharacterIterator
- (tn.getAttributedCharacterIterator());
+ textNode.setAttributedCharacterIterator
+ (textNode.getAttributedCharacterIterator());
}
- int getElementStartIndex
- (AttributedCharacterIterator aci, Element element) {
- // calculate which chars in the string belong to this element
- for (int i = 0; i < aci.getEndIndex();) {
- aci.setIndex(i);
- Element delimeter;
- delimeter = (Element)aci.getAttribute(TEXT_COMPOUND_DELIMITER);
- if (delimeter == element || nodeAncestorOf(element, delimeter))
- return i;
- i = aci.getRunLimit(TEXT_COMPOUND_DELIMITER);
- }
- return -1;
+ int getElementStartIndex(Element element) {
+ TextPaintInfo tpi = (TextPaintInfo)elemTPI.get(element);
+ if (tpi == null) return -1;
+ return tpi.startChar;
}
- int getElementEndIndex
- (AttributedCharacterIterator aci, Element element) {
- // calculate which chars in the string belong to this element
- for (int i = aci.getEndIndex()-1; i >= 0;) {
- aci.setIndex(i);
- Element delimeter;
- delimeter = (Element)aci.getAttribute(TEXT_COMPOUND_DELIMITER);
- if (delimeter == element || nodeAncestorOf(element, delimeter))
- return i;
- i = aci.getRunStart(TEXT_COMPOUND_DELIMITER)-1;
- }
- return -1;
+ int getElementEndIndex(Element element) {
+ TextPaintInfo tpi = (TextPaintInfo)elemTPI.get(element);
+ if (tpi == null) return -1;
+ return tpi.endChar;
}
// -----------------------------------------------------------------------
@@ -775,9 +851,9 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
*/
protected AttributedString buildAttributedString(BridgeContext ctx,
Element element) {
-
+
AttributedStringBuffer asb = new AttributedStringBuffer();
- fillAttributedStringBuffer(ctx, element, true, null, null, asb);
+ fillAttributedStringBuffer(ctx, element, true, null, null, null, asb);
return asb.toAttributedString();
}
@@ -798,6 +874,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
boolean top,
TextPath textPath,
Integer bidiLevel,
+ Map initialAttributes,
AttributedStringBuffer asb) {
// 'requiredFeatures', 'requiredExtensions', 'systemLanguage' &
// 'display="none".
@@ -805,105 +882,169 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
(!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)
+ if (top) {
endLimit = 0;
- if (preserve)
+ }
+ if (preserve) {
endLimit = asb.length();
-
- Map map = getAttributeMap(ctx, element, textPath, bidiLevel);
- Object o = map.get(TextAttribute.BIDI_EMBEDDING);
+ }
+
+ 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);
+ if (o != null) {
+ subBidiLevel = (Integer) o;
+ }
- for (Node n = element.getFirstChild();
+ for (Node n = getFirstChild(element);
n != null;
- n = n.getNextSibling()) {
+ n = getNextSibling(n)) {
if (preserve) {
prevEndsWithSpace = false;
} else {
- if (asb.length() == 0)
+ if (asb.length() == 0) {
prevEndsWithSpace = true;
- else
+ } 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 != null) {
- Map m = getAttributeMap(ctx, nodeElement,
- textPath, bidiLevel);
+ 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)) {
- EventTarget target = (EventTarget)nodeElement;
+ NodeEventTarget target = (NodeEventTarget)nodeElement;
UserAgent ua = ctx.getUserAgent();
- EventListener l = new SVGAElementBridge.AnchorListener(ua);
- target.addEventListener(SVG_EVENT_CLICK, l, false);
- ctx.storeEventListener(target, SVG_EVENT_CLICK, l, false);
-
+ 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:
+ case Node.TEXT_NODE: // fall-through is intended
case Node.CDATA_SECTION_NODE:
s = n.getNodeValue();
s = normalizeString(s, preserve, prevEndsWithSpace);
- asb.append(s, map);
- if (preserve)
- endLimit = asb.length();
+ if (s.length() != 0) {
+ asb.append(s, map);
+ if (preserve) {
+ endLimit = asb.length();
+ }
+ initialAttributes = null;
+ }
}
}
if (top) {
- while ((endLimit < asb.length()) && (asb.getLastChar() == ' '))
+ boolean strippedSome = false;
+ while ((endLimit < asb.length()) && (asb.getLastChar() == ' ')) {
asb.stripLast();
+ strippedSome = true;
+ }
+ if (strippedSome) {
+ Iterator iter = elemTPI.values().iterator();
+ while (iter.hasNext()) {
+ TextPaintInfo tpi = (TextPaintInfo)iter.next();
+ 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;
}
/**
@@ -916,7 +1057,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
if (preserve) {
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
- switch (c) {
+ switch (c) { // fall-through is intended
case 10:
case 13:
case '\t':
@@ -935,7 +1076,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
switch (s.charAt(idx)) {
default:
break loop;
- case 10:
+ case 10: // fall-through is intended
case 13:
case ' ':
case '\t':
@@ -948,10 +1089,10 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
for (int i = idx; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
- case 10:
+ case 10: // fall-through is intended
case 13:
break;
- case ' ':
+ case ' ': // fall-through is intended
case '\t':
if (!space) {
sb.append(' ');
@@ -981,7 +1122,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
* The attributes.
*/
protected List attributes;
-
+
/**
* The number of items.
*/
@@ -991,7 +1132,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
* The length of the attributed string.
*/
protected int length;
-
+
/**
* Creates a new empty AttributedStringBuffer.
*/
@@ -1008,7 +1149,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
public boolean isEmpty() {
return count == 0;
}
-
+
/**
* Returns the length in chars of the current Attributed String
*/
@@ -1020,11 +1161,11 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
* 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();
+ if (s.length() == 0) return;
+ strings.add(s);
+ attributes.add(m);
+ count++;
+ length += s.length();
}
/**
@@ -1043,7 +1184,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
*/
public void stripFirst() {
String s = (String)strings.get(0);
- if (s.charAt(s.length() - 1) != ' ')
+ if (s.charAt(s.length() - 1) != ' ')
return;
length--;
@@ -1063,7 +1204,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
*/
public void stripLast() {
String s = (String)strings.get(count - 1);
- if (s.charAt(s.length() - 1) != ' ')
+ if (s.charAt(s.length() - 1) != ' ')
return;
length--;
@@ -1084,13 +1225,13 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
public AttributedString toAttributedString() {
switch (count) {
case 0:
- return new AttributedString(" ");
+ return null;
case 1:
return new AttributedString((String)strings.get(0),
(Map)attributes.get(0));
}
- StringBuffer sb = new StringBuffer();
+ StringBuffer sb = new StringBuffer( strings.size() * 5 );
Iterator it = strings.iterator();
while (it.hasNext()) {
sb.append((String)it.next());
@@ -1128,7 +1269,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
return (String)strings.get(0);
}
- StringBuffer sb = new StringBuffer();
+ StringBuffer sb = new StringBuffer( strings.size() * 5 );
Iterator it = strings.iterator();
while (it.hasNext()) {
sb.append((String)it.next());
@@ -1144,9 +1285,9 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
if (node2 == null || node1 == null) {
return false;
}
- Node parent = node2.getParentNode();
+ Node parent = getParentNode(node2);
while (parent != null && parent != node1) {
- parent = parent.getParentNode();
+ parent = getParentNode(parent);
}
return (parent == node1);
}
@@ -1170,120 +1311,116 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
return;
}
- AttributedCharacterIterator aci = as.getIterator();
-
// calculate which chars in the string belong to this element
- int firstChar = getElementStartIndex(aci, element);
+ int firstChar = getElementStartIndex(element);
// No match so no chars to annotate.
if (firstChar == -1) return;
- int lastChar = getElementEndIndex(aci, element);
+ int lastChar = getElementEndIndex(element);
- // get all of the glyph position attribute values
- String xAtt = element.getAttributeNS(null, SVG_X_ATTRIBUTE);
- String yAtt = element.getAttributeNS(null, SVG_Y_ATTRIBUTE);
- String dxAtt = element.getAttributeNS(null, SVG_DX_ATTRIBUTE);
- String dyAtt = element.getAttributeNS(null, SVG_DY_ATTRIBUTE);
- String rotateAtt = element.getAttributeNS(null, SVG_ROTATE_ATTRIBUTE);
-
- ArrayList al;
- int len;
-
- // process the x attribute
- if (xAtt.length() != 0) {
- al = TextUtilities.svgHorizontalCoordinateArrayToUserSpace
- (element, SVG_X_ATTRIBUTE, xAtt, ctx);
- len = al.size();
- for (int i = 0; i < len; i++) {
- if (firstChar + i <= lastChar) {
- as.addAttribute
- (GVTAttributedCharacterIterator.TextAttribute.X,
- al.get(i), firstChar+i, firstChar+i+1);
- }
- }
+ // 'a' elements aren't SVGTextPositioningElements, so don't process
+ // their positioning attributes on them.
+ if (!(element instanceof SVGTextPositioningElement)) {
+ addChildGlyphPositionAttributes(as, element, ctx);
+ return;
}
-
- // process the y attribute
- if (yAtt.length() != 0) {
- al = TextUtilities.svgVerticalCoordinateArrayToUserSpace
- (element, SVG_Y_ATTRIBUTE, yAtt, ctx);
- len = al.size();
-
- for (int i = 0; i < len; i++) {
- if (firstChar+i <= lastChar) {
- as.addAttribute
- (GVTAttributedCharacterIterator.TextAttribute.Y,
- al.get(i), firstChar+i, firstChar+i+1);
- }
+ // 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,
+ new Float(xs.getItem(i).getValue()), firstChar + i,
+ firstChar + i + 1);
}
- }
-
- // process dx attribute
- if (dxAtt.length() != 0) {
- al = TextUtilities.svgHorizontalCoordinateArrayToUserSpace
- (element, SVG_DX_ATTRIBUTE, dxAtt, ctx);
- len = al.size();
- for (int i = 0; i < len; i++) {
- if (firstChar+i <= lastChar) {
- as.addAttribute
- (GVTAttributedCharacterIterator.TextAttribute.DX,
- al.get(i), 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,
+ new Float(ys.getItem(i).getValue()), firstChar + i,
+ firstChar + i + 1);
}
- }
- // process dy attribute
- if (dyAtt.length() != 0) {
- al = TextUtilities.svgVerticalCoordinateArrayToUserSpace
- (element, SVG_DY_ATTRIBUTE, dyAtt, ctx);
- len = al.size();
-
- for (int i = 0; i < len; i++) {
- if (firstChar+i <= lastChar) {
- as.addAttribute
- (GVTAttributedCharacterIterator.TextAttribute.DY,
- al.get(i), 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,
+ new Float(dxs.getItem(i).getValue()), firstChar + i,
+ firstChar + i + 1);
}
- }
- // process rotate attribute
- if (rotateAtt.length() != 0) {
- al = TextUtilities.svgRotateArrayToFloats
- (element, SVG_ROTATE_ATTRIBUTE, rotateAtt, ctx);
- len = al.size();
+ // process dy attribute
+ len = dys.getNumberOfItems();
+ for (int i = 0; i < len && firstChar + i <= lastChar; i++) {
+ as.addAttribute
+ (GVTAttributedCharacterIterator.TextAttribute.DY,
+ new Float(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 = new Float(Math.toRadians(rs.getItem(0).getValue()));
as.addAttribute
(GVTAttributedCharacterIterator.TextAttribute.ROTATION,
- al.get(0), firstChar, lastChar + 1);
+ rad, firstChar, lastChar + 1);
- } else { // its a list
+ } else if (len > 1) { // it's a list
// set each rotate value from the list
- for (int i = 0; i < len; i++) {
- if (firstChar+i <= lastChar) {
- as.addAttribute
- (GVTAttributedCharacterIterator.
- TextAttribute.ROTATION,
- al.get(i), firstChar+i, firstChar+i+1);
- }
+ for (int i = 0; i < len && firstChar + i <= lastChar; i++) {
+ Float rad = new Float(Math.toRadians(rs.getItem(i).getValue()));
+ as.addAttribute
+ (GVTAttributedCharacterIterator.TextAttribute.ROTATION,
+ rad, firstChar + i, firstChar + i + 1);
}
}
- }
- addChildGlyphPositionAttributes(as, element, ctx);
+ 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 = element.getFirstChild();
+ for (Node child = getFirstChild(element);
child != null;
- child = child.getNextSibling()) {
+ child = getNextSibling(child)) {
if (child.getNodeType() != Node.ELEMENT_NODE) continue;
Element childElement = (Element)child;
@@ -1307,8 +1444,9 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
return;
}
Object o = elemTPI.get(element);
- if (o == null) return;
- node.swapTextPaintInfo(pi, (TextPaintInfo)o);
+ if (o != null) {
+ node.swapTextPaintInfo(pi, (TextPaintInfo)o);
+ }
addChildPaintAttributes(as, element, node, pi, ctx);
}
@@ -1318,9 +1456,9 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
TextPaintInfo parentPI,
BridgeContext ctx) {
// Add Paint attributres for children of text element
- for (Node child = element.getFirstChild();
+ for (Node child = getFirstChild(element);
child != null;
- child = child.getNextSibling()) {
+ child = getNextSibling(child)) {
if (child.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
@@ -1333,71 +1471,150 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
}
}
- protected Map getFontProperties(BridgeContext ctx, Element element,
- Map map) {
- if (map == null) map = new HashMap(4);
+ /**
+ * This method adds all the font related properties to <tt>result</tt>
+ * It also builds a List of the GVTFonts and returns it.
+ */
+ protected List getFontList(BridgeContext ctx,
+ Element element,
+ Map result) {
- // Needed for SVG fonts.
- map.put(TEXT_COMPOUND_DELIMITER, element);
+ // 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.floatValue();
// Font size.
- map.put(TextAttribute.SIZE, TextUtilities.convertFontSize(element));
+ result.put(TextAttribute.SIZE, fsFloat);
// Font stretch
- map.put(TextAttribute.WIDTH, TextUtilities.convertFontStretch(element));
+ result.put(TextAttribute.WIDTH,
+ TextUtilities.convertFontStretch(element));
+
+ // Font style
+ result.put(TextAttribute.POSTURE,
+ TextUtilities.convertFontStyle(element));
// Font weight
- map.put(TextAttribute.WEIGHT, TextUtilities.convertFontWeight(element));
+ result.put(TextAttribute.WEIGHT,
+ TextUtilities.convertFontWeight(element));
+
+ // Font weight
+ Value v = CSSUtilities.getComputedStyle
+ (element, SVGCSSEngine.FONT_WEIGHT_INDEX);
+ String fontWeightString = v.getCssText();
// Font style
- map.put(TextAttribute.POSTURE, TextUtilities.convertFontStyle(element));
+ 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) continue;
+ if (fontFamily instanceof UnresolvedFontFamily) {
+ fontFamily = FontFamilyResolver.resolve
+ ((UnresolvedFontFamily)fontFamily);
+ if (fontFamily == null) continue;
+ }
+ fontFamilyList.add(fontFamily);
+ if (fontFamily instanceof SVGFontFamily) {
+ SVGFontFamily svgFF = (SVGFontFamily)fontFamily;
+ if (svgFF.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);
- return map;
+ 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) {
- UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, element);
+ 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 result = new HashMap();
+ Map inheritMap = null;
String s;
- float f;
-
+
if (SVG_NAMESPACE_URI.equals(element.getNamespaceURI()) &&
element.getLocalName().equals(SVG_ALT_GLYPH_TAG)) {
- result.put(ALT_GLYPH_HANDLER,
+ 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(GVTAttributedCharacterIterator.TextAttribute.TEXTPATH,
- textPath);
+ result.put(TEXTPATH, textPath);
}
// Text-anchor
TextNode.Anchor a = TextUtilities.convertTextAnchor(element);
- result.put(GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE,
- a);
-
- // get font size/width/weight/posture properties
- getFontProperties(ctx, element, result);
+ result.put(ANCHOR_TYPE, a);
// Font family
- List fontFamilyList = getFontFamilyList(element, ctx);
- result.put
- (GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES,
- fontFamilyList);
+ List fontList = getFontList(ctx, element, result);
+ result.put(GVT_FONTS, fontList);
+
// Text baseline adjustment.
Object bs = TextUtilities.convertBaselineShift(element);
if (bs != null) {
- result.put(GVTAttributedCharacterIterator.
- TextAttribute.BASELINE_SHIFT, bs);
+ result.put(BASELINE_SHIFT, bs);
}
// Unicode-bidi mode
@@ -1422,35 +1639,35 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
val = CSSUtilities.getComputedStyle
(element, SVGCSSEngine.DIRECTION_INDEX);
String rs = val.getStringValue();
- int cbidi = 0;
- if (bidiLevel != null) cbidi = bidiLevel.intValue();
+ int cbidi = 0;
+ if (bidiLevel != null) cbidi = bidiLevel.intValue();
- // 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;
+ // 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
+ 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
+ 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;
- }
+ }
+
+ switch (s.charAt(0)) {
+ case 'b': // bidi-override
+ cbidi = -cbidi; // For bidi-override we want a negative number.
+ break;
+ }
- result.put(TextAttribute.BIDI_EMBEDDING, new Integer(cbidi));
+ result.put(TextAttribute.BIDI_EMBEDDING, new Integer(cbidi));
}
// Writing mode
@@ -1483,7 +1700,8 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
val = CSSUtilities.getComputedStyle
(element, SVGCSSEngine.GLYPH_ORIENTATION_VERTICAL_INDEX);
- switch (val.getPrimitiveType()) {
+ int primitiveType = val.getPrimitiveType();
+ switch ( primitiveType ) {
case CSSPrimitiveValue.CSS_IDENT: // auto
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION,
@@ -1506,7 +1724,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
TextAttribute.ORIENTATION_ANGLE);
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION_ANGLE,
- new Float(val.getFloatValue() * 180 / Math.PI));
+ new Float( Math.toDegrees( val.getFloatValue() ) ));
break;
case CSSPrimitiveValue.CSS_GRAD:
result.put(GVTAttributedCharacterIterator.
@@ -1519,14 +1737,15 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
break;
default:
// Cannot happen
- throw new InternalError();
+ throw new IllegalStateException("unexpected primitiveType (V):" + primitiveType );
}
// glyph-orientation-horizontal
val = CSSUtilities.getComputedStyle
(element, SVGCSSEngine.GLYPH_ORIENTATION_HORIZONTAL_INDEX);
- switch (val.getPrimitiveType()) {
+ primitiveType = val.getPrimitiveType();
+ switch ( primitiveType ) {
case CSSPrimitiveValue.CSS_DEG:
result.put(GVTAttributedCharacterIterator.
TextAttribute.HORIZONTAL_ORIENTATION_ANGLE,
@@ -1535,7 +1754,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
case CSSPrimitiveValue.CSS_RAD:
result.put(GVTAttributedCharacterIterator.
TextAttribute.HORIZONTAL_ORIENTATION_ANGLE,
- new Float(val.getFloatValue() * 180 / Math.PI));
+ new Float( Math.toDegrees( val.getFloatValue() ) ));
break;
case CSSPrimitiveValue.CSS_GRAD:
result.put(GVTAttributedCharacterIterator.
@@ -1544,7 +1763,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
break;
default:
// Cannot happen
- throw new InternalError();
+ throw new IllegalStateException("unexpected primitiveType (H):" + primitiveType );
}
// text spacing properties...
@@ -1581,105 +1800,81 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
Boolean.TRUE);
}
- // textLength
- s = element.getAttributeNS(null, SVG_TEXT_LENGTH_ATTRIBUTE);
- if (s.length() != 0) {
- f = UnitProcessor.svgOtherLengthToUserSpace
- (s, SVG_TEXT_LENGTH_ATTRIBUTE, uctx);
- result.put(GVTAttributedCharacterIterator.TextAttribute.BBOX_WIDTH,
- new Float(f));
-
- // lengthAdjust
- s = element.getAttributeNS(null, SVG_LENGTH_ADJUST_ATTRIBUTE);
-
- if (s.length() < 10) {
- result.put(GVTAttributedCharacterIterator.
- TextAttribute.LENGTH_ADJUST,
- GVTAttributedCharacterIterator.
- TextAttribute.ADJUST_SPACING);
- result.put(GVTAttributedCharacterIterator.
- TextAttribute.CUSTOM_SPACING,
- Boolean.TRUE);
- } else {
- result.put(GVTAttributedCharacterIterator.
- TextAttribute.LENGTH_ADJUST,
- GVTAttributedCharacterIterator.
- TextAttribute.ADJUST_ALL);
- }
+ if (tce == null) {
+ return inheritMap;
}
- return result;
- }
-
-
- protected List getFontFamilyList(Element element, BridgeContext ctx) {
- // 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();
+ try {
+ // textLength
+ AbstractSVGAnimatedLength textLength =
+ (AbstractSVGAnimatedLength) tce.getTextLength();
+ if (textLength.isSpecified()) {
+ if (inheritMap == null) {
+ inheritMap = new HashMap();
+ }
- Value val = CSSUtilities.getComputedStyle
- (element, SVGCSSEngine.FONT_FAMILY_INDEX);
- // make a list of GVTFontFamily objects
- List fontFamilyList = new ArrayList();
- int len = val.getLength();
- for (int i = 0; i < len; i++) {
- Value it = val.item(i);
- String fontFamilyName = it.getStringValue();
- GVTFontFamily fontFamily
- = SVGFontUtilities.getFontFamily(element, ctx, fontFamilyName,
- fontWeightString,
- fontStyleString);
- if (fontFamily instanceof SVGFontFamily) {
- SVGFontFamily svgFF = (SVGFontFamily)fontFamily;
- if (svgFF.isComplex()) {
- usingComplexSVGFont = true;
+ Object value = new Float(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);
}
}
- fontFamilyList.add(fontFamily);
+ } catch (LiveAttributeException ex) {
+ throw new BridgeException(ctx, ex);
}
- return fontFamilyList;
+
+ return inheritMap;
}
+
/**
* Retrieve in the AttributeString the closest parent
* of the node 'child' and extract the text decorations
* of the parent.
*
- * @param aci an <code>AttributedCharacterIterator</code> value
* @param child an <code>Element</code> value
* @return a <code>TextDecoration</code> value
*/
- protected TextPaintInfo getParentTextPaintInfo
- (AttributedCharacterIterator aci, Element child) {
- Element parent = null;
-
- // calculate which chars in the string belong to the parent
- int firstChar = -1;
- for (int i = 0; i < aci.getEndIndex();) {
- aci.setIndex(i);
- Element delimeter;
- delimeter = (Element)aci.getAttribute(TEXT_COMPOUND_DELIMITER);
- if (nodeAncestorOf(delimeter,child) &&
- ((parent == null) || nodeAncestorOf(parent, delimeter))) {
- parent = delimeter;
- firstChar = i;
- }
- if (delimeter == child || nodeAncestorOf(child, delimeter)) {
- break;
- }
- i = aci.getRunLimit(TEXT_COMPOUND_DELIMITER);
+ 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);
}
-
- if ( parent == null)
- return new TextPaintInfo(); //no parent
-
- aci.setIndex(firstChar);
- return (TextPaintInfo)aci.getAttribute(PAINT_INFO);
+ return null;
}
/**
@@ -1689,13 +1884,13 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
*/
protected TextPaintInfo getTextPaintInfo(Element element,
GraphicsNode node,
- TextPaintInfo parent,
+ TextPaintInfo parentTPI,
BridgeContext ctx) {
// Force the engine to update stuff..
- Value val = CSSUtilities.getComputedStyle
+ CSSUtilities.getComputedStyle
(element, SVGCSSEngine.TEXT_DECORATION_INDEX);
- TextPaintInfo pi = new TextPaintInfo(parent);
+ TextPaintInfo pi = new TextPaintInfo(parentTPI);
// Was text-decoration explicity set on this element?
StyleMap sm = ((CSSStylableElement)element).getComputedStyleMap(null);
@@ -1783,11 +1978,11 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
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;
@@ -1796,21 +1991,15 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
}
/**
- * Implementation of <ode>SVGContext</code> for
+ * Implementation of <code>SVGContext</code> for
* the children of <text>
*/
- public abstract class AbstractTextChildSVGContext
- implements SVGContext {
-
- /** Bridge Context */
- protected BridgeContext ctx;
+ public abstract class AbstractTextChildSVGContext
+ extends AnimatableSVGBridge {
/** Text bridge parent */
protected SVGTextElementBridge textBridge;
- /** Element */
- protected Element e;
-
/**
* Initialize the <code>SVGContext</code> implementation
* with the bridgeContext, the parent bridge, and the
@@ -1824,8 +2013,31 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
this.e = e;
}
+ /**
+ * Returns the namespace URI of the element this <tt>Bridge</tt> is
+ * dedicated to.
+ */
+ public String getNamespaceURI() {
+ return null;
+ }
+
+ /**
+ * Returns the local name of the element this <tt>Bridge</tt> 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.
*/
@@ -1840,7 +2052,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
*/
public float getPixelToMM() {
return getPixelUnitToMillimeter();
-
+
}
/**
* Returns the tight bounding box in current user space (i.e.,
@@ -1899,7 +2111,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
public float getViewportWidth() {
return ctx.getBlockWidth(e);
}
-
+
/**
* Returns the height of the viewport which directly contains the
* given element.
@@ -1907,7 +2119,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
public float getViewportHeight() {
return ctx.getBlockHeight(e);
}
-
+
/**
* Returns the font-size on the associated element.
*/
@@ -1927,19 +2139,20 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
* <code>SVGTextElementBridge</code> which can determine
* the impact of a change of one of its children for the others.
*/
- protected abstract class AbstractTextChildBridgeUpdateHandler
+ protected abstract class AbstractTextChildBridgeUpdateHandler
extends AbstractTextChildSVGContext implements BridgeUpdateHandler {
/**
* Initialize the BridgeUpdateHandler implementation.
*/
- public AbstractTextChildBridgeUpdateHandler
+ protected AbstractTextChildBridgeUpdateHandler
(BridgeContext ctx,
SVGTextElementBridge parent,
Element e) {
super(ctx,parent,e);
}
+
/**
* Invoked when an MutationEvent of type 'DOMAttrModified' is fired.
*/
@@ -1958,12 +2171,10 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
* Invoked when an MutationEvent of type 'DOMNodeRemoved' is fired.
*/
public void handleDOMNodeRemovedEvent(MutationEvent evt) {
- //nothing to do
- dispose();
}
/**
- * Invoked when an MutationEvent of type 'DOMCharacterDataModified'
+ * Invoked when an MutationEvent of type 'DOMCharacterDataModified'
* is fired.
*/
public void handleDOMCharacterDataModified(MutationEvent evt) {
@@ -1978,6 +2189,20 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
}
/**
+ * 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(){
@@ -1986,14 +2211,14 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
}
}
- protected class AbstractTextChildTextContent
+ protected class AbstractTextChildTextContent
extends AbstractTextChildBridgeUpdateHandler
- implements SVGTextContent{
+ implements SVGTextContent {
/**
* Initialize the AbstractTextChildBridgeUpdateHandler implementation.
*/
- public AbstractTextChildTextContent
+ protected AbstractTextChildTextContent
(BridgeContext ctx,
SVGTextElementBridge parent,
Element e) {
@@ -2006,7 +2231,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
public int getNumberOfChars(){
return textBridge.getNumberOfChars(e);
}
-
+
public Rectangle2D getExtentOfChar(int charnum ){
return textBridge.getExtentOfChar(e,charnum);
}
@@ -2030,7 +2255,7 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
public float getComputedTextLength(){
return textBridge.getComputedTextLength(e);
}
-
+
public float getSubStringLength(int charnum, int nchars){
return textBridge.getSubStringLength(e,charnum,nchars);
}
@@ -2043,40 +2268,47 @@ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge
/**
* BridgeUpdateHandle for <tref> element.
*/
- protected class TRefBridge
+ protected class TRefBridge
extends AbstractTextChildTextContent {
- public TRefBridge(BridgeContext ctx,
+ protected TRefBridge(BridgeContext ctx,
SVGTextElementBridge parent,
Element e) {
super(ctx,parent,e);
}
/**
- * Handle the dynamic update for the attributes of
- * <tspan> : 'x', 'y', 'dx', 'dy' and 'rotate'.
+ * Invoked when the animated value of an animatable attribute has
+ * changed on a 'tref' element.
*/
- public void handleDOMAttrModifiedEvent(MutationEvent evt){
- String attrName = evt.getAttrName();
- if (attrName.equals(SVG_X_ATTRIBUTE) ||
- attrName.equals(SVG_Y_ATTRIBUTE) ||
- attrName.equals(SVG_DX_ATTRIBUTE) ||
- attrName.equals(SVG_DY_ATTRIBUTE) ||
- attrName.equals(SVG_ROTATE_ATTRIBUTE)) {
- //recompute the layout of the text node
- textBridge.computeLaidoutText(ctx, textBridge.e,
- textBridge.node);
+ 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 <textP
<TRUNCATED>