]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/export/ImageBuilder.java
Logger fixes after merge commit:fdbe8762
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / export / ImageBuilder.java
1 package org.simantics.diagram.export;\r
2 \r
3 import java.awt.Graphics2D;\r
4 import java.awt.Point;\r
5 import java.awt.RenderingHints;\r
6 import java.awt.geom.AffineTransform;\r
7 import java.awt.geom.Rectangle2D;\r
8 import java.awt.image.BufferedImage;\r
9 import java.io.File;\r
10 \r
11 import javax.imageio.ImageIO;\r
12 \r
13 import org.simantics.g2d.canvas.ICanvasContext;\r
14 import org.simantics.g2d.diagram.DiagramHints;\r
15 import org.simantics.g2d.diagram.DiagramUtils;\r
16 import org.simantics.g2d.diagram.IDiagram;\r
17 import org.simantics.g2d.participant.TransformUtil;\r
18 import org.simantics.scenegraph.g2d.G2DRenderingHints;\r
19 import org.simantics.scenegraph.utils.QualityHints;\r
20 import org.simantics.utils.page.MarginUtils;\r
21 \r
22 public class ImageBuilder {\r
23         File file;\r
24         Double dpi;\r
25         Point size;\r
26         double margin;\r
27 \r
28         \r
29         /**\r
30          * \r
31          * @param file File to write the image (optional)\r
32          * @param dpi Dots Per Inch\r
33          * @param size Image size in pixels\r
34          * @param margin percentage of image width for margins. 0.05 is 5%.\r
35          */\r
36         public ImageBuilder(File file, Double dpi, Point size, double margin) {\r
37                 this.file = file;\r
38                 this.dpi = dpi;\r
39                 this.size = size;\r
40                 this.margin = Math.max(margin,0.0);\r
41                 \r
42         }\r
43 \r
44         /**\r
45          * @param canvasContext\r
46          *            the canvas context to paint\r
47          * @param writeResults\r
48          *            <code>true</code> to actually write the resulting Image to the file.\r
49          */\r
50         public BufferedImage paint(ICanvasContext canvasContext) throws Exception {\r
51 \r
52                 Graphics2D g2 = null;\r
53                 BufferedImage image = null;\r
54                 try {\r
55                         IDiagram diagram = canvasContext.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM);\r
56                         Rectangle2D diagramRect = DiagramUtils.getContentRect(diagram);\r
57 \r
58                         if (diagramRect == null)\r
59                                 diagramRect = new Rectangle2D.Double(0, 0, 100, 100);\r
60 \r
61                         // add margins to content.\r
62                         double off = Math.max(diagramRect.getWidth(), diagramRect.getHeight()) * margin*0.5;\r
63                         diagramRect = new Rectangle2D.Double(diagramRect.getX() - off, diagramRect.getY() - off, diagramRect.getWidth() + off * 2.0, diagramRect.getHeight() + off * 2.0);\r
64 \r
65                         // Make sure the transformation is reset.\r
66                         AffineTransform tr = new AffineTransform();\r
67 \r
68                         Rectangle2D controlArea;\r
69                         if (dpi != null) {\r
70                                 double mmToInch = 1.0 / 25.0;\r
71                                 controlArea = new Rectangle2D.Double(0, 0, diagramRect.getWidth() * mmToInch * dpi, diagramRect.getHeight() * mmToInch * dpi);\r
72 \r
73                         } else {\r
74                                 controlArea = new Rectangle2D.Double(0, 0, size.getX(), size.getY());\r
75                         }\r
76 \r
77                         canvasContext.getSingleItem(TransformUtil.class).fitArea(controlArea, diagramRect, MarginUtils.NO_MARGINS);\r
78 \r
79                         int width = (int) controlArea.getWidth();\r
80                         int height = (int) controlArea.getHeight();\r
81                         long sizeBytes = width*height*3;\r
82                         long free = Runtime.getRuntime().freeMemory();\r
83                         if (sizeBytes >= free) { // TODO: should we estimate memory required for rendering?  \r
84                                 System.gc();\r
85                                 free = Runtime.getRuntime().freeMemory();\r
86                         }\r
87                         \r
88                         if (sizeBytes >= free) {\r
89                                 throw new Exception("There is not enough available memory to create the image; required " + sizeBytes + ", available " + free);\r
90                         }\r
91                         \r
92                         image = new BufferedImage(width, height , BufferedImage.TYPE_3BYTE_BGR);\r
93                         g2 = (Graphics2D) image.getGraphics();\r
94 \r
95                         QualityHints.HIGH_QUALITY_HINTS.setQuality(g2);\r
96                         g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);\r
97 \r
98 \r
99                         g2.setTransform(tr);\r
100                         g2.setClip(new Rectangle2D.Double(0, 0, controlArea.getWidth(), controlArea.getHeight()));\r
101 \r
102                         g2.setRenderingHint(G2DRenderingHints.KEY_CONTROL_BOUNDS, new Rectangle2D.Double(0, 0, controlArea.getWidth(), controlArea.getHeight()));\r
103 \r
104                         if (canvasContext.isLocked())\r
105                                 throw new IllegalStateException("cannot render image, canvas context is locked: " + canvasContext);\r
106 \r
107                         canvasContext.getSceneGraph().render(g2);\r
108                         \r
109                         if (file != null) {\r
110                                 String name = file.getName();\r
111                                 name = name.substring(name.lastIndexOf(".") + 1);\r
112                                 ImageIO.write(image, name, file);\r
113                         }\r
114 \r
115                 } finally {\r
116                         if (g2 != null)\r
117                                 g2.dispose();\r
118 \r
119                         \r
120 \r
121                 }\r
122                 return image;\r
123         }\r
124 }\r