* before appending new content.
*/
public CompositeGraphicsNode buildCompositeGraphicsNode
(BridgeContext ctx, Element e, CompositeGraphicsNode gn) {
// get the referenced element
SVGOMUseElement ue = (SVGOMUseElement) e;
String uri = ue.getHref().getAnimVal();
if (uri.length() == 0) {
throw new BridgeException(ctx, e, ERR_ATTRIBUTE_MISSING,
new Object[] {"xlink:href"});
}
Element refElement = ctx.getReferencedElement(e, uri);
SVGOMDocument document, refDocument;
document = (SVGOMDocument)e.getOwnerDocument();
refDocument = (SVGOMDocument)refElement.getOwnerDocument();
boolean isLocal = (refDocument == document);
BridgeContext theCtx = ctx;
subCtx = null;
if (!isLocal) {
subCtx = (BridgeContext)refDocument.getCSSEngine().getCSSContext();
theCtx = subCtx;
}
// import or clone the referenced element in current document
Element localRefElement;
localRefElement = (Element)document.importNode(refElement, true, true);
if (SVG_SYMBOL_TAG.equals(localRefElement.getLocalName())) {
// The referenced 'symbol' and its contents are deep-cloned into
// the generated tree, with the exception that the 'symbol' is
// replaced by an 'svg'.
Element svgElement = document.createElementNS(SVG_NAMESPACE_URI,
SVG_SVG_TAG);
// move the attributes from <symbol> to the <svg> element
NamedNodeMap attrs = localRefElement.getAttributes();
int len = attrs.getLength();
for (int i = 0; i < len; i++) {
Attr attr = (Attr)attrs.item(i);
svgElement.setAttributeNS(attr.getNamespaceURI(),
attr.getName(),
attr.getValue());
}
// move the children from <symbol> to the <svg> element
for (Node n = localRefElement.getFirstChild();
n != null;
n = localRefElement.getFirstChild()) {
svgElement.appendChild(n);
}
localRefElement = svgElement;
}
if (SVG_SVG_TAG.equals(localRefElement.getLocalName())) {
// The referenced 'svg' and its contents are deep-cloned into the
// generated tree. If attributes width and/or height are provided
// on the 'use' element, then these values will override the
// corresponding attributes on the 'svg' in the generated tree.
try {
SVGOMAnimatedLength al = (SVGOMAnimatedLength) ue.getWidth();
if (al.isSpecified()) {
localRefElement.setAttributeNS
(null, SVG_WIDTH_ATTRIBUTE,
al.getAnimVal().getValueAsString());
}
al = (SVGOMAnimatedLength) ue.getHeight();
if (al.isSpecified()) {
localRefElement.setAttributeNS
(null, SVG_HEIGHT_ATTRIBUTE,
al.getAnimVal().getValueAsString());
}
} catch (LiveAttributeException ex) {
throw new BridgeException(ctx, ex);
}
}
// attach the referenced element to the current document
SVGOMUseShadowRoot root;
root = new SVGOMUseShadowRoot(document, e, isLocal);
root.appendChild(localRefElement);
if (gn == null) {
gn = new CompositeGraphicsNode();
associateSVGContext(ctx, e, node);
} else {
int s = gn.size();
for (int i=0; i<s; i++)
gn.remove(0);
}
Node oldRoot = ue.getCSSFirstChild();
if (oldRoot != null) {
disposeTree(oldRoot);
}
ue.setUseShadowTree(root);
Element g = localRefElement;
// compute URIs and style sheets for the used element
CSSUtilities.computeStyleAndURIs(refElement, localRefElement, uri);