--- /dev/null
+package org.simantics.diagram.export;\r
+\r
+import java.awt.Graphics2D;\r
+import java.awt.Point;\r
+import java.awt.RenderingHints;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Rectangle2D;\r
+import java.awt.image.BufferedImage;\r
+import java.io.File;\r
+\r
+import javax.imageio.ImageIO;\r
+\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.DiagramUtils;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.participant.TransformUtil;\r
+import org.simantics.scenegraph.g2d.G2DRenderingHints;\r
+import org.simantics.scenegraph.utils.QualityHints;\r
+import org.simantics.utils.page.MarginUtils;\r
+\r
+public class ImageBuilder {\r
+ File file;\r
+ Double dpi;\r
+ Point size;\r
+ double margin;\r
+\r
+ \r
+ /**\r
+ * \r
+ * @param file File to write the image (optional)\r
+ * @param dpi Dots Per Inch\r
+ * @param size Image size in pixels\r
+ * @param margin percentage of image width for margins. 0.05 is 5%.\r
+ */\r
+ public ImageBuilder(File file, Double dpi, Point size, double margin) {\r
+ this.file = file;\r
+ this.dpi = dpi;\r
+ this.size = size;\r
+ this.margin = Math.max(margin,0.0);\r
+ \r
+ }\r
+\r
+ /**\r
+ * @param canvasContext\r
+ * the canvas context to paint\r
+ * @param writeResults\r
+ * <code>true</code> to actually write the resulting Image to the file.\r
+ */\r
+ public BufferedImage paint(ICanvasContext canvasContext) throws Exception {\r
+\r
+ Graphics2D g2 = null;\r
+ BufferedImage image = null;\r
+ try {\r
+ IDiagram diagram = canvasContext.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM);\r
+ Rectangle2D diagramRect = DiagramUtils.getContentRect(diagram);\r
+\r
+ if (diagramRect == null)\r
+ diagramRect = new Rectangle2D.Double(0, 0, 100, 100);\r
+\r
+ // add margins to content.\r
+ double off = Math.max(diagramRect.getWidth(), diagramRect.getHeight()) * margin*0.5;\r
+ diagramRect = new Rectangle2D.Double(diagramRect.getX() - off, diagramRect.getY() - off, diagramRect.getWidth() + off * 2.0, diagramRect.getHeight() + off * 2.0);\r
+\r
+ // Make sure the transformation is reset.\r
+ AffineTransform tr = new AffineTransform();\r
+\r
+ Rectangle2D controlArea;\r
+ if (dpi != null) {\r
+ double mmToInch = 1.0 / 25.0;\r
+ controlArea = new Rectangle2D.Double(0, 0, diagramRect.getWidth() * mmToInch * dpi, diagramRect.getHeight() * mmToInch * dpi);\r
+\r
+ } else {\r
+ controlArea = new Rectangle2D.Double(0, 0, size.getX(), size.getY());\r
+ }\r
+\r
+ canvasContext.getSingleItem(TransformUtil.class).fitArea(controlArea, diagramRect, MarginUtils.NO_MARGINS);\r
+\r
+ int width = (int) controlArea.getWidth();\r
+ int height = (int) controlArea.getHeight();\r
+ long sizeBytes = width*height*3;\r
+ long free = Runtime.getRuntime().freeMemory();\r
+ if (sizeBytes >= free) { // TODO: should we estimate memory required for rendering? \r
+ System.gc();\r
+ free = Runtime.getRuntime().freeMemory();\r
+ }\r
+ \r
+ if (sizeBytes >= free) {\r
+ throw new Exception("There is not enough available memory to create the image; required " + sizeBytes + ", available " + free);\r
+ }\r
+ \r
+ image = new BufferedImage(width, height , BufferedImage.TYPE_3BYTE_BGR);\r
+ g2 = (Graphics2D) image.getGraphics();\r
+\r
+ QualityHints.HIGH_QUALITY_HINTS.setQuality(g2);\r
+ g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);\r
+\r
+\r
+ g2.setTransform(tr);\r
+ g2.setClip(new Rectangle2D.Double(0, 0, controlArea.getWidth(), controlArea.getHeight()));\r
+\r
+ g2.setRenderingHint(G2DRenderingHints.KEY_CONTROL_BOUNDS, new Rectangle2D.Double(0, 0, controlArea.getWidth(), controlArea.getHeight()));\r
+\r
+ if (canvasContext.isLocked())\r
+ throw new IllegalStateException("cannot render image, canvas context is locked: " + canvasContext);\r
+\r
+ canvasContext.getSceneGraph().render(g2);\r
+ \r
+ if (file != null) {\r
+ String name = file.getName();\r
+ name = name.substring(name.lastIndexOf(".") + 1);\r
+ ImageIO.write(image, name, file);\r
+ }\r
+\r
+ } finally {\r
+ if (g2 != null)\r
+ g2.dispose();\r
+\r
+ \r
+\r
+ }\r
+ return image;\r
+ }\r
+}\r