diff --git a/examples/src/main/java/edu/umd/cs/piccolo/examples/OffscreenCanvasExample.java b/examples/src/main/java/edu/umd/cs/piccolo/examples/OffscreenCanvasExample.java new file mode 100755 index 0000000..3dee51d --- /dev/null +++ b/examples/src/main/java/edu/umd/cs/piccolo/examples/OffscreenCanvasExample.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2008-2009, Piccolo2D project, http://piccolo2d.org + * Copyright (c) 1998-2008, University of Maryland + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided + * that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of conditions + * and the following disclaimer. + * + * 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. + * + * None of the name of the University of Maryland, the name of the Piccolo2D project, or the names of its + * contributors may be used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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. + */ +package edu.umd.cs.piccolo.examples; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Frame; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferStrategy; + +import edu.umd.cs.piccolo.activities.PActivity; +import edu.umd.cs.piccolo.nodes.PPath; +import edu.umd.cs.piccolo.nodes.PText; + +import edu.umd.cs.piccolox.POffscreenCanvas; + +/** + * Offscreen canvas example. + */ +public final class OffscreenCanvasExample { + + /** Frame. */ + private final Frame frame; + + /** Background color. */ + private final Color background = new Color(80, 80, 80); + + /** Offscreen canvas. */ + private final POffscreenCanvas canvas; + + + /** + * Create a new offscreen canvas example with the specified graphics device. + * + * @param device graphics device + */ + public OffscreenCanvasExample(final GraphicsDevice device) { + GraphicsConfiguration configuration = device.getDefaultConfiguration(); + frame = new Frame(configuration); + frame.setUndecorated(true); + frame.setIgnoreRepaint(true); + frame.setBounds(100, 100, 400, 400); + frame.setVisible(true); + frame.createBufferStrategy(2); + + canvas = new POffscreenCanvas(400, 400); + + PText text = new PText("Offscreen Canvas Example"); + text.setFont(text.getFont().deriveFont(32.0f)); + text.setTextPaint(new Color(200, 200, 200)); + text.offset(200.0f - (text.getWidth() / 2.0f), 200.0f - (text.getHeight() / 2.0f)); + + PPath rect = PPath.createRectangle(0.0f, 0.0f, 360.0f, 360.0f); + rect.setPaint(new Color(20, 20, 20, 80)); + rect.setStroke(new BasicStroke(2.0f)); + rect.setStrokePaint(new Color(20, 20, 20)); + rect.offset(20.0f, 20.0f); + + canvas.getCamera().getLayer(0).addChild(text); + canvas.getCamera().getLayer(0).addChild(rect); + + Rectangle2D right = new Rectangle2D.Double(200.0f, 200.0f, 800.0f, 800.0f); + Rectangle2D left = new Rectangle2D.Double(-200.0f, 200.0f, 225.0f, 225.0f); + Rectangle2D start = new Rectangle2D.Double(0.0f, 0.0f, 400.0f, 400.0f); + PActivity toRight = canvas.getCamera().animateViewToCenterBounds(right, true, 5000); + PActivity toLeft = canvas.getCamera().animateViewToCenterBounds(left, true, 5000); + PActivity toStart = canvas.getCamera().animateViewToCenterBounds(start, true, 5000); + toLeft.setStartTime(toLeft.getStartTime() + 5000); + toStart.setStartTime(toStart.getStartTime() + 10000); + } + + + /** + * Render offscreen graphics into the frame. + */ + private void render() { + BufferStrategy bufferStrategy = frame.getBufferStrategy(); + do { + do { + Graphics2D graphics = (Graphics2D) bufferStrategy.getDrawGraphics(); + // canvas is not opaque, so fill with background color + graphics.setPaint(background); + graphics.fillRect(0, 0, 400, 400); + // then let canvas render into graphics + canvas.render(graphics); + graphics.dispose(); + } + while (bufferStrategy.contentsRestored()); + bufferStrategy.show(); + } + while (bufferStrategy.contentsLost()); + } + + + /** + * Main. + * + * @param args command line arguments + */ + public static void main(final String[] args) { + GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice device = environment.getDefaultScreenDevice(); + OffscreenCanvasExample example = new OffscreenCanvasExample(device); + + boolean done = false; + while (!done) { + example.render(); + } + } +} diff --git a/extras/src/main/java/edu/umd/cs/piccolox/POffscreenCanvas.java b/extras/src/main/java/edu/umd/cs/piccolox/POffscreenCanvas.java new file mode 100755 index 0000000..3166efc --- /dev/null +++ b/extras/src/main/java/edu/umd/cs/piccolox/POffscreenCanvas.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2008-2009, Piccolo2D project, http://piccolo2d.org + * Copyright (c) 1998-2008, University of Maryland + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided + * that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of conditions + * and the following disclaimer. + * + * 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. + * + * None of the name of the University of Maryland, the name of the Piccolo2D project, or the names of its + * contributors may be used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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. + */ +package edu.umd.cs.piccolox; + +import java.awt.Cursor; +import java.awt.Graphics2D; + +import edu.umd.cs.piccolo.PCamera; +import edu.umd.cs.piccolo.PComponent; + +import edu.umd.cs.piccolo.util.PBounds; +import edu.umd.cs.piccolo.util.PPaintContext; +import edu.umd.cs.piccolo.util.PUtil; + +/** + * Offscreen canvas. + */ +public final class POffscreenCanvas implements PComponent { + + /** Bounds of this offscreen canvas. */ + private final PBounds bounds; + + /** Camera for this offscreen canvas. */ + private PCamera camera; + + + /** + * Create a new offscreen canvas the specified width and height. + * + * @param width width of this offscreen canvas, must be at least zero + * @param height height of this offscreen canvas, must be at least zero + */ + public POffscreenCanvas(final int width, final int height) { + if (width < 0) { + throw new IllegalArgumentException("width must be at least zero, was " + width); + } + if (height < 0) { + throw new IllegalArgumentException("height must be at least zero, was " + height); + } + bounds = new PBounds(0.0d, 0.0d, width, height); + setCamera(PUtil.createBasicScenegraph()); + } + + + /** + * Render this offscreen canvas to the specified graphics. + * + * @param graphics graphics to render this offscreen canvas to, must not be null + */ + public void render(final Graphics2D graphics) { + if (graphics == null) { + throw new IllegalArgumentException("graphics must not be null"); + } + PPaintContext paintContext = new PPaintContext(graphics); + paintContext.setRenderQuality(PPaintContext.HIGH_QUALITY_RENDERING); + camera.fullPaint(paintContext); + } + + /** + * Set the camera for this offscreen canvas to camera. + * + * @param camera camera for this offscreen canvas + */ + public void setCamera(final PCamera camera) { + if (this.camera != null) { + this.camera.setComponent(null); + } + this.camera = camera; + if (camera != null) { + camera.setComponent(this); + camera.setBounds((PBounds) bounds.clone()); + } + } + + /** + * Return the camera for this offscreen canvas. + * + * @return the camera for this offscreen canvas + */ + public PCamera getCamera() { + return camera; + } + + /**{@inheritDoc} */ + public final void paintImmediately() { + // empty + } + + /**{@inheritDoc} */ + public final void popCursor() { + // empty + } + + /**{@inheritDoc} */ + public final void pushCursor(final Cursor cursor) { + // empty + } + + /**{@inheritDoc} */ + public final void repaint(final PBounds repaintBounds) { + // empty + } + + /**{@inheritDoc} */ + public final void setInteracting(final boolean interacting) { + // empty + } +} \ No newline at end of file diff --git a/extras/src/test/java/edu/umd/cs/piccolox/POffscreenCanvasTest.java b/extras/src/test/java/edu/umd/cs/piccolox/POffscreenCanvasTest.java new file mode 100755 index 0000000..8e51185 --- /dev/null +++ b/extras/src/test/java/edu/umd/cs/piccolox/POffscreenCanvasTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2008-2009, Piccolo2D project, http://piccolo2d.org + * Copyright (c) 1998-2008, University of Maryland + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided + * that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of conditions + * and the following disclaimer. + * + * 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. + * + * None of the name of the University of Maryland, the name of the Piccolo2D project, or the names of its + * contributors may be used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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. + */ +package edu.umd.cs.piccolox; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Graphics2D; + +import java.awt.image.BufferedImage; + +import edu.umd.cs.piccolo.PCamera; + +import edu.umd.cs.piccolo.nodes.PPath; + +import edu.umd.cs.piccolo.util.PBounds; + +import junit.framework.TestCase; + +/** + * Unit test for POffscreenCanvas. + */ +public class POffscreenCanvasTest extends TestCase { + + public void testConstructor() { + POffscreenCanvas canvas0 = new POffscreenCanvas(100, 100); + assertNotNull(canvas0); + POffscreenCanvas canvas1 = new POffscreenCanvas(0, 0); + assertNotNull(canvas1); + POffscreenCanvas canvas2 = new POffscreenCanvas(0, 100); + assertNotNull(canvas2); + POffscreenCanvas canvas3 = new POffscreenCanvas(100, 0); + assertNotNull(canvas3); + + try { + POffscreenCanvas canvas = new POffscreenCanvas(-1, 100); + fail("ctr(-1, 100) expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + try { + POffscreenCanvas canvas = new POffscreenCanvas(100, -1); + fail("ctr(100, -1) expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + try { + POffscreenCanvas canvas = new POffscreenCanvas(-1, -1); + fail("ctr(-1, -1) expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + } + + public void testCamera() { + POffscreenCanvas canvas = new POffscreenCanvas(100, 200); + assertNotNull(canvas); + PCamera camera = canvas.getCamera(); + assertNotNull(camera); + assertEquals(canvas, camera.getComponent()); + PCamera camera1 = new PCamera(); + canvas.setCamera(camera1); + assertEquals(camera1, canvas.getCamera()); + assertEquals(null, camera.getComponent()); + assertEquals(canvas, camera1.getComponent()); + canvas.setCamera(null); + assertEquals(null, camera1.getComponent()); + assertEquals(null, canvas.getCamera()); + } + + public void testRenderEmpty() { + POffscreenCanvas canvas = new POffscreenCanvas(100, 200); + BufferedImage image = new BufferedImage(100, 200, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = image.createGraphics(); + canvas.render(graphics); + for (int x = 0; x < 100; x++) + { + for (int y = 0; y < 200; y++) + { + assertEquals(0, image.getRGB(x, y)); + } + } + } + + public void testRenderFull() { + POffscreenCanvas canvas = new POffscreenCanvas(100, 200); + PPath rect = PPath.createRectangle(0.0f, 0.0f, 200.0f, 300.0f); + rect.setPaint(new Color(255, 0, 0)); + rect.setStroke(null); + rect.offset(-100.0d, -100.0d); + canvas.getCamera().getLayer(0).addChild(rect); + BufferedImage image = new BufferedImage(100, 200, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = image.createGraphics(); + canvas.render(graphics); + for (int x = 0; x < 100; x++) + { + for (int y = 0; y < 200; y++) + { + // red pixel, RGBA is 255, 0, 0, 255 + assertEquals(-65536, image.getRGB(x, y)); + } + } + } + + public void testRenderNull() { + try { + POffscreenCanvas canvas = new POffscreenCanvas(100, 200); + canvas.render(null); + fail("render(null) expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + } + + public void testPaintImmediately() { + POffscreenCanvas canvas = new POffscreenCanvas(100, 200); + canvas.paintImmediately(); + } + + public void testPopCursor() { + POffscreenCanvas canvas = new POffscreenCanvas(100, 200); + canvas.popCursor(); + } + + public void testPushCursor() { + POffscreenCanvas canvas = new POffscreenCanvas(100, 200); + canvas.pushCursor(null); + canvas.pushCursor(Cursor.getDefaultCursor()); + } + + public void testInteracting() { + POffscreenCanvas canvas = new POffscreenCanvas(100, 200); + canvas.setInteracting(true); + canvas.setInteracting(false); + } +} \ No newline at end of file