]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java
Fix SCL SceneGraph is omitting graphical elements
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / SCLScenegraph.java
index 55ed12656131c0629595cd7ded70c4f4bd064234..40a5265852fa79083df1781db24a563df95d4532 100644 (file)
@@ -68,6 +68,7 @@ import org.simantics.scenegraph.g2d.nodes.BackgroundNode;
 import org.simantics.scenegraph.g2d.nodes.BoundsNode;
 import org.simantics.scenegraph.g2d.nodes.ConnectionNode;
 import org.simantics.scenegraph.g2d.nodes.DataNode;
+import org.simantics.scenegraph.g2d.nodes.LinkNode;
 import org.simantics.scenegraph.g2d.nodes.NavigationNode;
 import org.simantics.scenegraph.g2d.nodes.SVGNode;
 import org.simantics.scenegraph.g2d.nodes.SelectionNode;
@@ -93,9 +94,16 @@ public class SCLScenegraph {
        private static final String MAIN_SECTION = "main";
        private static final String SELECTION_SECTION = "selection";
        private static final String SELECTION_MASK_SECTION = "selectionMask";
-       
+
        private static final String[] ALL_SECTIONS = { MAIN_SECTION, SELECTION_SECTION, SELECTION_MASK_SECTION };
 
+       // Changed from 0.001 to 0.0001 to prevent creation of huge BufferedImage's when
+       // generating PDF from SVG. If SVG contains any transparency then Batik uses
+       // bitmap-rendering which remarkably slows things down
+       // See org.apache.batik.gvt.AbstractGraphicsNode.paint(Graphics2D) where decisions are made
+       // if AlphaComposite should be painted 
+       private static final String OPACITY = "0.0001";
+
        @Deprecated
        public static ICanvasSceneGraphProvider getICanvasSceneGraphProvider(Resource model, Resource diagram, String diagramRVI) throws DatabaseException, InterruptedException {
                ICanvasSceneGraphProvider provider = DiagramNodeUtil.loadSceneGraphProvider(model, diagram, diagramRVI);
@@ -666,22 +674,28 @@ public class SCLScenegraph {
                        // get the bounds of the content
                        Rectangle2D content = rtreeBounds;
                        
-                       // To account for dynamic padding of selection rectangles (5 units + stroke width)
-                       int offset = 6;
                        
-                       double scale = width < 0 || height < 0 ? 1.0 : Math.min((width - 2*offset) / content.getWidth(), (height - 2*offset) / content.getHeight());
-               
-                       AffineTransform tr = new AffineTransform();
-                       tr.translate(offset, offset);
-                       tr.scale(scale, scale);
-                       tr.translate(-content.getX(), -content.getY());
-                       tr.getMatrix(matrix);
+                       if (content != null) {
+                        // To account for dynamic padding of selection rectangles (5 units + stroke width)
+                   int offset = 6;
+                   
+                   double scale = width < 0 || height < 0 ? 1.0 : Math.min((width - 2*offset) / content.getWidth(), (height - 2*offset) / content.getHeight());
+               
+                   AffineTransform tr = new AffineTransform();
+                   tr.translate(offset, offset);
+                   tr.scale(scale, scale);
+                           tr.translate(-content.getX(), -content.getY());
+                           tr.getMatrix(matrix);
+                           svgGenerator.setSVGCanvasSize(new Dimension((int)Math.ceil(scale * content.getWidth()) + 2*offset, (int)Math.ceil(scale * content.getHeight()) + 2*offset));
+                       } else {
+                           svgGenerator.setSVGCanvasSize(new Dimension(100, 100));
+                       }
                        //svgGenerator.translate(offset, offset);
                        //svgGenerator.scale(scale, scale);
                        // translate svgGenerator to the x and y coordinates of current content
                        //svgGenerator.translate(-content.getX(), -content.getY());
 
-                       svgGenerator.setSVGCanvasSize(new Dimension((int)Math.ceil(scale * content.getWidth()) + 2*offset, (int)Math.ceil(scale * content.getHeight()) + 2*offset));
+                       
                        //svgGenerator.setClip(content);
                        
                        result.append(MAIN_SECTION, "<g class=\"symbols\">");
@@ -793,7 +807,7 @@ public class SCLScenegraph {
                 String key = getKey((ConnectionNode) node);
                 parentBuilder.append(MAIN_SECTION, "\n<g class=\"connection\" id=\"" + key + "\">");
                 parentBuilder.append(SELECTION_SECTION, "\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
-                parentBuilder.append(SELECTION_MASK_SECTION, "\n<g class=\"selectionMask\" opacity=\"0.001\" id=\"" + key + "\">");
+                parentBuilder.append(SELECTION_MASK_SECTION, "\n<g class=\"selectionMask\" opacity=\"" + OPACITY + "\" id=\"" + key + "\">");
                 
                 Element doc = renderSVGNode(svgGenerator, (IG2DNode)node);
                 String svg = printSVGDocument(doc);
@@ -821,7 +835,7 @@ public class SCLScenegraph {
                 parentBuilder.append(SELECTION_SECTION, "\n</g>");
                 parentBuilder.append(MAIN_SECTION, "\n</g>");
                 
-            } else if (node instanceof SelectionNode) {
+            } else if (isSelection0(node)) {
                 
                 SelectionNode n = (SelectionNode)node;
                 SingleElementNode parentSEN = (SingleElementNode)NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
@@ -841,7 +855,7 @@ public class SCLScenegraph {
                     Rectangle2D rect = n.getRect();
                     // NaN
                     if(rect.getHeight() == rect.getHeight() && rect.getWidth() == rect.getWidth()) {
-                           parentBuilder2.append(SELECTION_MASK_SECTION,"<rect style=\"fill:#fff\" opacity=\"0.001\"");
+                           parentBuilder2.append(SELECTION_MASK_SECTION,"<rect style=\"fill:#fff\" opacity=\"" + OPACITY + "\"");
                            parentBuilder2.append(SELECTION_MASK_SECTION," x=\"" + rect.getX() + "\" y=\"" + rect.getY() + "\"");
                            parentBuilder2.append(SELECTION_MASK_SECTION," width=\"" + rect.getWidth() + "\" height=\"" + rect.getHeight() + "\"");
                            parentBuilder2.append(SELECTION_MASK_SECTION,"></rect>");
@@ -849,9 +863,32 @@ public class SCLScenegraph {
                     parentBuilder2.append(SELECTION_MASK_SECTION,"\n</g>");
                    
                 }
+            } else if (node instanceof SelectionNode) {
+
+                Element doc = renderSVGNode(svgGenerator, (IG2DNode)node);
+                String svg = printSVGDocument(doc);
+                parentBuilder.append(MAIN_SECTION, "<g>");
+                parentBuilder.append(MAIN_SECTION, svg);
+                parentBuilder.append(MAIN_SECTION, "\n</g>");
+
             } else if (node instanceof SVGNode) {
                 SVGNode svg = (SVGNode)node;
+                AffineTransform at = svg.getTransform();
+                if (!at.isIdentity()) {
+                        if(at.getScaleX() == 1.0 && at.getScaleY() == 1.0 && at.getShearX() == 0.0 && at.getShearY() == 0.0) {
+                         String m = "translate(" + at.getTranslateX() + " " + at.getTranslateY() + ")";
+                         parentBuilder.append(MAIN_SECTION, "\n<g transform=\"" + m + "\">");
+                     } else {
+                         double[] ds = new double[6];
+                         at.getMatrix(ds);
+                         String m = "matrix(" + ds[0] + " " + ds[1] + " " + ds[2] + " " + ds[3] + " " + ds[4] + " " + ds[5] + ")";
+                         parentBuilder.append(MAIN_SECTION, "\n<g transform=\"" + m + "\">");
+                     }
+                }
                 parentBuilder.append(MAIN_SECTION, svg.getSVGText());
+                if (!at.isIdentity()) {
+                       parentBuilder.append(MAIN_SECTION, "\n</g>");
+                }
             } else if (node instanceof G2DParentNode) {
                 AffineTransform at = node.getTransform();
                 if(node instanceof SingleElementNode) {
@@ -876,12 +913,35 @@ public class SCLScenegraph {
                         parentBuilder.append(ALL_SECTIONS, "\n<g transform=\"" + m + "\">");
                     }
                 }
+            } else if (!(node instanceof RouteGraphNode) && !(node instanceof LinkNode)){
+               try {
+                       Element doc = renderSVGNode(svgGenerator, (IG2DNode)node);
+                       if (doc.getElementsByTagName("g").getLength() == 0)
+                               return;
+                       String svg = printSVGDocument(doc);
+                       parentBuilder.append(MAIN_SECTION, "<g>");
+                       parentBuilder.append(MAIN_SECTION, svg);
+                       parentBuilder.append(MAIN_SECTION, "\n</g>");
+               } catch (Exception e) {
+                       // TODO: There are nodes that do not behave well when rendered to SVG. For backwards compatibility, we don't handle the exceptions.
+               }
             }
 
             //enters.put(node, b.length());
 
         }
         
+        private boolean isSelection0(IG2DNode node) {
+            
+            if(node instanceof SelectionNode) {
+                SelectionNode sn = (SelectionNode)node;
+                return sn.getSelectionId() == 0;
+            } else {
+                return false;
+            }
+            
+        }
+        
         private RenderSVGContext getParentBuilder(IG2DNode node) {
             
             INode parentSEN = NodeUtil.getNearestParentOfType(node, SingleElementNode.class);