* @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) {
CanvasGraphicsNode gn = new CanvasGraphicsNode();
UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e);
String s;
boolean isOutermost = (((SVGElement)e).getOwnerSVGElement() == null);
float x = 0;
float y = 0;
// x and y have no meaning on the outermost 'svg' element
if (!isOutermost) {
// 'x' attribute - default is 0
s = e.getAttributeNS(null, SVG_X_ATTRIBUTE);
if (s.length() != 0) {
x = UnitProcessor.svgHorizontalCoordinateToUserSpace
(s, SVG_X_ATTRIBUTE, uctx);
}
// 'y' attribute - default is 0
s = e.getAttributeNS(null, SVG_Y_ATTRIBUTE);
if (s.length() != 0) {
y = UnitProcessor.svgVerticalCoordinateToUserSpace
(s, SVG_Y_ATTRIBUTE, uctx);
}
}
// 'width' attribute - default is 100%
s = e.getAttributeNS(null, SVG_WIDTH_ATTRIBUTE);
if (s.length() == 0) {
s = SVG_SVG_WIDTH_DEFAULT_VALUE;
}
float w = UnitProcessor.svgHorizontalLengthToUserSpace
(s, SVG_WIDTH_ATTRIBUTE, uctx);
// 'height' attribute - default is 100%
s = e.getAttributeNS(null, SVG_HEIGHT_ATTRIBUTE);
if (s.length() == 0) {
s = SVG_SVG_HEIGHT_DEFAULT_VALUE;
}
float h = UnitProcessor.svgVerticalLengthToUserSpace
(s, SVG_HEIGHT_ATTRIBUTE, uctx);
// 'visibility'
gn.setVisible(CSSUtilities.convertVisibility(e));
// 'viewBox' and "preserveAspectRatio' attributes
AffineTransform at =
ViewBox.getPreserveAspectRatioTransform(e, w, h);
float actualWidth = w;
float actualHeight = h;
try {
AffineTransform atInv = at.createInverse();
actualWidth = (float) (w*atInv.getScaleX());
actualHeight = (float) (h*atInv.getScaleY());
} catch (NoninvertibleTransformException ex) {}
at.preConcatenate(AffineTransform.getTranslateInstance(x, y));
// 'overflow' and 'clip'
// The outermost preserveAspectRatio matrix is set by the user
// agent, so we don't need to set the transform for outermost svg
Shape clip = null;
if (!isOutermost) {
gn.setTransform(at);
} else {
// <!> FIXME: hack to compute the original document's size
if (ctx.getDocumentSize() == null) {
ctx.setDocumentSize(new Dimension((int)w, (int)h));
}
}
if (CSSUtilities.convertOverflow(e)) { // overflow:hidden
float [] offsets = CSSUtilities.convertClip(e);
if (offsets == null) { // clip:auto
clip = new Rectangle2D.Float(x, y, w, h);
} else { // clip:rect(<x> <y> <w> <h>)
// offsets[0] = top
// offsets[1] = right
// offsets[2] = bottom
// offsets[3] = left
clip = new Rectangle2D.Float(x+offsets[3],
y+offsets[0],
w-offsets[1]-offsets[3],
h-offsets[2]-offsets[0]);
}
}
if (clip != null) {
try {
at = at.createInverse(); // clip in user space
clip = at.createTransformedShape(clip);
Filter filter = gn.getGraphicsNodeRable();
gn.setClip(new ClipRable8Bit(filter, clip));
} catch (NoninvertibleTransformException ex) {}
}
// 'enable-background'
Rectangle2D r = CSSUtilities.convertEnableBackground(e, uctx);
if (r != null) {
gn.setBackgroundEnable(r);
}
ctx.openViewport
(e, new SVGSVGElementViewport((SVGSVGElement)e,
actualWidth,