]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/MipMapVRamBufferedImage.java
Replace System.err and System.out with SLF4J Logging
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / utils / MipMapVRamBufferedImage.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.scenegraph.utils;
13
14 import java.awt.Color;
15 import java.awt.Graphics2D;
16 import java.awt.GraphicsConfiguration;
17 import java.awt.Point;
18 import java.awt.RenderingHints;
19 import java.awt.geom.AffineTransform;
20 import java.awt.geom.Rectangle2D;
21 import java.awt.image.VolatileImage;
22 import java.util.concurrent.atomic.AtomicInteger;
23
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 import com.kitfox.svg.SVGDiagram;
28
29 /**
30  * Video-ram cache suitable for rasterized PaintableSymbols scalable vector graphics.
31  * <p>
32  * This implementation rasterizes the same symbol from different mip map levels.
33  * 
34  * @see VRamImage
35  * @author Toni Kalajainen
36  */
37 public class MipMapVRamBufferedImage extends MipMapBufferedImage {
38
39     private static final Logger LOGGER = LoggerFactory.getLogger(MipMapVRamBufferedImage.class);
40     /**
41      * @param original
42      * @param imageBounds
43      * @param referenceSize a reference size for the rasterized images or
44      *        <code>null</code> to not specify one in which case a default
45      *        resolution is used
46      * @param gc
47      */
48     public MipMapVRamBufferedImage(SVGDiagram original, Rectangle2D imageBounds, Point referenceSize)
49     {
50         super(original, imageBounds, referenceSize);
51     }
52
53     @Override
54     protected IRaster createRaster(double resolution) {
55         return new VolatileRaster(resolution);
56     }
57
58     @Override
59     protected double getRasterRenderingThresholdResolution() {
60         return maxResolution*1.5;
61     }
62
63     @Override
64     protected void setupSourceRender(Graphics2D g2d) {
65 //        g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
66 //        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
67 //        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
68 //        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
69 //        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
70 //        g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
71
72         g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
73         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
74         g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
75         g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
76         g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
77         g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
78     }
79
80     class VolatileRaster extends Raster {
81         VolatileImageProvider imageProvider;
82         int widMargin, heiMargin;
83         int wid, hei;
84         AtomicInteger validateResult = new AtomicInteger(VolatileImage.IMAGE_OK);
85
86         public VolatileRaster(double resolution) {
87             super(resolution);
88             double wid = imageBounds.getWidth();
89             double hei = imageBounds.getHeight();
90             this.wid = (int) (wid * resolution);
91             this.hei = (int) (hei * resolution);
92             widMargin = (int) (wid * resolution * (MARGIN_PERCENT/100)) +1;
93             heiMargin = (int) (hei * resolution * (MARGIN_PERCENT/100)) +1;
94             imageProvider = VolatileImageCache.getInstance().create(this.wid+widMargin*2, this.hei+heiMargin*2);
95             //System.out.println("VolatileRaster(" + resolution + "): " + this.wid + " x " + this.hei);
96         }
97
98         /**
99          * @param image
100          * @return
101          */
102         private VolatileImage sourceRender(VolatileImage image) {
103             Graphics2D target = image.createGraphics();
104             target.setBackground(new Color(255,255,255,0));
105             target.clearRect(0, 0, image.getWidth(), image.getHeight());
106
107             target.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
108             target.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
109             target.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
110             target.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
111
112             target.translate(widMargin, heiMargin);
113             target.scale(resolution, resolution);
114             target.translate(-imageBounds.getMinX(), -imageBounds.getMinY());
115             try {
116                 source.render(target);
117             } catch (Exception e) {
118                 e.printStackTrace();
119                 target.dispose();
120                 image = null;
121                 return null;
122             }
123             target.dispose();
124             //JAI.create("filestore", image.getSnapshot(), "d:/test" + (koss++) + ".png", "png");
125             return image;
126         }
127
128         synchronized VolatileImage restore(GraphicsConfiguration gc2) {
129             //System.out.println("restoring provider " + imageProvider);
130             VolatileImage image = imageProvider.get(gc2, this.validateResult);
131
132             // If a new image was created, we always need to render from source.
133             int validateResult = this.validateResult.get();
134             //System.out.println("got VolatileImage " + image + " (validation result=" + validated + ")");
135
136             // Couldn't get image? This is not supposed to happen but happened anyway.
137             if (image == null) {
138                 LOGGER.error("BUG: VolatileImageProvider.get returned null!");
139                 return null;
140             }
141
142 //            if (validateResult != VolatileImage.IMAGE_OK) {
143 //                System.out.println("NEED SOURCE RENDER FOR VOLATILE IMAGE PROVIDER " + imageProvider + " - " + image);
144 //            }
145
146             boolean contentsLost = validateResult != VolatileImage.IMAGE_OK || image.contentsLost();
147             return contentsLost ? sourceRender(image) : image;
148             //return contentsLost ? sourceRender(image) : sourceRender(image);
149         }
150
151         public void paint(Graphics2D g) {
152             VolatileImage image = restore(g.getDeviceConfiguration());
153             if (image==null)
154             {
155                 g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
156                 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
157                 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
158                 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
159
160                 try {
161                     source.render(g);
162                 } catch (Exception e) {
163                     // TODO Auto-generated catch block
164                     // NOTE: Catching Exception instead of SVGException due to an
165                     // NPE when encountering invalid color SVG definitions (e.g.
166                     // rgb(256,-1,0))
167                     e.printStackTrace();
168                 }
169                 return;
170             }
171             AffineTransform af = g.getTransform();
172             Object rh = g.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
173             try {
174                 /// Bicubic interpolation is very slow with opengl pipeline
175                 if (rh == RenderingHints.VALUE_INTERPOLATION_BICUBIC)
176                     g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
177                 g.translate(imageBounds.getMinX(), imageBounds.getMinY());
178                 g.scale(1/resolution, 1/resolution);
179                 g.translate(-widMargin, -heiMargin);
180                 g.drawImage(image, 0, 0, null);
181             } finally {
182                 g.setTransform(af);
183                 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, rh);
184             }
185         }
186
187         public void release() {
188             imageProvider.dispose();
189         }
190     }
191
192     //static long koss = 0;
193
194     /*
195     @Override
196     public int hashCode() {
197         return gc.hashCode() ^original.hashCode();
198     }
199
200     @Override
201     public boolean equals(Object obj) {
202         if (!(obj instanceof VRamBufferedImage)) return false;
203         VRamBufferedImage o = (VRamBufferedImage) obj;
204         return o.gc == gc && o.original.equals(original);
205     }
206      */
207
208 }