|
1 /* |
|
2 * Copyright (c) 2013, 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. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 */ |
|
23 |
|
24 import java.awt.Color; |
|
25 import java.awt.Graphics; |
|
26 import java.awt.Graphics2D; |
|
27 import java.awt.Image; |
|
28 import java.awt.Toolkit; |
|
29 import java.awt.image.BufferedImage; |
|
30 import java.io.File; |
|
31 import java.lang.reflect.Method; |
|
32 import java.net.URL; |
|
33 import javax.imageio.ImageIO; |
|
34 import sun.awt.OSInfo; |
|
35 import sun.awt.SunHints; |
|
36 import java.awt.MediaTracker; |
|
37 import java.awt.geom.AffineTransform; |
|
38 import java.awt.image.ImageObserver; |
|
39 import java.util.Arrays; |
|
40 import java.util.List; |
|
41 import javax.swing.JPanel; |
|
42 import sun.awt.SunToolkit; |
|
43 import sun.awt.image.MultiResolutionImage; |
|
44 |
|
45 /** |
|
46 * @test |
|
47 * @bug 8011059 |
|
48 * @author Alexander Scherbatiy |
|
49 * @summary [macosx] Make JDK demos look perfect on retina displays |
|
50 * @run main MultiResolutionImageTest CUSTOM |
|
51 * @run main MultiResolutionImageTest TOOLKIT_PREPARE |
|
52 * @run main MultiResolutionImageTest TOOLKIT_LOAD |
|
53 * @run main MultiResolutionImageTest TOOLKIT |
|
54 */ |
|
55 public class MultiResolutionImageTest { |
|
56 |
|
57 private static final int IMAGE_WIDTH = 300; |
|
58 private static final int IMAGE_HEIGHT = 200; |
|
59 private static final Color COLOR_1X = Color.GREEN; |
|
60 private static final Color COLOR_2X = Color.BLUE; |
|
61 private static final String IMAGE_NAME_1X = "image.png"; |
|
62 private static final String IMAGE_NAME_2X = "image@2x.png"; |
|
63 |
|
64 public static void main(String[] args) throws Exception { |
|
65 |
|
66 System.out.println("args: " + args.length); |
|
67 |
|
68 if (args.length == 0) { |
|
69 throw new RuntimeException("Not found a test"); |
|
70 } |
|
71 |
|
72 String test = args[0]; |
|
73 |
|
74 System.out.println("TEST: " + test); |
|
75 System.out.println("CHECK OS: " + checkOS()); |
|
76 |
|
77 if ("CUSTOM".equals(test)) { |
|
78 testCustomMultiResolutionImage(); |
|
79 } else if (checkOS()) { |
|
80 switch (test) { |
|
81 case "CUSTOM": |
|
82 break; |
|
83 case "TOOLKIT_PREPARE": |
|
84 testToolkitMultiResolutionImagePrepare(); |
|
85 break; |
|
86 case "TOOLKIT_LOAD": |
|
87 testToolkitMultiResolutionImageLoad(); |
|
88 break; |
|
89 case "TOOLKIT": |
|
90 testToolkitMultiResolutionImage(); |
|
91 testImageNameTo2xParsing(); |
|
92 break; |
|
93 default: |
|
94 throw new RuntimeException("Unknown test: " + test); |
|
95 } |
|
96 } |
|
97 } |
|
98 |
|
99 static boolean checkOS() { |
|
100 return OSInfo.getOSType() == OSInfo.OSType.MACOSX; |
|
101 } |
|
102 |
|
103 public static void testCustomMultiResolutionImage() { |
|
104 testCustomMultiResolutionImage(false); |
|
105 testCustomMultiResolutionImage(true); |
|
106 } |
|
107 |
|
108 public static void testCustomMultiResolutionImage(boolean enableImageScaling) { |
|
109 |
|
110 Image image = new MultiResolutionBufferedImage(); |
|
111 |
|
112 // Same image size |
|
113 BufferedImage bufferedImage = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, |
|
114 BufferedImage.TYPE_INT_RGB); |
|
115 Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics(); |
|
116 setImageScalingHint(g2d, enableImageScaling); |
|
117 g2d.drawImage(image, 0, 0, null); |
|
118 checkColor(bufferedImage.getRGB(3 * IMAGE_WIDTH / 4, 3 * IMAGE_HEIGHT / 4), false); |
|
119 |
|
120 // Twice image size |
|
121 bufferedImage = new BufferedImage(2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT, |
|
122 BufferedImage.TYPE_INT_RGB); |
|
123 g2d = (Graphics2D) bufferedImage.getGraphics(); |
|
124 setImageScalingHint(g2d, enableImageScaling); |
|
125 g2d.drawImage(image, 0, 0, 2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null); |
|
126 checkColor(bufferedImage.getRGB(3 * IMAGE_WIDTH / 2, 3 * IMAGE_HEIGHT / 2), enableImageScaling); |
|
127 |
|
128 // Scale 2x |
|
129 bufferedImage = new BufferedImage(2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); |
|
130 g2d = (Graphics2D) bufferedImage.getGraphics(); |
|
131 setImageScalingHint(g2d, enableImageScaling); |
|
132 g2d.scale(2, 2); |
|
133 g2d.drawImage(image, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null); |
|
134 checkColor(bufferedImage.getRGB(3 * IMAGE_WIDTH / 2, 3 * IMAGE_HEIGHT / 2), enableImageScaling); |
|
135 |
|
136 // Rotate |
|
137 bufferedImage = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, |
|
138 BufferedImage.TYPE_INT_RGB); |
|
139 g2d = (Graphics2D) bufferedImage.getGraphics(); |
|
140 setImageScalingHint(g2d, enableImageScaling); |
|
141 g2d.drawImage(image, 0, 0, null); |
|
142 g2d.rotate(Math.PI / 4); |
|
143 checkColor(bufferedImage.getRGB(3 * IMAGE_WIDTH / 4, 3 * IMAGE_HEIGHT / 4), false); |
|
144 |
|
145 // Scale 2x and Rotate |
|
146 bufferedImage = new BufferedImage(2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); |
|
147 g2d = (Graphics2D) bufferedImage.getGraphics(); |
|
148 setImageScalingHint(g2d, enableImageScaling); |
|
149 g2d.scale(-2, 2); |
|
150 g2d.rotate(-Math.PI / 10); |
|
151 g2d.drawImage(image, -IMAGE_WIDTH, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null); |
|
152 checkColor(bufferedImage.getRGB(3 * IMAGE_WIDTH / 2, 3 * IMAGE_HEIGHT / 2), enableImageScaling); |
|
153 |
|
154 // General Transform |
|
155 bufferedImage = new BufferedImage(2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); |
|
156 g2d = (Graphics2D) bufferedImage.getGraphics(); |
|
157 setImageScalingHint(g2d, enableImageScaling); |
|
158 float delta = 0.05f; |
|
159 float cos = 1 - delta * delta / 2; |
|
160 float sin = 1 + delta; |
|
161 AffineTransform transform = new AffineTransform(2 * cos, 0.1, 0.3, -2 * sin, 10, -5); |
|
162 g2d.setTransform(transform); |
|
163 g2d.drawImage(image, 0, -IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_HEIGHT, null); |
|
164 checkColor(bufferedImage.getRGB(3 * IMAGE_WIDTH / 2, 3 * IMAGE_HEIGHT / 2), enableImageScaling); |
|
165 |
|
166 int D = 10; |
|
167 // From Source to small Destination region |
|
168 bufferedImage = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); |
|
169 g2d = (Graphics2D) bufferedImage.getGraphics(); |
|
170 setImageScalingHint(g2d, enableImageScaling); |
|
171 g2d.drawImage(image, IMAGE_WIDTH / 2, IMAGE_HEIGHT / 2, IMAGE_WIDTH - D, IMAGE_HEIGHT - D, |
|
172 D, D, IMAGE_WIDTH - D, IMAGE_HEIGHT - D, null); |
|
173 checkColor(bufferedImage.getRGB(3 * IMAGE_WIDTH / 4, 3 * IMAGE_HEIGHT / 4), false); |
|
174 |
|
175 // From Source to large Destination region |
|
176 bufferedImage = new BufferedImage(2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); |
|
177 g2d = (Graphics2D) bufferedImage.getGraphics(); |
|
178 setImageScalingHint(g2d, enableImageScaling); |
|
179 g2d.drawImage(image, D, D, 2 * IMAGE_WIDTH - D, 2 * IMAGE_HEIGHT - D, |
|
180 IMAGE_WIDTH / 2, IMAGE_HEIGHT / 2, IMAGE_WIDTH - D, IMAGE_HEIGHT - D, null); |
|
181 checkColor(bufferedImage.getRGB(3 * IMAGE_WIDTH / 2, 3 * IMAGE_HEIGHT / 2), enableImageScaling); |
|
182 } |
|
183 |
|
184 static class MultiResolutionBufferedImage extends BufferedImage |
|
185 implements MultiResolutionImage { |
|
186 |
|
187 Image highResolutionImage; |
|
188 |
|
189 public MultiResolutionBufferedImage() { |
|
190 super(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); |
|
191 highResolutionImage = new BufferedImage( |
|
192 2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); |
|
193 draw(getGraphics(), 1); |
|
194 draw(highResolutionImage.getGraphics(), 2); |
|
195 } |
|
196 |
|
197 void draw(Graphics graphics, float resolution) { |
|
198 Graphics2D g2 = (Graphics2D) graphics; |
|
199 g2.scale(resolution, resolution); |
|
200 g2.setColor((resolution == 1) ? COLOR_1X : COLOR_2X); |
|
201 g2.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); |
|
202 } |
|
203 |
|
204 @Override |
|
205 public Image getResolutionVariant(int width, int height) { |
|
206 return ((width <= getWidth() && height <= getHeight())) |
|
207 ? this : highResolutionImage; |
|
208 } |
|
209 |
|
210 @Override |
|
211 public List<Image> getResolutionVariants() { |
|
212 return Arrays.asList(this, highResolutionImage); |
|
213 } |
|
214 } |
|
215 |
|
216 static void testToolkitMultiResolutionImagePrepare() throws Exception { |
|
217 |
|
218 generateImages(); |
|
219 |
|
220 File imageFile = new File(IMAGE_NAME_1X); |
|
221 String fileName = imageFile.getAbsolutePath(); |
|
222 |
|
223 Image image = Toolkit.getDefaultToolkit().getImage(fileName); |
|
224 |
|
225 SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); |
|
226 toolkit.prepareImage(image, IMAGE_WIDTH, IMAGE_HEIGHT, new LoadImageObserver(image)); |
|
227 |
|
228 testToolkitMultiResolutionImageLoad(image); |
|
229 } |
|
230 |
|
231 static void testToolkitMultiResolutionImageLoad() throws Exception { |
|
232 |
|
233 generateImages(); |
|
234 |
|
235 File imageFile = new File(IMAGE_NAME_1X); |
|
236 String fileName = imageFile.getAbsolutePath(); |
|
237 Image image = Toolkit.getDefaultToolkit().getImage(fileName); |
|
238 testToolkitMultiResolutionImageLoad(image); |
|
239 } |
|
240 |
|
241 static void testToolkitMultiResolutionImageLoad(Image image) throws Exception { |
|
242 |
|
243 MediaTracker tracker = new MediaTracker(new JPanel()); |
|
244 tracker.addImage(image, 0); |
|
245 tracker.waitForID(0); |
|
246 if (tracker.isErrorAny()) { |
|
247 throw new RuntimeException("Error during image loading"); |
|
248 } |
|
249 tracker.removeImage(image, 0); |
|
250 |
|
251 testImageLoaded(image); |
|
252 |
|
253 int w = image.getWidth(null); |
|
254 int h = image.getHeight(null); |
|
255 |
|
256 Image resolutionVariant = ((MultiResolutionImage) image) |
|
257 .getResolutionVariant(2 * w, 2 * h); |
|
258 |
|
259 if (image == resolutionVariant) { |
|
260 throw new RuntimeException("Resolution variant is not loaded"); |
|
261 } |
|
262 |
|
263 testImageLoaded(resolutionVariant); |
|
264 } |
|
265 |
|
266 static void testImageLoaded(Image image) { |
|
267 |
|
268 SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); |
|
269 |
|
270 int flags = toolkit.checkImage(image, IMAGE_WIDTH, IMAGE_WIDTH, new SilentImageObserver()); |
|
271 if ((flags & (ImageObserver.FRAMEBITS | ImageObserver.ALLBITS)) == 0) { |
|
272 throw new RuntimeException("Image is not loaded!"); |
|
273 } |
|
274 } |
|
275 |
|
276 static class SilentImageObserver implements ImageObserver { |
|
277 |
|
278 @Override |
|
279 public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { |
|
280 throw new RuntimeException("Observer should not be called!"); |
|
281 } |
|
282 } |
|
283 |
|
284 static class LoadImageObserver implements ImageObserver { |
|
285 |
|
286 Image image; |
|
287 |
|
288 public LoadImageObserver(Image image) { |
|
289 this.image = image; |
|
290 } |
|
291 |
|
292 @Override |
|
293 public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { |
|
294 |
|
295 if (image != img) { |
|
296 throw new RuntimeException("Original image is not passed to the observer"); |
|
297 } |
|
298 |
|
299 if ((infoflags & ImageObserver.WIDTH) != 0) { |
|
300 if (width != IMAGE_WIDTH) { |
|
301 throw new RuntimeException("Original width is not passed to the observer"); |
|
302 } |
|
303 } |
|
304 |
|
305 if ((infoflags & ImageObserver.HEIGHT) != 0) { |
|
306 if (height != IMAGE_HEIGHT) { |
|
307 throw new RuntimeException("Original height is not passed to the observer"); |
|
308 } |
|
309 } |
|
310 |
|
311 return (infoflags & ALLBITS) == 0; |
|
312 } |
|
313 |
|
314 } |
|
315 |
|
316 static void testToolkitMultiResolutionImage() throws Exception { |
|
317 |
|
318 generateImages(); |
|
319 |
|
320 File imageFile = new File(IMAGE_NAME_1X); |
|
321 String fileName = imageFile.getAbsolutePath(); |
|
322 URL url = imageFile.toURI().toURL(); |
|
323 testToolkitMultiResolutionImageChache(fileName, url); |
|
324 |
|
325 Image image = Toolkit.getDefaultToolkit().getImage(fileName); |
|
326 testToolkitImageObserver(image); |
|
327 testToolkitMultiResolutionImage(image, false); |
|
328 testToolkitMultiResolutionImage(image, true); |
|
329 |
|
330 image = Toolkit.getDefaultToolkit().getImage(url); |
|
331 testToolkitImageObserver(image); |
|
332 testToolkitMultiResolutionImage(image, false); |
|
333 testToolkitMultiResolutionImage(image, true); |
|
334 } |
|
335 |
|
336 static void testToolkitMultiResolutionImageChache(String fileName, URL url) { |
|
337 |
|
338 Image img1 = Toolkit.getDefaultToolkit().getImage(fileName); |
|
339 if (!(img1 instanceof MultiResolutionImage)) { |
|
340 throw new RuntimeException("Not a MultiResolutionImage"); |
|
341 } |
|
342 |
|
343 Image img2 = Toolkit.getDefaultToolkit().getImage(fileName); |
|
344 if (img1 != img2) { |
|
345 throw new RuntimeException("Image is not cached"); |
|
346 } |
|
347 |
|
348 img1 = Toolkit.getDefaultToolkit().getImage(url); |
|
349 if (!(img1 instanceof MultiResolutionImage)) { |
|
350 throw new RuntimeException("Not a MultiResolutionImage"); |
|
351 } |
|
352 |
|
353 img2 = Toolkit.getDefaultToolkit().getImage(url); |
|
354 if (img1 != img2) { |
|
355 throw new RuntimeException("Image is not cached"); |
|
356 } |
|
357 } |
|
358 |
|
359 static void testToolkitMultiResolutionImage(Image image, boolean enableImageScaling) |
|
360 throws Exception { |
|
361 |
|
362 MediaTracker tracker = new MediaTracker(new JPanel()); |
|
363 tracker.addImage(image, 0); |
|
364 tracker.waitForID(0); |
|
365 if (tracker.isErrorAny()) { |
|
366 throw new RuntimeException("Error during image loading"); |
|
367 } |
|
368 |
|
369 final BufferedImage bufferedImage1x = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, |
|
370 BufferedImage.TYPE_INT_RGB); |
|
371 Graphics2D g1x = (Graphics2D) bufferedImage1x.getGraphics(); |
|
372 setImageScalingHint(g1x, false); |
|
373 g1x.drawImage(image, 0, 0, null); |
|
374 checkColor(bufferedImage1x.getRGB(3 * IMAGE_WIDTH / 4, 3 * IMAGE_HEIGHT / 4), false); |
|
375 |
|
376 Image resolutionVariant = ((MultiResolutionImage) image). |
|
377 getResolutionVariant(2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT); |
|
378 |
|
379 if (resolutionVariant == null) { |
|
380 throw new RuntimeException("Resolution variant is null"); |
|
381 } |
|
382 |
|
383 MediaTracker tracker2x = new MediaTracker(new JPanel()); |
|
384 tracker2x.addImage(resolutionVariant, 0); |
|
385 tracker2x.waitForID(0); |
|
386 if (tracker2x.isErrorAny()) { |
|
387 throw new RuntimeException("Error during scalable image loading"); |
|
388 } |
|
389 |
|
390 final BufferedImage bufferedImage2x = new BufferedImage(2 * IMAGE_WIDTH, |
|
391 2 * IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); |
|
392 Graphics2D g2x = (Graphics2D) bufferedImage2x.getGraphics(); |
|
393 setImageScalingHint(g2x, enableImageScaling); |
|
394 g2x.drawImage(image, 0, 0, 2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null); |
|
395 checkColor(bufferedImage2x.getRGB(3 * IMAGE_WIDTH / 2, 3 * IMAGE_HEIGHT / 2), enableImageScaling); |
|
396 |
|
397 if (!(image instanceof MultiResolutionImage)) { |
|
398 throw new RuntimeException("Not a MultiResolutionImage"); |
|
399 } |
|
400 |
|
401 MultiResolutionImage multiResolutionImage = (MultiResolutionImage) image; |
|
402 |
|
403 Image image1x = multiResolutionImage.getResolutionVariant(IMAGE_WIDTH, IMAGE_HEIGHT); |
|
404 Image image2x = multiResolutionImage.getResolutionVariant(2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT); |
|
405 |
|
406 if (image1x.getWidth(null) * 2 != image2x.getWidth(null) |
|
407 || image1x.getHeight(null) * 2 != image2x.getHeight(null)) { |
|
408 throw new RuntimeException("Wrong resolution variant size"); |
|
409 } |
|
410 } |
|
411 |
|
412 static void testToolkitImageObserver(final Image image) { |
|
413 |
|
414 ImageObserver observer = new ImageObserver() { |
|
415 |
|
416 @Override |
|
417 public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { |
|
418 |
|
419 if (img != image) { |
|
420 throw new RuntimeException("Wrong image in observer"); |
|
421 } |
|
422 |
|
423 if ((infoflags & (ImageObserver.ERROR | ImageObserver.ABORT)) != 0) { |
|
424 throw new RuntimeException("Error during image loading"); |
|
425 } |
|
426 |
|
427 return (infoflags & ImageObserver.ALLBITS) == 0; |
|
428 |
|
429 } |
|
430 }; |
|
431 |
|
432 final BufferedImage bufferedImage2x = new BufferedImage(2 * IMAGE_WIDTH, |
|
433 2 * IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); |
|
434 Graphics2D g2x = (Graphics2D) bufferedImage2x.getGraphics(); |
|
435 setImageScalingHint(g2x, true); |
|
436 |
|
437 g2x.drawImage(image, 0, 0, 2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, observer); |
|
438 |
|
439 } |
|
440 |
|
441 static void setImageScalingHint(Graphics2D g2d, boolean enableImageScaling) { |
|
442 g2d.setRenderingHint(SunHints.KEY_RESOLUTION_VARIANT, enableImageScaling |
|
443 ? SunHints.VALUE_RESOLUTION_VARIANT_ON |
|
444 : SunHints.VALUE_RESOLUTION_VARIANT_OFF); |
|
445 } |
|
446 |
|
447 static void checkColor(int rgb, boolean isImageScaled) { |
|
448 |
|
449 if (!isImageScaled && COLOR_1X.getRGB() != rgb) { |
|
450 throw new RuntimeException("Wrong 1x color: " + new Color(rgb)); |
|
451 } |
|
452 |
|
453 if (isImageScaled && COLOR_2X.getRGB() != rgb) { |
|
454 throw new RuntimeException("Wrong 2x color" + new Color(rgb)); |
|
455 } |
|
456 } |
|
457 |
|
458 static void generateImages() throws Exception { |
|
459 if (!new File(IMAGE_NAME_1X).exists()) { |
|
460 generateImage(1); |
|
461 } |
|
462 |
|
463 if (!new File(IMAGE_NAME_2X).exists()) { |
|
464 generateImage(2); |
|
465 } |
|
466 } |
|
467 |
|
468 static void generateImage(int scale) throws Exception { |
|
469 BufferedImage image = new BufferedImage(scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT, |
|
470 BufferedImage.TYPE_INT_RGB); |
|
471 Graphics g = image.getGraphics(); |
|
472 g.setColor(scale == 1 ? COLOR_1X : COLOR_2X); |
|
473 g.fillRect(0, 0, scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT); |
|
474 File file = new File(scale == 1 ? IMAGE_NAME_1X : IMAGE_NAME_2X); |
|
475 ImageIO.write(image, "png", file); |
|
476 } |
|
477 |
|
478 static void testImageNameTo2xParsing() throws Exception { |
|
479 |
|
480 for (String[] testNames : TEST_FILE_NAMES) { |
|
481 String testName = testNames[0]; |
|
482 String goldenName = testNames[1]; |
|
483 String resultName = getTestScaledImageName(testName); |
|
484 |
|
485 if (!isValidPath(testName) && resultName == null) { |
|
486 continue; |
|
487 } |
|
488 |
|
489 if (goldenName.equals(resultName)) { |
|
490 continue; |
|
491 } |
|
492 |
|
493 throw new RuntimeException("Test name " + testName |
|
494 + ", result name: " + resultName); |
|
495 } |
|
496 |
|
497 for (URL[] testURLs : TEST_URLS) { |
|
498 URL testURL = testURLs[0]; |
|
499 URL goldenURL = testURLs[1]; |
|
500 URL resultURL = getTestScaledImageURL(testURL); |
|
501 |
|
502 if (!isValidPath(testURL.getPath()) && resultURL == null) { |
|
503 continue; |
|
504 } |
|
505 |
|
506 if (goldenURL.equals(resultURL)) { |
|
507 continue; |
|
508 } |
|
509 |
|
510 throw new RuntimeException("Test url: " + testURL |
|
511 + ", result url: " + resultURL); |
|
512 } |
|
513 |
|
514 } |
|
515 |
|
516 static URL getTestScaledImageURL(URL url) throws Exception { |
|
517 Method method = getScalableImageMethod("getScaledImageURL", URL.class); |
|
518 return (URL) method.invoke(null, url); |
|
519 } |
|
520 |
|
521 static String getTestScaledImageName(String name) throws Exception { |
|
522 Method method = getScalableImageMethod("getScaledImageName", String.class); |
|
523 return (String) method.invoke(null, name); |
|
524 } |
|
525 |
|
526 private static boolean isValidPath(String path) { |
|
527 return !path.isEmpty() && !path.endsWith("/") && !path.endsWith(".") |
|
528 && !path.contains("@2x"); |
|
529 } |
|
530 |
|
531 private static Method getScalableImageMethod(String name, |
|
532 Class... parameterTypes) throws Exception { |
|
533 Toolkit toolkit = Toolkit.getDefaultToolkit(); |
|
534 Method method = toolkit.getClass().getDeclaredMethod(name, parameterTypes); |
|
535 method.setAccessible(true); |
|
536 return method; |
|
537 } |
|
538 private static final String[][] TEST_FILE_NAMES; |
|
539 private static final URL[][] TEST_URLS; |
|
540 |
|
541 static { |
|
542 TEST_FILE_NAMES = new String[][]{ |
|
543 {"", null}, |
|
544 {".", null}, |
|
545 {"..", null}, |
|
546 {"/", null}, |
|
547 {"/.", null}, |
|
548 {"dir/", null}, |
|
549 {"dir/.", null}, |
|
550 {"aaa@2x.png", null}, |
|
551 {"/dir/aaa@2x.png", null}, |
|
552 {"image", "image@2x"}, |
|
553 {"image.ext", "image@2x.ext"}, |
|
554 {"image.aaa.ext", "image.aaa@2x.ext"}, |
|
555 {"dir/image", "dir/image@2x"}, |
|
556 {"dir/image.ext", "dir/image@2x.ext"}, |
|
557 {"dir/image.aaa.ext", "dir/image.aaa@2x.ext"}, |
|
558 {"dir/aaa.bbb/image", "dir/aaa.bbb/image@2x"}, |
|
559 {"dir/aaa.bbb/image.ext", "dir/aaa.bbb/image@2x.ext"}, |
|
560 {"dir/aaa.bbb/image.ccc.ext", "dir/aaa.bbb/image.ccc@2x.ext"}, |
|
561 {"/dir/image", "/dir/image@2x"}, |
|
562 {"/dir/image.ext", "/dir/image@2x.ext"}, |
|
563 {"/dir/image.aaa.ext", "/dir/image.aaa@2x.ext"}, |
|
564 {"/dir/aaa.bbb/image", "/dir/aaa.bbb/image@2x"}, |
|
565 {"/dir/aaa.bbb/image.ext", "/dir/aaa.bbb/image@2x.ext"}, |
|
566 {"/dir/aaa.bbb/image.ccc.ext", "/dir/aaa.bbb/image.ccc@2x.ext"} |
|
567 }; |
|
568 try { |
|
569 TEST_URLS = new URL[][]{ |
|
570 // file |
|
571 {new URL("file:/aaa"), new URL("file:/aaa@2x")}, |
|
572 {new URL("file:/aaa.ext"), new URL("file:/aaa@2x.ext")}, |
|
573 {new URL("file:/aaa.bbb.ext"), new URL("file:/aaa.bbb@2x.ext")}, |
|
574 {new URL("file:/ccc/aaa.bbb.ext"), |
|
575 new URL("file:/ccc/aaa.bbb@2x.ext")}, |
|
576 {new URL("file:/ccc.ddd/aaa.bbb.ext"), |
|
577 new URL("file:/ccc.ddd/aaa.bbb@2x.ext")}, |
|
578 {new URL("file:///~/image"), new URL("file:///~/image@2x")}, |
|
579 {new URL("file:///~/image.ext"), |
|
580 new URL("file:///~/image@2x.ext")}, |
|
581 // http |
|
582 {new URL("http://www.test.com"), null}, |
|
583 {new URL("http://www.test.com/"), null}, |
|
584 {new URL("http://www.test.com///"), null}, |
|
585 {new URL("http://www.test.com/image"), |
|
586 new URL("http://www.test.com/image@2x")}, |
|
587 {new URL("http://www.test.com/image.ext"), |
|
588 new URL("http://www.test.com/image@2x.ext")}, |
|
589 {new URL("http://www.test.com/dir/image"), |
|
590 new URL("http://www.test.com/dir/image@2x")}, |
|
591 {new URL("http://www.test.com:80/dir/image.aaa.ext"), |
|
592 new URL("http://www.test.com:80/dir/image.aaa@2x.ext")}, |
|
593 {new URL("http://www.test.com:8080/dir/image.aaa.ext"), |
|
594 new URL("http://www.test.com:8080/dir/image.aaa@2x.ext")}, |
|
595 // jar |
|
596 {new URL("jar:file:/dir/Java2D.jar!/image"), |
|
597 new URL("jar:file:/dir/Java2D.jar!/image@2x")}, |
|
598 {new URL("jar:file:/dir/Java2D.jar!/image.aaa.ext"), |
|
599 new URL("jar:file:/dir/Java2D.jar!/image.aaa@2x.ext")}, |
|
600 {new URL("jar:file:/dir/Java2D.jar!/images/image"), |
|
601 new URL("jar:file:/dir/Java2D.jar!/images/image@2x")}, |
|
602 {new URL("jar:file:/dir/Java2D.jar!/images/image.ext"), |
|
603 new URL("jar:file:/dir/Java2D.jar!/images/image@2x.ext")}, |
|
604 {new URL("jar:file:/aaa.bbb/Java2D.jar!/images/image.ext"), |
|
605 new URL("jar:file:/aaa.bbb/Java2D.jar!/images/image@2x.ext")}, |
|
606 {new URL("jar:file:/dir/Java2D.jar!/aaa.bbb/image.ext"), |
|
607 new URL("jar:file:/dir/Java2D.jar!/aaa.bbb/image@2x.ext")},}; |
|
608 } catch (Exception e) { |
|
609 throw new RuntimeException(e); |
|
610 } |
|
611 } |
|
612 |
|
613 static class PreloadedImageObserver implements ImageObserver { |
|
614 |
|
615 @Override |
|
616 public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { |
|
617 throw new RuntimeException("Image should be already preloaded"); |
|
618 } |
|
619 } |
|
620 } |