]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
SVGNode reference counting breaks with assignments 56/356/4
authorAntti Villberg <antti.villberg@semantum.fi>
Fri, 10 Mar 2017 09:07:30 +0000 (11:07 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Tue, 14 Mar 2017 10:04:52 +0000 (12:04 +0200)
refs #7078

Change-Id: I72c42302d6ed04d0cd5b95525d2ee68d9fda248b

bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java

index 97de387f8b0fce3bfcf2728a19b11cb9327b7894..d50c65056af7c6fe1e028cac2a8a3afefe9cb97d 100644 (file)
@@ -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<SVGNodeAssignment> 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<SVGNodeAssignment> 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;