import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.WeakHashMap;
import org.simantics.scenegraph.ExportableWidget.RasterOutputWidget;
@RasterOutputWidget
public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode {
- public static class SVGNodeAssignment {
- public String elementId;
- public String attributeNameOrId;
- public String value;
- public SVGNodeAssignment(String elementId, String attributeNameOrId, String value) {
- this.elementId = elementId;
- this.attributeNameOrId = attributeNameOrId;
- this.value = value;
- }
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((attributeNameOrId == null) ? 0 : attributeNameOrId.hashCode());
- result = prime * result + ((elementId == null) ? 0 : elementId.hashCode());
- result = prime * result + ((value == null) ? 0 : value.hashCode());
- return result;
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- SVGNodeAssignment other = (SVGNodeAssignment) obj;
- if (attributeNameOrId == null) {
- if (other.attributeNameOrId != null)
- return false;
- } else if (!attributeNameOrId.equals(other.attributeNameOrId))
- return false;
- if (elementId == null) {
- if (other.elementId != null)
- return false;
- } else if (!elementId.equals(other.elementId))
- return false;
- if (value == null) {
- if (other.value != null)
- return false;
- } else if (!value.equals(other.value))
- return false;
- return true;
- }
- }
-
- private static final long serialVersionUID = 8508750881358776559L;
+ private static final long serialVersionUID = 8508750881358776559L;
protected String data = null;
protected String defaultData = null;
if (data == null)
return null;
+ SVGUniverse univ = SVGCache.getSVGUniverse();
try {
- SVGUniverse univ = SVGCache.getSVGUniverse();
- synchronized(univ) {
- // NOTE: hard-coded to assume all SVG data is encoded in UTF-8
- byte[] dataBytes = data.getBytes("UTF-8");
- dataHash = digest(dataBytes, assignments);
- if (diagramCache != null)
- univ.decRefCount(diagramCache.getXMLBase());
- URI uri = univ.loadSVG(new ByteArrayInputStream(dataBytes), dataHash);
- diagramCache = univ.getDiagram(uri, false);
- if (diagramCache != null) {
- if (diagramCache.getRoot() == null) {
- diagramCache = univ.getDiagram(univ.loadSVG(BROKEN_SVG_DATA), false);
- dataHash = "broken";
- } else if (diagramCache.getRoot().getBoundingBox().isEmpty()) {
- diagramCache = univ.getDiagram(univ.loadSVG(EMPTY_SVG_DATA), false);
- dataHash = "empty";
- } else {
- for(SVGNodeAssignment ass : assignments) {
- SVGElement e = diagramCache.getElement(ass.elementId);
- if(e != null) {
- if("$text".equals(ass.attributeNameOrId)) {
- Tspan t = (Tspan)e;
- t.setText(ass.value);
- Text text = (Text)t.getParent();
- text.rebuild();
- } else {
- e.setAttribute(ass.attributeNameOrId, AnimationElement.AT_AUTO, ass.value);
- }
- }
- }
- if(!assignments.isEmpty())
- diagramCache.updateTime(0);
- }
- }
- documentCache = data;
- if (diagramCache != null) {
- setBounds((Rectangle2D) diagramCache.getRoot().getBoundingBox().clone());
- univ.incRefCount(diagramCache.getXMLBase());
- } else {
- setBounds(new Rectangle2D.Double());
- }
- }
+ Rectangle2D bbox = null;
+ synchronized (univ) {
+ // Relinquish reference to current element
+ if (diagramCache != null) {
+ univ.decRefCount(diagramCache.getXMLBase());
+ diagramCache = null;
+ }
+
+
+ // Lets check for rootAssignment that contributes the whole SVG
+ SVGNodeAssignment rootAssignment = null;
+ if (!assignments.isEmpty()) {
+ for (SVGNodeAssignment ass : assignments) {
+ if (ass.attributeNameOrId.equals("$root")) {
+ rootAssignment = ass;
+ break;
+ }
+ }
+ }
+ byte[] dataBytes;
+ if (rootAssignment != null) {
+ dataBytes = rootAssignment.value.getBytes("UTF-8");
+ } else {
+ // NOTE: hard-coded to assume all SVG data is encoded in UTF-8
+ dataBytes = data.getBytes("UTF-8");
+ }
+ dataHash = digest(dataBytes, assignments);
+ URI uri = univ.loadSVG(new ByteArrayInputStream(dataBytes), dataHash);
+ diagramCache = univ.getDiagram(uri, false);
+
+ if (diagramCache != null) {
+ univ.incRefCount(diagramCache.getXMLBase());
+ SVGRoot root = diagramCache.getRoot();
+ if (root == null) {
+ univ.decRefCount(diagramCache.getXMLBase());
+ diagramCache = univ.getDiagram(univ.loadSVG(BROKEN_SVG_DATA), false);
+ dataHash = "broken";
+ univ.incRefCount(diagramCache.getXMLBase());
+ bbox = (Rectangle2D) diagramCache.getRoot().getBoundingBox().clone();
+ } else {
+ bbox = root.getBoundingBox();
+ if (bbox.isEmpty()) {
+ // Lets check if this should be visible or not
+ Set presentationAttributes = root.getPresentationAttributes();
+ if (!presentationAttributes.contains("display")) {
+ // TODO: fix this - How can one read values of attributes in SVG salamander???
+ univ.decRefCount(diagramCache.getXMLBase());
+ diagramCache = univ.getDiagram(univ.loadSVG(EMPTY_SVG_DATA), false);
+ dataHash = "empty";
+ univ.incRefCount(diagramCache.getXMLBase());
+ bbox = (Rectangle2D) root.getBoundingBox().clone();
+ } else {
+ bbox = new Rectangle2D.Double(0, 0, 0, 0);
+ }
+ } else {
+ if (applyAssignments(diagramCache, assignments)) {
+ bbox = (Rectangle2D) root.getBoundingBox().clone();
+ } else {
+ bbox = (Rectangle2D) bbox.clone();
+ }
+ }
+ }
+ } else {
+ bbox = new Rectangle2D.Double();
+ }
+ }
+
+ documentCache = data;
+ setBounds(bbox);
} catch (SVGException e) {
- setBounds((Rectangle2D) diagramCache.getViewRect().clone());
+ // This can only occur if diagramCache != null.
+ setBounds(diagramCache.getViewRect(new Rectangle2D.Double()));
+ univ.decRefCount(diagramCache.getXMLBase());
+ diagramCache = null;
} catch (IOException e) {
diagramCache = null;
}
return dataHash;
}
+ private static boolean applyAssignments(SVGDiagram diagram, List<SVGNodeAssignment> assignments) throws SVGException {
+ if (assignments.isEmpty())
+ return false;
+ boolean changed = false;
+ for (SVGNodeAssignment ass : assignments) {
+// System.err.println("assign: " + ass.elementId + " " + ass.attributeNameOrId + " " + ass.value);
+// if("opacity".equals(ass.attributeNameOrId))
+// System.err.println("faaf");
+ SVGElement e = diagram.getElement(ass.elementId);
+ if (e != null) {
+ if ("$text".equals(ass.attributeNameOrId)) {
+ if (e instanceof Tspan) {
+ Tspan t = (Tspan) e;
+ if (ass.value.trim().isEmpty()) {
+ t.setText("-");
+ } else {
+ t.setText(ass.value);
+ }
+ SVGElement parent = t.getParent();
+ if (parent instanceof Text)
+ ((Text) parent).rebuild();
+ changed = true;
+ }
+ } else {
+ e.setAttribute(ass.attributeNameOrId, AnimationElement.AT_AUTO, ass.value);
+ changed = true;
+ }
+ }
+ }
+ diagram.updateTime(0);
+ return changed;
+ }
+
public static Rectangle2D getBounds(String data) {
- return getBounds(data, null);
+ return getBounds(data, null);
}
public static Rectangle2D getBounds(String data, List<SVGNodeAssignment> assignments) {
}
return rect;
} catch (SVGException e) {
- return ((Rectangle2D) diagramCache.getViewRect().clone());
+ return diagramCache.getViewRect(new Rectangle2D.Double());
} catch(IOException e) {
}
return null;
URI uri = univ.loadSVG(new ByteArrayInputStream(dataBytes), digest);
diagramCache = univ.getDiagram(uri, false);
if (diagramCache != null) {
- SVGRoot root = diagramCache.getRoot();
+ SVGRoot root = diagramCache.getRoot();
if (root == null) return new Rectangle2D.Double();
return (Rectangle2D)root.getBoundingBox().clone();
}
}
} catch (SVGException e) {
- return ((Rectangle2D) diagramCache.getViewRect().clone());
+ return diagramCache.getViewRect(new Rectangle2D.Double());
} catch(IOException e) {
}
return null;
this.setTransform(new AffineTransform(data));
}
+ public String getSVGText() {
+ String ret = data.replace("<svg", "<g").replaceAll("svg>", "g>");
+ //return diagramCache.toString();
+ //return data.replace("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"><svg xmlns=\"http://www.w3.org/2000/svg\" overflow=\"visible\" version=\"1.1\"", "<g").replaceAll("svg>", "/g>");
+ return ret;
+ }
+
}