From: Antti Villberg Date: Fri, 10 Mar 2017 09:07:30 +0000 (+0200) Subject: SVGNode reference counting breaks with assignments X-Git-Tag: v1.28.0~57 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=d9d532f32a94b62a8c2bfaeb1da0ad5ec429a21d;p=simantics%2Fplatform.git SVGNode reference counting breaks with assignments refs #7078 Change-Id: I72c42302d6ed04d0cd5b95525d2ee68d9fda248b --- diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java index 97de387f8..d50c65056 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java @@ -208,51 +208,59 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode { 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; + } + + // NOTE: hard-coded to assume all SVG data is encoded in UTF-8 + byte[] 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()); + + if (diagramCache.getRoot() == 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 = diagramCache.getRoot().getBoundingBox(); + if (bbox.isEmpty()) { + univ.decRefCount(diagramCache.getXMLBase()); + diagramCache = univ.getDiagram(univ.loadSVG(EMPTY_SVG_DATA), false); + dataHash = "empty"; + univ.incRefCount(diagramCache.getXMLBase()); + bbox = (Rectangle2D) diagramCache.getRoot().getBoundingBox().clone(); + } else { + if (applyAssignments(diagramCache, assignments)) { + bbox = (Rectangle2D) diagramCache.getRoot().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; } @@ -260,8 +268,34 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode { return dataHash; } + private static boolean applyAssignments(SVGDiagram diagram, List assignments) throws SVGException { + if (assignments.isEmpty()) + return false; + boolean changed = false; + for (SVGNodeAssignment ass : assignments) { + SVGElement e = diagram.getElement(ass.elementId); + if (e != null) { + if ("$text".equals(ass.attributeNameOrId)) { + if (e instanceof Tspan) { + Tspan t = (Tspan) e; + 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 assignments) { @@ -301,7 +335,7 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode { } return rect; } catch (SVGException e) { - return ((Rectangle2D) diagramCache.getViewRect().clone()); + return diagramCache.getViewRect(new Rectangle2D.Double()); } catch(IOException e) { } return null; @@ -330,13 +364,13 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode { 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;