diff options
author | Sven Gothel <[email protected]> | 2013-09-07 12:52:19 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-09-07 12:52:19 +0200 |
commit | 4b5e77961d1c660f3537f4041fc1a3ce47ef105c (patch) | |
tree | db6bd07357ce6a79d5cb6279b76fa58d99e7b508 /src/jogl/classes/jogamp | |
parent | 27c4a837580c7a68582e852d5ff64f733e669509 (diff) |
AWT/GL Printing WIP: Abstract AWT tile painting code out to AWTTilePainter, reused w/ GLCanvas and GLJPanel
Diffstat (limited to 'src/jogl/classes/jogamp')
-rw-r--r-- | src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java new file mode 100644 index 000000000..7493a19c5 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java @@ -0,0 +1,217 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.opengl.awt; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; + +import com.jogamp.opengl.util.TileRenderer; +import com.jogamp.opengl.util.TileRendererBase; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.awt.AWTGLPixelBuffer; +import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider; + +/** + * Implementing AWT {@link Graphics2D} based {@link TileRenderer} <i>painter</i>. + * <p> + * Maybe utilized for AWT printing. + * </p> + */ +public class AWTTilePainter { + final private TileRenderer renderer; + final private int componentCount; + final private boolean verbose; + + private AWTGLPixelBuffer tBuffer = null; + private BufferedImage vFlipImage = null; + private Graphics2D g2d = null; + + /** + * Assumes a configured {@link TileRenderer}, i.e. + * an {@link TileRenderer#attachToAutoDrawable(GLAutoDrawable) attached} + * {@link GLAutoDrawable} with {@link TileRenderer#setTileSize(int, int, int) set tile size}. + * <p> + * Sets the renderer to {@link TileRenderer#TR_TOP_TO_BOTTOM} row order. + * </p> + * <p> + * <code>componentCount</code> reflects opaque, i.e. 4 if non opaque. + * </p> + */ + public AWTTilePainter(TileRenderer renderer, int componentCount, boolean verbose) { + this.renderer = renderer; + this.renderer.setGLEventListener(preTileGLEL, postTileGLEL); + this.componentCount = componentCount; + this.verbose = verbose; + this.renderer.setRowOrder(TileRenderer.TR_TOP_TO_BOTTOM); + } + + public String toString() { return renderer.toString(); } + + public TileRenderer getTileRenderer() { return renderer; } + + /** + * Caches the {@link Graphics2D} instance for rendering. + * <p> + * Sets the {@link TileRenderer}'s {@link TileRenderer#setImageSize(int, int) image size} + * and {@link TileRenderer#setTileOffset(int, int) tile offset} according the + * the {@link Graphics2D#getClipBounds() graphics clip bounds}. + * </p> + * @param g2d + */ + public void updateGraphics2DAndClipBounds(Graphics2D g2d) { + this.g2d = g2d; + final Rectangle gClipOrig = g2d.getClipBounds(); + final Rectangle gClip = new Rectangle(gClipOrig); + if( 0 > gClip.x ) { + gClip.width += gClip.x; + gClip.x = 0; + } + if( 0 > gClip.y ) { + gClip.height += gClip.y; + gClip.y = 0; + } + if( verbose ) { + System.err.println("AWT print.0: "+gClipOrig+" -> "+gClip); + } + renderer.setImageSize(gClip.width, gClip.height); + renderer.setTileOffset(gClip.x, gClip.y); + } + + /** + * Disposes resources and {@link TileRenderer#detachFromAutoDrawable() detaches} + * the {@link TileRenderer}'s {@link GLAutoDrawable}. + */ + public void dispose() { + renderer.detachFromAutoDrawable(); // tile-renderer -> printGLAD + g2d = null; + if( null != tBuffer ) { + tBuffer.dispose(); + tBuffer = null; + } + if( null != vFlipImage ) { + vFlipImage.flush(); + vFlipImage = null; + } + } + + final GLEventListener preTileGLEL = new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + if( null == tBuffer ) { + final int tWidth = renderer.getParam(TileRenderer.TR_TILE_WIDTH); + final int tHeight = renderer.getParam(TileRenderer.TR_TILE_HEIGHT); + final AWTGLPixelBufferProvider printBufferProvider = new AWTGLPixelBufferProvider( true /* allowRowStride */ ); + final GLPixelAttributes pixelAttribs = printBufferProvider.getAttributes(gl, componentCount); + tBuffer = printBufferProvider.allocate(gl, pixelAttribs, tWidth, tHeight, 1, true, 0); + renderer.setTileBuffer(tBuffer); + vFlipImage = new BufferedImage(tBuffer.width, tBuffer.height, tBuffer.image.getType()); + } + if( verbose ) { + System.err.println("XXX tile-pre "+renderer); + } + } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }; + final GLEventListener postTileGLEL = new GLEventListener() { + int tTopRowHeight = 0; + @Override + public void init(GLAutoDrawable drawable) { + tTopRowHeight = 0; + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) { + // Copy temporary data into raster of BufferedImage for faster + // blitting Note that we could avoid this copy in the cases + // where !offscreenDrawable.isGLOriented(), + // but that's the software rendering path which is very slow anyway. + final int tWidth = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH); + final int tHeight = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT); + // final BufferedImage dstImage = printBuffer.image; + final BufferedImage srcImage = tBuffer.image; + final BufferedImage dstImage = vFlipImage; + final int[] src = ((DataBufferInt) srcImage.getRaster().getDataBuffer()).getData(); + final int[] dst = ((DataBufferInt) dstImage.getRaster().getDataBuffer()).getData(); + final int incr = tBuffer.width; + int srcPos = 0; + int destPos = (tHeight - 1) * tBuffer.width; + for (; destPos >= 0; srcPos += incr, destPos -= incr) { + System.arraycopy(src, srcPos, dst, destPos, incr); + } + // Draw resulting image in one shot + final int tRows = renderer.getParam(TileRenderer.TR_ROWS); + final int tRow = renderer.getParam(TileRenderer.TR_CURRENT_ROW); + final int pX = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS); + final int pYf; + if( tRow == tRows - 1 ) { + tTopRowHeight = tHeight; + pYf = 0; + } else if( tRow == tRows - 2 ){ + pYf = tTopRowHeight; + } else { + pYf = ( tRows - 2 - tRow ) * tHeight + tTopRowHeight; + } + final Shape oClip = g2d.getClip(); + g2d.clipRect(pX, pYf, tWidth, tHeight); + final Shape clip = g2d.getClip(); + g2d.drawImage(dstImage, pX, pYf, dstImage.getWidth(), dstImage.getHeight(), null); // Null ImageObserver since image data is ready. + g2d.setColor(Color.BLACK); + g2d.drawRect(pX, pYf, tWidth, tHeight); + { + final Rectangle r = oClip.getBounds(); + g2d.setColor(Color.YELLOW); + g2d.drawRect(r.x, r.y, r.width, r.height); + } + g2d.setClip(oClip); + if( verbose ) { + System.err.println("XXX tile-post.X clip "+oClip+" -> "+clip); + System.err.println("XXX tile-post.X "+renderer); + System.err.println("XXX tile-post.X dst-img "+dstImage.getWidth()+"x"+dstImage.getHeight()+" -> "+pX+"/"+pYf); + } + } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }; + +} |