1 /*
   2  * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.scene;
  27 
  28 import java.util.ArrayList;
  29 import java.util.Collection;
  30 import javafx.geometry.Rectangle2D;
  31 import javafx.scene.image.WritableImage;
  32 import javafx.scene.shape.Rectangle;
  33 import javafx.scene.transform.Transform;
  34 import javafx.util.Callback;
  35 import org.junit.After;
  36 import org.junit.AfterClass;
  37 import org.junit.Before;
  38 import org.junit.BeforeClass;
  39 import org.junit.Ignore;
  40 import org.junit.Test;
  41 import org.junit.runner.RunWith;
  42 import org.junit.runners.Parameterized;
  43 import org.junit.runners.Parameterized.Parameters;
  44 import util.Util;
  45 
  46 import static org.junit.Assert.*;
  47 
  48 /**
  49  * Test program for showAndWait functionality.
  50  */
  51 @RunWith(Parameterized.class)
  52 public class Snapshot2Test extends SnapshotCommon {
  53 
  54     @BeforeClass
  55     public static void setupOnce() {
  56         doSetupOnce();
  57     }
  58 
  59     @AfterClass
  60     public static void teardownOnce() {
  61         doTeardownOnce();
  62     }
  63 
  64     // Flag indicating snapshot should be taken on a live scene, that is a
  65     // scene attached to the primary stage
  66     private final boolean live;
  67 
  68     // Flag indicating to use an existing image
  69     private final boolean useImage;
  70 
  71     // Temporary stage, scene, and node used for testing
  72     private TestStage tmpStage = null;
  73     private Scene tmpScene = null;
  74     private Node tmpNode = null;
  75 
  76     private static Collection params = null;
  77 
  78     private static final Object[] pLive = { Boolean.FALSE, Boolean.TRUE };
  79     private static final Object[] pUseImage = { Boolean.FALSE, Boolean.TRUE };
  80 
  81     @Parameters
  82     public static Collection getParams() {
  83         if (params == null) {
  84             params = new ArrayList();
  85             for (Object o0 : pLive) {
  86                 for (Object o1 : pUseImage) {
  87                     params.add(new Object[] { o0, o1 });
  88                 }
  89             }
  90         }
  91         return params;
  92     }
  93 
  94     public Snapshot2Test(Boolean live, Boolean useImage) {
  95         this.live = live;
  96         this.useImage = useImage;
  97     }
  98 
  99     @Before
 100     public void setupEach() {
 101         assertNotNull(myApp);
 102         assertNotNull(myApp.primaryStage);
 103         assertTrue(myApp.primaryStage.isShowing());
 104     }
 105 
 106     @After
 107     public void teardownEach() {
 108         Util.runAndWait(() -> {
 109             if (tmpStage != null && tmpStage.isShowing()) {
 110                 tmpStage.hide();
 111             }
 112         });
 113     }
 114 
 115     // ========================== TEST CASES ==========================
 116 
 117     private void setupEmptyScene() {
 118         Util.runAndWait(() -> {
 119             Group root = new Group();
 120             tmpScene = new Scene(root);
 121             if (live) {
 122                 tmpStage = new TestStage(tmpScene);
 123                 assertNotNull(tmpScene.getWindow());
 124                 tmpStage.show();
 125             } else {
 126                 assertNull(tmpScene.getWindow());
 127             }
 128         });
 129     }
 130 
 131     // Verify a snapshot of an empty scene / root node
 132     @Test
 133     public void testSnapshotEmptySceneImm() {
 134         setupEmptyScene();
 135 
 136         final WritableImage img = useImage ? new WritableImage(1, 1) : null;
 137         Util.runAndWait(() -> {
 138             WritableImage wimg = tmpScene.snapshot(img);
 139             assertNotNull(wimg);
 140             if (img != null) {
 141                 assertSame(img, wimg);
 142             }
 143 
 144             assertEquals(1, (int)wimg.getWidth());
 145             assertEquals(1, (int)wimg.getHeight());
 146         });
 147     }
 148 
 149     @Test
 150     public void testSnapshotEmptySceneDefer() {
 151         setupEmptyScene();
 152         final WritableImage img = useImage ? new WritableImage(1, 1) : null;
 153         runDeferredSnapshotWait(tmpScene, result -> {
 154             assertSame(tmpScene, result.getSource());
 155             assertNull(result.getSnapshotParameters());
 156             assertNotNull(result.getImage());
 157             if (img != null) {
 158                 assertSame(img, result.getImage());
 159             }
 160 
 161             assertEquals(1, (int)result.getImage().getWidth());
 162             assertEquals(1, (int)result.getImage().getHeight());
 163 
 164             return null;
 165         }, img);
 166     }
 167 
 168     private void doTestSnapshotEmptyNodeImm(final SnapshotParameters snapshotParams) {
 169         setupEmptyScene();
 170         final WritableImage img = useImage ? new WritableImage(1, 1) : null;
 171         Util.runAndWait(() -> {
 172             WritableImage wimg = tmpScene.getRoot().snapshot(snapshotParams, img);
 173             assertNotNull(wimg);
 174             if (img != null) {
 175                 assertSame(img, wimg);
 176             }
 177 
 178             assertEquals(1, (int)wimg.getWidth());
 179             assertEquals(1, (int)wimg.getHeight());
 180         });
 181     }
 182 
 183     @Test
 184     public void testSnapshotEmptyNodeImmNoParams() {
 185         doTestSnapshotEmptyNodeDefer(null);
 186     }
 187 
 188     @Test
 189     public void testSnapshotEmptyNodeImm() {
 190         doTestSnapshotEmptyNodeDefer(new SnapshotParameters());
 191     }
 192 
 193     private void doTestSnapshotEmptyNodeDefer(final SnapshotParameters snapshotParams) {
 194         setupEmptyScene();
 195         final WritableImage img = useImage ? new WritableImage(1, 1) : null;
 196         runDeferredSnapshotWait(tmpScene.getRoot(), result -> {
 197             assertSame(tmpScene.getRoot(), result.getSource());
 198             assertNotNull(result.getSnapshotParameters());
 199             assertNotNull(result.getImage());
 200             if (img != null) {
 201                 assertSame(img, result.getImage());
 202             }
 203 
 204             assertEquals(1, (int)result.getImage().getWidth());
 205             assertEquals(1, (int)result.getImage().getHeight());
 206 
 207             return null;
 208         }, snapshotParams, img);
 209     }
 210 
 211     @Test
 212     public void testSnapshotEmptyNodeDeferNoParams() {
 213         doTestSnapshotEmptyNodeImm(null);
 214     }
 215 
 216     @Test
 217     public void testSnapshotEmptyNodeDefer() {
 218         doTestSnapshotEmptyNodeImm(new SnapshotParameters());
 219     }
 220 
 221     private static final int SCENE_W = 200;
 222     private static final int SCENE_H = 100;
 223     private static final int NODE_W = SCENE_W - 2*10;
 224     private static final int NODE_H = SCENE_H - 2*5;
 225 
 226     private void setupSimpleScene() {
 227         Util.runAndWait(() -> {
 228             tmpNode = new Rectangle(10, 5, NODE_W, NODE_H);
 229             Group root = new Group();
 230             tmpScene = new Scene(root, SCENE_W, SCENE_H);
 231             root.getChildren().add(tmpNode);
 232             if (live) {
 233                 tmpStage = new TestStage(tmpScene);
 234                 assertNotNull(tmpScene.getWindow());
 235                 tmpStage.show();
 236             } else {
 237                 assertNull(tmpScene.getWindow());
 238             }
 239         });
 240     }
 241 
 242     // Test snapshot of a simple scene
 243 
 244     @Test
 245     public void testSnapshotSimpleSceneImm() {
 246         setupSimpleScene();
 247 
 248         final WritableImage img = useImage ? new WritableImage(SCENE_W, SCENE_H) : null;
 249         Util.runAndWait(() -> {
 250             WritableImage wimg = tmpScene.snapshot(img);
 251             assertNotNull(wimg);
 252             if (img != null) {
 253                 assertSame(img, wimg);
 254             }
 255 
 256             assertEquals(SCENE_W, (int)wimg.getWidth());
 257             assertEquals(SCENE_H, (int)wimg.getHeight());
 258         });
 259     }
 260 
 261     @Test
 262     public void testSnapshotSimpleSceneDefer() {
 263         setupSimpleScene();
 264 
 265         final WritableImage img = useImage ? new WritableImage(SCENE_W, SCENE_H) : null;
 266         runDeferredSnapshotWait(tmpScene, result -> {
 267             assertSame(tmpScene, result.getSource());
 268             assertNull(result.getSnapshotParameters());
 269             assertNotNull(result.getImage());
 270             if (img != null) {
 271                 assertSame(img, result.getImage());
 272             }
 273 
 274             assertEquals(SCENE_W, (int)result.getImage().getWidth());
 275             assertEquals(SCENE_H, (int)result.getImage().getHeight());
 276 
 277             return null;
 278         }, img);
 279     }
 280 
 281     @Test
 282     public void testSnapshotSimpleNodeImm() {
 283         setupSimpleScene();
 284         final SnapshotParameters snapshotParams = new SnapshotParameters();
 285         final WritableImage img = useImage ? new WritableImage(NODE_W, NODE_H) : null;
 286         Util.runAndWait(() -> {
 287             WritableImage wimg = tmpScene.getRoot().snapshot(snapshotParams, img);
 288             assertNotNull(wimg);
 289             if (img != null) {
 290                 assertSame(img, wimg);
 291             }
 292 
 293             assertEquals(NODE_W, (int)wimg.getWidth());
 294             assertEquals(NODE_H, (int)wimg.getHeight());
 295         });
 296     }
 297 
 298     @Test
 299     public void testSnapshotSimpleNodeDefer() {
 300         setupSimpleScene();
 301         final SnapshotParameters snapshotParams = new SnapshotParameters();
 302         final WritableImage img = useImage ? new WritableImage(NODE_W, NODE_H) : null;
 303         runDeferredSnapshotWait(tmpScene.getRoot(), result -> {
 304             assertSame(tmpScene.getRoot(), result.getSource());
 305             assertNotNull(result.getSnapshotParameters());
 306             assertNotNull(result.getImage());
 307             if (img != null) {
 308                 assertSame(img, result.getImage());
 309             }
 310 
 311             assertEquals(NODE_W, (int)result.getImage().getWidth());
 312             assertEquals(NODE_H, (int)result.getImage().getHeight());
 313 
 314             return null;
 315         }, snapshotParams, img);
 316     }
 317 
 318     // Test node snapshot with a scale transform
 319 
 320     private void doTestSnapshotScaleNodeImm(int xScale, int yScale) {
 321         setupSimpleScene();
 322         final SnapshotParameters snapshotParams = new SnapshotParameters();
 323         snapshotParams.setTransform(Transform.scale(xScale, yScale));
 324         final int WIDTH = NODE_W * xScale;
 325         final int HEIGHT = NODE_H * yScale;
 326         final WritableImage img = useImage ? new WritableImage(WIDTH, HEIGHT) : null;
 327         Util.runAndWait(() -> {
 328             WritableImage wimg = tmpScene.getRoot().snapshot(snapshotParams, img);
 329             assertNotNull(wimg);
 330             if (img != null) {
 331                 assertSame(img, wimg);
 332             }
 333 
 334             assertEquals(WIDTH, (int)wimg.getWidth());
 335             assertEquals(HEIGHT, (int)wimg.getHeight());
 336         });
 337     }
 338 
 339     private void doTestSnapshotScaleNodeDefer(int xScale, int yScale) {
 340         setupSimpleScene();
 341         final SnapshotParameters snapshotParams = new SnapshotParameters();
 342         snapshotParams.setTransform(Transform.scale(xScale, yScale));
 343         final int WIDTH = NODE_W * xScale;
 344         final int HEIGHT = NODE_H * yScale;
 345         final WritableImage img = useImage ? new WritableImage(WIDTH, HEIGHT) : null;
 346         runDeferredSnapshotWait(tmpScene.getRoot(), result -> {
 347             assertSame(tmpScene.getRoot(), result.getSource());
 348             assertNotNull(result.getSnapshotParameters());
 349             assertNotNull(result.getImage());
 350             if (img != null) {
 351                 assertSame(img, result.getImage());
 352             }
 353 
 354             assertEquals(WIDTH, (int)result.getImage().getWidth());
 355             assertEquals(HEIGHT, (int)result.getImage().getHeight());
 356 
 357             return null;
 358         }, snapshotParams, img);
 359     }
 360 
 361     @Test
 362     public void testSnapshotScaleNodeImm() {
 363         doTestSnapshotScaleNodeImm(3, 3);
 364     }
 365 
 366     @Test
 367     public void testSnapshotScaleNodeDefer() {
 368         doTestSnapshotScaleNodeDefer(3, 3);
 369     }
 370 
 371     // TODO: Re-enable this test when RT-22073 is fixed
 372     @Ignore @Test
 373     public void testSnapshotBigXScaleNodeImm() {
 374         doTestSnapshotScaleNodeImm(100, 1);
 375     }
 376 
 377     // TODO: Re-enable this test when RT-22073 is fixed
 378     @Ignore @Test
 379     public void testSnapshotBigXScaleNodeDefer() {
 380         doTestSnapshotScaleNodeDefer(100, 1);
 381     }
 382 
 383     // TODO: Re-enable this test when RT-22073 is fixed
 384     @Ignore @Test
 385     public void testSnapshotBigYScaleNodeImm() {
 386         doTestSnapshotScaleNodeImm(1, 200);
 387     }
 388 
 389     // TODO: Re-enable this test when RT-22073 is fixed
 390     @Ignore @Test
 391     public void testSnapshotBigYScaleNodeDefer() {
 392         doTestSnapshotScaleNodeDefer(1, 200);
 393     }
 394 
 395     // Test node snapshot with a 90 degree rotate transform
 396 
 397     @Test
 398     public void testSnapshotRotateNodeImm() {
 399         setupSimpleScene();
 400         final SnapshotParameters snapshotParams = new SnapshotParameters();
 401         // Rotate by 90 degrees, which will swap width and height
 402         snapshotParams.setTransform(Transform.rotate(90, 0, 0));
 403         final int WIDTH = NODE_H;
 404         final int HEIGHT = NODE_W;
 405         final WritableImage img = useImage ? new WritableImage(WIDTH, HEIGHT) : null;
 406         Util.runAndWait(() -> {
 407             WritableImage wimg = tmpScene.getRoot().snapshot(snapshotParams, img);
 408             assertNotNull(wimg);
 409             if (img != null) {
 410                 assertSame(img, wimg);
 411             }
 412 
 413             assertEquals(WIDTH, (int)wimg.getWidth());
 414             assertEquals(HEIGHT, (int)wimg.getHeight());
 415         });
 416     }
 417 
 418     @Test
 419     public void testSnapshotRotateNodeDefer() {
 420         setupSimpleScene();
 421         final SnapshotParameters snapshotParams = new SnapshotParameters();
 422         // Rotate by 90 degrees, which will swap width and height
 423         snapshotParams.setTransform(Transform.rotate(90, 0, 0));
 424         final int WIDTH = NODE_H;
 425         final int HEIGHT = NODE_W;
 426         final WritableImage img = useImage ? new WritableImage(WIDTH, HEIGHT) : null;
 427         runDeferredSnapshotWait(tmpScene.getRoot(), result -> {
 428             assertSame(tmpScene.getRoot(), result.getSource());
 429             assertNotNull(result.getSnapshotParameters());
 430             assertNotNull(result.getImage());
 431             if (img != null) {
 432                 assertSame(img, result.getImage());
 433             }
 434 
 435             assertEquals(WIDTH, (int)result.getImage().getWidth());
 436             assertEquals(HEIGHT, (int)result.getImage().getHeight());
 437 
 438             return null;
 439         }, snapshotParams, img);
 440     }
 441 
 442     // Test viewport
 443     private static final int VP_X = 105;
 444     private static final int VP_Y = 20;
 445     private static final int VP_WIDTH = 160;
 446     private static final int VP_HEIGHT = 100;
 447 
 448     @Test
 449     public void testSnapshotViewportNodeImm() {
 450         setupSimpleScene();
 451         final SnapshotParameters snapshotParams = new SnapshotParameters();
 452         snapshotParams.setViewport(new Rectangle2D(VP_X, VP_Y, VP_WIDTH, VP_HEIGHT));
 453         final WritableImage img = useImage ? new WritableImage(NODE_W, NODE_H) : null;
 454         final int WIDTH = useImage ? NODE_W : VP_WIDTH;
 455         final int HEIGHT = useImage ? NODE_H : VP_HEIGHT;
 456         Util.runAndWait(() -> {
 457             WritableImage wimg = tmpScene.getRoot().snapshot(snapshotParams, img);
 458             assertNotNull(wimg);
 459             if (img != null) {
 460                 assertSame(img, wimg);
 461             }
 462 
 463             assertEquals(WIDTH, (int)wimg.getWidth());
 464             assertEquals(HEIGHT, (int)wimg.getHeight());
 465         });
 466     }
 467 
 468     @Test
 469     public void testSnapshotViewportNodeDefer() {
 470         setupSimpleScene();
 471         final SnapshotParameters snapshotParams = new SnapshotParameters();
 472         snapshotParams.setViewport(new Rectangle2D(VP_X, VP_Y, VP_WIDTH, VP_HEIGHT));
 473         final WritableImage img = useImage ? new WritableImage(NODE_W, NODE_H) : null;
 474         final int WIDTH = useImage ? NODE_W : VP_WIDTH;
 475         final int HEIGHT = useImage ? NODE_H : VP_HEIGHT;
 476         runDeferredSnapshotWait(tmpScene.getRoot(), result -> {
 477             assertSame(tmpScene.getRoot(), result.getSource());
 478             assertNotNull(result.getSnapshotParameters());
 479             assertNotNull(result.getImage());
 480             if (img != null) {
 481                 assertSame(img, result.getImage());
 482             }
 483 
 484             assertEquals(WIDTH, (int)result.getImage().getWidth());
 485             assertEquals(HEIGHT, (int)result.getImage().getHeight());
 486 
 487             return null;
 488         }, snapshotParams, img);
 489     }
 490 
 491     // Test updating the node after the call to a deferred snapshot, in
 492     // the same runLater call. Verify that the change to the node is
 493     // reflected in the result
 494 
 495     private static final int NEW_WIDTH = 70;
 496     private static final int NEW_HEIGHT = 35;
 497 
 498     @Test
 499     public void testSnapshotUpdateNodeDefer() {
 500         setupSimpleScene();
 501         final SnapshotParameters snapshotParams = new SnapshotParameters();
 502         final WritableImage img = useImage ? new WritableImage(NODE_W, NODE_H) : null;
 503         final int WIDTH = useImage ? NODE_W : NEW_WIDTH;
 504         final int HEIGHT = useImage ? NODE_H : NEW_HEIGHT;
 505         Callback<SnapshotResult, Void> cb = result -> {
 506             assertSame(tmpScene.getRoot(), result.getSource());
 507             assertNotNull(result.getSnapshotParameters());
 508             assertNotNull(result.getImage());
 509             if (img != null) {
 510                 assertSame(img, result.getImage());
 511             }
 512 
 513             assertEquals(WIDTH, (int)result.getImage().getWidth());
 514             assertEquals(HEIGHT, (int)result.getImage().getHeight());
 515 
 516             return null;
 517         };
 518         Runnable runAfter = () -> {
 519             assertTrue(tmpNode instanceof Rectangle);
 520             Rectangle rect = (Rectangle)tmpNode;
 521             rect.setWidth(NEW_WIDTH);
 522             rect.setHeight(NEW_HEIGHT);
 523         };
 524 
 525         runDeferredSnapshotWait(tmpScene.getRoot(), cb, snapshotParams, img, runAfter);
 526     }
 527 
 528 }