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