X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scenegraph%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Futils%2FMipMapVRamBufferedImage.java;h=54323097badd9d77463d3dfe5497013e83ac93a9;hp=0570eeeb341cee263678446ab0c23588bd67032c;hb=1dfeb7d5c49b1391cd9d877e1eddab18995cb151;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/MipMapVRamBufferedImage.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/MipMapVRamBufferedImage.java index 0570eeeb3..54323097b 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/MipMapVRamBufferedImage.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/MipMapVRamBufferedImage.java @@ -1,204 +1,208 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.scenegraph.utils; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; -import java.awt.Point; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.awt.image.VolatileImage; -import java.util.concurrent.atomic.AtomicInteger; - -import com.kitfox.svg.SVGDiagram; - -/** - * Video-ram cache suitable for rasterized PaintableSymbols scalable vector graphics. - *

- * This implementation rasterizes the same symbol from different mip map levels. - * - * @see VRamImage - * @author Toni Kalajainen - */ -public class MipMapVRamBufferedImage extends MipMapBufferedImage { - - /** - * @param original - * @param imageBounds - * @param referenceSize a reference size for the rasterized images or - * null to not specify one in which case a default - * resolution is used - * @param gc - */ - public MipMapVRamBufferedImage(SVGDiagram original, Rectangle2D imageBounds, Point referenceSize) - { - super(original, imageBounds, referenceSize); - } - - @Override - protected IRaster createRaster(double resolution) { - return new VolatileRaster(resolution); - } - - @Override - protected double getRasterRenderingThresholdResolution() { - return maxResolution*1.5; - } - - @Override - protected void setupSourceRender(Graphics2D g2d) { -// g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED); -// g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); -// g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); -// g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); -// g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); -// g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE); - - g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED); - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); - g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE); - } - - class VolatileRaster extends Raster { - VolatileImageProvider imageProvider; - int widMargin, heiMargin; - int wid, hei; - AtomicInteger validateResult = new AtomicInteger(VolatileImage.IMAGE_OK); - - public VolatileRaster(double resolution) { - super(resolution); - double wid = imageBounds.getWidth(); - double hei = imageBounds.getHeight(); - this.wid = (int) (wid * resolution); - this.hei = (int) (hei * resolution); - widMargin = (int) (wid * resolution * (MARGIN_PERCENT/100)) +1; - heiMargin = (int) (hei * resolution * (MARGIN_PERCENT/100)) +1; - imageProvider = VolatileImageCache.getInstance().create(this.wid+widMargin*2, this.hei+heiMargin*2); - //System.out.println("VolatileRaster(" + resolution + "): " + this.wid + " x " + this.hei); - } - - /** - * @param image - * @return - */ - private VolatileImage sourceRender(VolatileImage image) { - Graphics2D target = image.createGraphics(); - target.setBackground(new Color(255,255,255,0)); - target.clearRect(0, 0, image.getWidth(), image.getHeight()); - - target.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - target.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - target.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - target.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - - target.translate(widMargin, heiMargin); - target.scale(resolution, resolution); - target.translate(-imageBounds.getMinX(), -imageBounds.getMinY()); - try { - source.render(target); - } catch (Exception e) { - e.printStackTrace(); - target.dispose(); - image = null; - return null; - } - target.dispose(); - //JAI.create("filestore", image.getSnapshot(), "d:/test" + (koss++) + ".png", "png"); - return image; - } - - synchronized VolatileImage restore(GraphicsConfiguration gc2) { - //System.out.println("restoring provider " + imageProvider); - VolatileImage image = imageProvider.get(gc2, this.validateResult); - - // If a new image was created, we always need to render from source. - int validateResult = this.validateResult.get(); - //System.out.println("got VolatileImage " + image + " (validation result=" + validated + ")"); - - // Couldn't get image? This is not supposed to happen but happened anyway. - if (image == null) { - System.err.println("BUG: VolatileImageProvider.get returned null!"); - return null; - } - -// if (validateResult != VolatileImage.IMAGE_OK) { -// System.out.println("NEED SOURCE RENDER FOR VOLATILE IMAGE PROVIDER " + imageProvider + " - " + image); -// } - - boolean contentsLost = validateResult != VolatileImage.IMAGE_OK || image.contentsLost(); - return contentsLost ? sourceRender(image) : image; - //return contentsLost ? sourceRender(image) : sourceRender(image); - } - - public void paint(Graphics2D g) { - VolatileImage image = restore(g.getDeviceConfiguration()); - if (image==null) - { - g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); - - try { - source.render(g); - } catch (Exception e) { - // TODO Auto-generated catch block - // NOTE: Catching Exception instead of SVGException due to an - // NPE when encountering invalid color SVG definitions (e.g. - // rgb(256,-1,0)) - e.printStackTrace(); - } - return; - } - AffineTransform af = g.getTransform(); - Object rh = g.getRenderingHint(RenderingHints.KEY_INTERPOLATION); - try { - /// Bicubic interpolation is very slow with opengl pipeline - if (rh == RenderingHints.VALUE_INTERPOLATION_BICUBIC) - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - g.translate(imageBounds.getMinX(), imageBounds.getMinY()); - g.scale(1/resolution, 1/resolution); - g.translate(-widMargin, -heiMargin); - g.drawImage(image, 0, 0, null); - } finally { - g.setTransform(af); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, rh); - } - } - - public void release() { - imageProvider.dispose(); - } - } - - //static long koss = 0; - - /* - @Override - public int hashCode() { - return gc.hashCode() ^original.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof VRamBufferedImage)) return false; - VRamBufferedImage o = (VRamBufferedImage) obj; - return o.gc == gc && o.original.equals(original); - } - */ - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.scenegraph.utils; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.VolatileImage; +import java.util.concurrent.atomic.AtomicInteger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.kitfox.svg.SVGDiagram; + +/** + * Video-ram cache suitable for rasterized PaintableSymbols scalable vector graphics. + *

+ * This implementation rasterizes the same symbol from different mip map levels. + * + * @see VRamImage + * @author Toni Kalajainen + */ +public class MipMapVRamBufferedImage extends MipMapBufferedImage { + + private static final Logger LOGGER = LoggerFactory.getLogger(MipMapVRamBufferedImage.class); + /** + * @param original + * @param imageBounds + * @param referenceSize a reference size for the rasterized images or + * null to not specify one in which case a default + * resolution is used + * @param gc + */ + public MipMapVRamBufferedImage(SVGDiagram original, Rectangle2D imageBounds, Point referenceSize) + { + super(original, imageBounds, referenceSize); + } + + @Override + protected IRaster createRaster(double resolution) { + return new VolatileRaster(resolution); + } + + @Override + protected double getRasterRenderingThresholdResolution() { + return maxResolution*1.5; + } + + @Override + protected void setupSourceRender(Graphics2D g2d) { +// g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED); +// g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); +// g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); +// g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); +// g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); +// g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE); + + g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE); + } + + class VolatileRaster extends Raster { + VolatileImageProvider imageProvider; + int widMargin, heiMargin; + int wid, hei; + AtomicInteger validateResult = new AtomicInteger(VolatileImage.IMAGE_OK); + + public VolatileRaster(double resolution) { + super(resolution); + double wid = imageBounds.getWidth(); + double hei = imageBounds.getHeight(); + this.wid = (int) (wid * resolution); + this.hei = (int) (hei * resolution); + widMargin = (int) (wid * resolution * (MARGIN_PERCENT/100)) +1; + heiMargin = (int) (hei * resolution * (MARGIN_PERCENT/100)) +1; + imageProvider = VolatileImageCache.getInstance().create(this.wid+widMargin*2, this.hei+heiMargin*2); + //System.out.println("VolatileRaster(" + resolution + "): " + this.wid + " x " + this.hei); + } + + /** + * @param image + * @return + */ + private VolatileImage sourceRender(VolatileImage image) { + Graphics2D target = image.createGraphics(); + target.setBackground(new Color(255,255,255,0)); + target.clearRect(0, 0, image.getWidth(), image.getHeight()); + + target.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + target.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + target.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + target.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + + target.translate(widMargin, heiMargin); + target.scale(resolution, resolution); + target.translate(-imageBounds.getMinX(), -imageBounds.getMinY()); + try { + source.render(target); + } catch (Exception e) { + e.printStackTrace(); + target.dispose(); + image = null; + return null; + } + target.dispose(); + //JAI.create("filestore", image.getSnapshot(), "d:/test" + (koss++) + ".png", "png"); + return image; + } + + synchronized VolatileImage restore(GraphicsConfiguration gc2) { + //System.out.println("restoring provider " + imageProvider); + VolatileImage image = imageProvider.get(gc2, this.validateResult); + + // If a new image was created, we always need to render from source. + int validateResult = this.validateResult.get(); + //System.out.println("got VolatileImage " + image + " (validation result=" + validated + ")"); + + // Couldn't get image? This is not supposed to happen but happened anyway. + if (image == null) { + LOGGER.error("BUG: VolatileImageProvider.get returned null!"); + return null; + } + +// if (validateResult != VolatileImage.IMAGE_OK) { +// System.out.println("NEED SOURCE RENDER FOR VOLATILE IMAGE PROVIDER " + imageProvider + " - " + image); +// } + + boolean contentsLost = validateResult != VolatileImage.IMAGE_OK || image.contentsLost(); + return contentsLost ? sourceRender(image) : image; + //return contentsLost ? sourceRender(image) : sourceRender(image); + } + + public void paint(Graphics2D g) { + VolatileImage image = restore(g.getDeviceConfiguration()); + if (image==null) + { + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + + try { + source.render(g); + } catch (Exception e) { + // TODO Auto-generated catch block + // NOTE: Catching Exception instead of SVGException due to an + // NPE when encountering invalid color SVG definitions (e.g. + // rgb(256,-1,0)) + e.printStackTrace(); + } + return; + } + AffineTransform af = g.getTransform(); + Object rh = g.getRenderingHint(RenderingHints.KEY_INTERPOLATION); + try { + /// Bicubic interpolation is very slow with opengl pipeline + if (rh == RenderingHints.VALUE_INTERPOLATION_BICUBIC) + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g.translate(imageBounds.getMinX(), imageBounds.getMinY()); + g.scale(1/resolution, 1/resolution); + g.translate(-widMargin, -heiMargin); + g.drawImage(image, 0, 0, null); + } finally { + g.setTransform(af); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, rh); + } + } + + public void release() { + imageProvider.dispose(); + } + } + + //static long koss = 0; + + /* + @Override + public int hashCode() { + return gc.hashCode() ^original.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof VRamBufferedImage)) return false; + VRamBufferedImage o = (VRamBufferedImage) obj; + return o.gc == gc && o.original.equals(original); + } + */ + +}