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