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