1 /* 2 * Copyright (c) 2010, 2016, 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.image; 27 28 import test.com.sun.javafx.pgstub.StubPlatformImageInfo; 29 import test.com.sun.javafx.pgstub.StubPlatformImage; 30 import test.com.sun.javafx.pgstub.StubImageLoader; 31 import test.com.sun.javafx.pgstub.StubAsyncImageLoader; 32 import test.com.sun.javafx.pgstub.StubImageLoaderFactory; 33 import test.com.sun.javafx.pgstub.StubToolkit; 34 import test.com.sun.javafx.test.PropertyInvalidationCounter; 35 import com.sun.javafx.tk.Toolkit; 36 import javafx.beans.InvalidationListener; 37 import org.junit.Before; 38 import org.junit.Test; 39 40 import java.io.ByteArrayInputStream; 41 import java.io.InputStream; 42 import java.util.LinkedList; 43 import java.util.Queue; 44 import javafx.scene.image.Image; 45 import javafx.scene.image.ImageShim; 46 47 import static org.junit.Assert.*; 48 49 public final class ImageTest { 50 private final StubToolkit toolkit; 51 private final StubImageLoaderFactory imageLoaderFactory; 52 53 public ImageTest() { 54 toolkit = (StubToolkit) Toolkit.getToolkit(); 55 imageLoaderFactory = toolkit.getImageLoaderFactory(); 56 } 57 58 @Before 59 public void setUp() { 60 imageLoaderFactory.reset(); 61 } 62 63 @Test 64 public void loadImageFromUrlBasicTest() { 65 final String url = "file:test.png"; 66 registerImage(url, 100, 200); 67 68 final Image image = new Image(url); 69 70 assertEquals(url, image.getUrl()); 71 verifyLoadedImage(image, 0, 0, false, false, 100, 200); 72 } 73 74 @Test 75 public void loadImageFromUrlScaledTest() { 76 final String url = "file:test.png"; 77 registerImage(url, 300, 100); 78 79 final Image image = new Image(url, 200, 400, true, true); 80 81 assertEquals(url, image.getUrl()); 82 verifyLoadedImage(image, 200, 400, true, true, 300, 100); 83 } 84 85 @Test 86 public void loadImageFromMissingUrlTest() { 87 final Image image = new Image("file:missing.png"); 88 89 assertTrue(image.isError()); 90 } 91 92 @Test 93 public void loadImageFromStreamBasicTest() { 94 final InputStream is = new ByteArrayInputStream(new byte[0]); 95 registerImage(is, 100, 200); 96 97 final Image image = new Image(is); 98 99 assertEquals(is, ImageShim.getInputSource(image)); 100 verifyLoadedImage(image, 0, 0, false, false, 100, 200); 101 } 102 103 @Test 104 public void loadImageFromStreamScaledTest() { 105 final InputStream is = new ByteArrayInputStream(new byte[0]); 106 registerImage(is, 300, 100); 107 108 final Image image = new Image(is, 200, 400, true, true); 109 110 assertEquals(is, ImageShim.getInputSource(image)); 111 verifyLoadedImage(image, 200, 400, true, true, 300, 100); 112 } 113 114 @Test 115 public void fromPlatformImageTest() { 116 final Object fakePlatformImage = new Object(); 117 registerImage(fakePlatformImage, 200, 500); 118 119 final Image image = Toolkit.getImageAccessor().fromPlatformImage(fakePlatformImage); 120 verifyLoadedImage(image, 0, 0, false, false, 200, 500); 121 } 122 123 @Test 124 public void loadImageAsyncProgressTest() { 125 final String url = "file:test.png"; 126 registerImage(url, 200, 100); 127 128 final Image image = new Image(url, true); 129 130 final StubAsyncImageLoader lastAsyncImageLoader = 131 getLastAsyncImageLoader(); 132 133 lastAsyncImageLoader.setProgress(0, 100); 134 final float p1 = (float) image.getProgress(); 135 136 lastAsyncImageLoader.setProgress(33, 100); 137 final float p2 = (float) image.getProgress(); 138 139 lastAsyncImageLoader.setProgress(66, 100); 140 final float p3 = (float) image.getProgress(); 141 142 lastAsyncImageLoader.setProgress(200, 100); 143 final float p4 = (float) image.getProgress(); 144 145 lastAsyncImageLoader.finish(); 146 147 assertTrue(p1 < p2); 148 assertTrue(p2 < p3); 149 assertTrue(p3 == p4); 150 } 151 152 /* 153 @Test 154 public void loadImageAsyncPlaceholderTest() { 155 final Object fakePlatformImage1 = new Object(); 156 registerImage(fakePlatformImage1, 200, 500); 157 final Object fakePlatformImage2 = new Object(); 158 registerImage(fakePlatformImage2, 200, 500); 159 160 final String url = "file:test.png"; 161 registerImage(url, 200, 100); 162 163 final Image placeholderImage1 = 164 Toolkit.getImageAccessor().fromPlatformImage(fakePlatformImage1); 165 final Image placeholderImage2 = 166 Toolkit.getImageAccessor().fromPlatformImage(fakePlatformImage2); 167 final Image image = new Image(url, 500, 200, true, false, 168 true); 169 170 final StubAsyncImageLoader lastAsyncImageLoader = 171 getLastAsyncImageLoader(); 172 173 final Object platformImage1 = getPlatformImage(image); 174 final Object platformImage2 = getPlatformImage(image); 175 lastAsyncImageLoader.finish(); 176 final Object platformImage3 = getPlatformImage(image); 177 final Object platformImage4 = getPlatformImage(image); 178 179 lastAsyncImageLoader.finish(); 180 181 assertNotSame(platformImage1, platformImage2); 182 assertNotSame(platformImage2, platformImage3); 183 assertNotSame(platformImage1, platformImage3); 184 assertSame(platformImage3, platformImage4); 185 186 verifyLoadedImage(image, 500, 200, true, false, 200, 100); 187 } 188 189 @Test 190 public void loadImageAsyncWithAsyncPlaceholderTest() { 191 final String placeholderUrl = "file:placeholder.png"; 192 registerImage(placeholderUrl, 200, 100); 193 final String finalUrl = "file:final.png"; 194 registerImage(finalUrl, 100, 200); 195 196 final Image placeholderImage = 197 new Image(placeholderUrl, true); 198 final StubAsyncImageLoader placeholderLoader = 199 getLastAsyncImageLoader(); 200 201 final Image finalImage = 202 new Image(finalUrl, true); 203 final StubAsyncImageLoader finalLoader = 204 getLastAsyncImageLoader(); 205 206 assertNull(Toolkit.getImageAccessor().getPlatformImage(finalImage)); 207 assertEquals(0, finalImage.getWidth(), 0); 208 assertEquals(0, finalImage.getHeight(), 0); 209 210 placeholderLoader.finish(); 211 assertEquals(placeholderUrl, getPlatformImage(finalImage).getSource()); 212 assertEquals(200, finalImage.getWidth(), 0); 213 assertEquals(100, finalImage.getHeight(), 0); 214 215 finalLoader.finish(); 216 assertEquals(finalUrl, getPlatformImage(finalImage).getSource()); 217 assertEquals(100, finalImage.getWidth(), 0); 218 assertEquals(200, finalImage.getHeight(), 0); 219 } 220 */ 221 222 @Test 223 public void loadImageAsyncCancelTest() { 224 final String url = "file:test.png"; 225 registerImage(url, 200, 100); 226 227 final Image image1 = new Image(url, true); 228 final StubAsyncImageLoader lastAsyncImageLoader = 229 getLastAsyncImageLoader(); 230 231 image1.cancel(); 232 assertTrue(lastAsyncImageLoader.isCancelled()); 233 assertTrue(image1.isError()); 234 235 final Image image2 = new Image(url); 236 image2.cancel(); 237 verifyLoadedImage(image2, 0, 0, false, false, 200, 100); 238 } 239 240 @Test 241 public void loadImageAsyncErrorTest() { 242 final String url = "file:test.png"; 243 registerImage(url, 200, 100); 244 245 final Image image = new Image(url, true); 246 247 final StubAsyncImageLoader lastAsyncImageLoader = 248 getLastAsyncImageLoader(); 249 250 final Exception testException = new Exception("Test exception"); 251 252 lastAsyncImageLoader.finish(testException); 253 assertTrue(image.isError()); 254 assertEquals(testException, image.getException()); 255 } 256 257 @Test 258 public void loadMultipleImagesAsyncTest() { 259 final int multiImageCount = 100; 260 final Queue<StubAsyncImageLoader> asyncLoaders = 261 new LinkedList<StubAsyncImageLoader>(); 262 final Image[] images = new Image[multiImageCount]; 263 264 StubAsyncImageLoader lastAsyncLoader = null; 265 for (int i = 0; i < multiImageCount; ++i) { 266 final String url = "file:multi" + i + ".png"; 267 registerImage(url, 100, 100); 268 269 images[i] = new Image(url, true); 270 271 StubAsyncImageLoader asyncLoader = 272 imageLoaderFactory.getLastAsyncImageLoader(); 273 assertNotNull(asyncLoader); 274 if (lastAsyncLoader == asyncLoader) { 275 asyncLoaders.poll().finish(); 276 asyncLoader = imageLoaderFactory.getLastAsyncImageLoader(); 277 assertNotSame(lastAsyncLoader, asyncLoader); 278 } 279 280 asyncLoaders.add(asyncLoader); 281 lastAsyncLoader = asyncLoader; 282 } 283 284 for (final StubAsyncImageLoader asyncLoader: asyncLoaders) { 285 asyncLoader.finish(); 286 } 287 288 for (final Image image: images) { 289 verifyLoadedImage(image, 0, 0, false, false, 100, 100); 290 } 291 } 292 293 @Test 294 public void loadMultipleImagesAsyncCancelTest() { 295 final int multiImageCount = 100; 296 final Image[] images = new Image[multiImageCount]; 297 298 for (int i = 0; i < multiImageCount; ++i) { 299 final String url = "file:multi_cancel_" + i + ".png"; 300 registerImage(url, 100, 100); 301 302 images[i] = new Image(url, true); 303 } 304 305 // traverse backwards to first cancel images which were queued because 306 // of the thread limit 307 for (int i = images.length - 1; i >= 0; --i) { 308 final Image image = images[i]; 309 image.cancel(); 310 assertTrue(image.isError()); 311 } 312 } 313 314 @Test 315 public void animatedImageTest() { 316 // reset time 317 toolkit.setAnimationTime(0); 318 final Image animatedImage = 319 TestImages.createAnimatedTestImage( 320 300, 400, // width, height 321 0, // loop count 322 2000, 1000, 3000 // frame delays 323 ); 324 325 verifyLoadedImage(animatedImage, 0, 0, false, false, 300, 400); 326 327 toolkit.setAnimationTime(1000); 328 assertEquals(0, getPlatformImage(animatedImage).getFrame()); 329 330 toolkit.setAnimationTime(1999); 331 assertEquals(0, getPlatformImage(animatedImage).getFrame()); 332 toolkit.setAnimationTime(2000); 333 assertEquals(1, getPlatformImage(animatedImage).getFrame()); 334 335 toolkit.setAnimationTime(2500); 336 assertEquals(1, getPlatformImage(animatedImage).getFrame()); 337 338 toolkit.setAnimationTime(2999); 339 assertEquals(1, getPlatformImage(animatedImage).getFrame()); 340 toolkit.setAnimationTime(3000); 341 assertEquals(2, getPlatformImage(animatedImage).getFrame()); 342 343 toolkit.setAnimationTime(4500); 344 assertEquals(2, getPlatformImage(animatedImage).getFrame()); 345 346 toolkit.setAnimationTime(5999); 347 assertEquals(2, getPlatformImage(animatedImage).getFrame()); 348 toolkit.setAnimationTime(6000); 349 // end of the cycle does flip frames! 350 assertEquals(0, getPlatformImage(animatedImage).getFrame()); 351 352 toolkit.setAnimationTime(7000); 353 assertEquals(0, getPlatformImage(animatedImage).getFrame()); 354 355 TestImages.disposeAnimatedImage(animatedImage); 356 } 357 358 @Test 359 public void animatedImageTestLoopOnce() { 360 // reset time 361 toolkit.setAnimationTime(0); 362 final Image animatedImage = 363 TestImages.createAnimatedTestImage( 364 300, 400, // width, height 365 1, // loop count 366 2000, 1000, 3000 // frame delays 367 ); 368 369 verifyLoadedImage(animatedImage, 0, 0, false, false, 300, 400); 370 371 toolkit.setAnimationTime(1000); 372 assertEquals(0, getPlatformImage(animatedImage).getFrame()); 373 374 toolkit.setAnimationTime(2500); 375 assertEquals(1, getPlatformImage(animatedImage).getFrame()); 376 377 toolkit.setAnimationTime(4500); 378 assertEquals(2, getPlatformImage(animatedImage).getFrame()); 379 380 toolkit.setAnimationTime(7000); 381 assertEquals(2, getPlatformImage(animatedImage).getFrame()); 382 383 TestImages.disposeAnimatedImage(animatedImage); 384 } 385 386 @Test 387 public void imagePropertyListenersCalledOnceTest() { 388 final String url = "file:test.png"; 389 registerImage(url, 200, 100); 390 391 final Image image = new Image(url, true); 392 393 final StubAsyncImageLoader lastAsyncImageLoader = 394 getLastAsyncImageLoader(); 395 396 final PropertyInvalidationCounter<Number> widthInvalidationCounter = 397 new PropertyInvalidationCounter<Number>(); 398 final PropertyInvalidationCounter<Number> heightInvalidationCounter = 399 new PropertyInvalidationCounter<Number>(); 400 final PropertyInvalidationCounter<Object> plImageInvalidationCounter = 401 new PropertyInvalidationCounter<Object>(); 402 403 image.widthProperty().addListener(widthInvalidationCounter); 404 image.heightProperty().addListener(heightInvalidationCounter); 405 Toolkit.getImageAccessor().getImageProperty(image).addListener(plImageInvalidationCounter); 406 407 assertEquals(0, image.getWidth(), 0); 408 assertEquals(0, image.getHeight(), 0); 409 assertEquals(null, Toolkit.getImageAccessor().getPlatformImage(image)); 410 411 lastAsyncImageLoader.finish(); 412 413 assertEquals(1, widthInvalidationCounter.getCounter()); 414 assertEquals(1, heightInvalidationCounter.getCounter()); 415 assertEquals(1, plImageInvalidationCounter.getCounter()); 416 } 417 418 @Test 419 public void imagePropertiesChangedAtomicallyTest() { 420 final String url = "file:test.png"; 421 registerImage(url, 200, 100); 422 423 final Image image = new Image(url, true); 424 final StubAsyncImageLoader lastAsyncImageLoader = 425 getLastAsyncImageLoader(); 426 427 final InvalidationListener imageChecker = 428 observable -> { 429 assertEquals(200, image.getWidth(), 0); 430 assertEquals(100, image.getHeight(), 0); 431 assertNotNull(Toolkit.getImageAccessor().getPlatformImage(image)); 432 }; 433 434 image.widthProperty().addListener(imageChecker); 435 image.heightProperty().addListener(imageChecker); 436 Toolkit.getImageAccessor().getImageProperty(image).addListener(imageChecker); 437 438 assertEquals(0, image.getWidth(), 0); 439 assertEquals(0, image.getHeight(), 0); 440 assertEquals(null, Toolkit.getImageAccessor().getPlatformImage(image)); 441 442 lastAsyncImageLoader.finish(); 443 } 444 445 private static void verifyLoadedImage(final Image image, 446 final int loadWidth, 447 final int loadHeight, 448 final boolean preserveRatio, 449 final boolean smooth, 450 final int imageWidth, 451 final int imageHeight) { 452 assertFalse(image.isError()); 453 assertEquals(1, (int) image.getProgress()); 454 455 final StubPlatformImage platformImage = 456 getPlatformImage(image); 457 assertEquals(0, platformImage.getFrame()); 458 459 final StubImageLoader imageLoader = 460 platformImage.getImageLoader(); 461 assertEquals(loadWidth, imageLoader.getLoadWidth()); 462 assertEquals(loadHeight, imageLoader.getLoadHeight()); 463 assertEquals(preserveRatio, imageLoader.getPreserveRatio()); 464 assertEquals(smooth, imageLoader.getSmooth()); 465 466 assertEquals(imageWidth, (int) image.getWidth()); 467 assertEquals(imageHeight, (int) image.getHeight()); 468 } 469 470 private static StubPlatformImage getPlatformImage(final Image srcImage) { 471 final Object unknownPlatformImage = Toolkit.getImageAccessor().getPlatformImage(srcImage); 472 assertTrue(unknownPlatformImage instanceof StubPlatformImage); 473 return (StubPlatformImage) unknownPlatformImage; 474 } 475 476 private void registerImage(final Object source, 477 final int width, 478 final int height) { 479 imageLoaderFactory.registerImage( 480 source, new StubPlatformImageInfo(width, height)); 481 } 482 483 private StubAsyncImageLoader getLastAsyncImageLoader() { 484 final StubAsyncImageLoader lastAsyncImageLoader = 485 imageLoaderFactory.getLastAsyncImageLoader(); 486 assertNotNull(lastAsyncImageLoader); 487 assertTrue(lastAsyncImageLoader.isStarted()); 488 489 return lastAsyncImageLoader; 490 } 491 492 @Test 493 public void createImageFromClasspathTest() { 494 final String url = "test/javafx/scene/image/test.png"; 495 final String resolvedUrl = Thread.currentThread().getContextClassLoader().getResource(url).toString(); 496 registerImage(resolvedUrl, 100, 200); 497 498 final Image image = new Image(url); 499 500 assertEquals(resolvedUrl, image.getUrl()); 501 verifyLoadedImage(image, 0, 0, false, false, 100, 200); 502 } 503 504 @Test 505 public void createImageFromClasspathTest_withLeadingSlash() { 506 final String url = "/test/javafx/scene/image/test.png"; 507 final String resolvedUrl = Thread.currentThread().getContextClassLoader().getResource(url.substring(1)).toString(); 508 registerImage(resolvedUrl, 100, 200); 509 510 final Image image = new Image(url); 511 512 assertEquals(resolvedUrl, image.getUrl()); 513 verifyLoadedImage(image, 0, 0, false, false, 100, 200); 514 } 515 516 @Test(expected=NullPointerException.class) 517 public void createImageFromNullUrlTest() { 518 new Image((String) null); 519 } 520 521 @Test(expected=NullPointerException.class) 522 public void createImageAsyncFromNullUrlTest() { 523 new Image(null, true); 524 } 525 526 @Test(expected=NullPointerException.class) 527 public void createImageFromNullInputStreamTest() { 528 new Image((InputStream) null); 529 } 530 531 @Test(expected=IllegalArgumentException.class) 532 public void createImageFromEmptyUrlTest() { 533 new Image(""); 534 } 535 536 @Test(expected=IllegalArgumentException.class) 537 public void createImageAsyncFromEmptyUrlTest() { 538 new Image("", true); 539 } 540 541 @Test(expected=IllegalArgumentException.class) 542 public void createImageFromInvalidUrlTest() { 543 new Image(":"); 544 } 545 546 @Test(expected=IllegalArgumentException.class) 547 public void createImageAsyncFromInvalidUrlTest() { 548 new Image(":", true); 549 } 550 551 @Test(expected=IllegalArgumentException.class) 552 public void createImageFromUnsupportedUrlTest() { 553 new Image("unsupported:image.png"); 554 } 555 556 @Test(expected=IllegalArgumentException.class) 557 public void createImageAsyncFromUnsupportedUrlTest() { 558 new Image("unsupported:image.png", true); 559 } 560 }