- Timestamp:
- 2020-08-30T21:27:14+02:00 (4 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/tools/ImageProvider.java
r16946 r16984 48 48 import java.util.concurrent.Executors; 49 49 import java.util.function.Consumer; 50 import java.util.function.UnaryOperator; 50 51 import java.util.regex.Matcher; 51 52 import java.util.regex.Pattern; … … 1331 1332 1332 1333 Point hotSpot = new Point(); 1333 Image image = getCursorImage(name, overlay, hotSpot);1334 Image image = getCursorImage(name, overlay, dim -> Toolkit.getDefaultToolkit().getBestCursorSize(dim.width, dim.height), hotSpot); 1334 1335 1335 1336 return Toolkit.getDefaultToolkit().createCustomCursor(image, hotSpot, name); … … 1348 1349 * @param name the cursor image filename in "cursor" directory 1349 1350 * @param overlay optional overlay image 1351 * @param bestCursorSizeFunction computes the best cursor size, see {@link Toolkit#getBestCursorSize(int, int)} 1350 1352 * @param hotSpot will be set to the properly scaled hotspot of the cursor 1351 1353 * @return cursor with a given file name, optionally decorated with an overlay image 1352 1354 */ 1353 static Image getCursorImage(String name, String overlay, /* out */ Point hotSpot) {1355 static Image getCursorImage(String name, String overlay, UnaryOperator<Dimension> bestCursorSizeFunction, /* out */ Point hotSpot) { 1354 1356 ImageProvider imageProvider = new ImageProvider("cursor", name); 1355 1357 if (overlay != null) { … … 1366 1368 // AWT will resize the cursor to bestCursorSize internally anyway, but miss to scale the hotspot as well 1367 1369 // (bug JDK-8238734). So let's do this ourselves, and also scale the hotspot accordingly. 1368 Dimension bestCursorSize = Toolkit.getDefaultToolkit().getBestCursorSize(width, height);1370 Dimension bestCursorSize = bestCursorSizeFunction.apply(new Dimension(width, height)); 1369 1371 if (bestCursorSize.width != 0 && bestCursorSize.height != 0) { 1370 1372 // In principle, we could pass the MultiResolutionImage itself to AWT, but due to bug JDK-8240568, -
trunk/test/functional/org/openstreetmap/josm/tools/ImageProviderTest.java
r16983 r16984 2 2 package org.openstreetmap.josm.tools; 3 3 4 import static java.awt.image.BufferedImage.TYPE_INT_ARGB;5 4 import static org.junit.Assert.assertEquals; 6 5 import static org.junit.Assert.assertFalse; 7 6 import static org.junit.Assert.assertNotNull; 8 import static org.junit.Assert.assertTrue;9 7 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 10 8 import static org.openstreetmap.josm.gui.mappaint.MapCSSRendererTest.assertImageEquals; 11 9 12 10 import java.awt.Dimension; 13 import java.awt.GraphicsEnvironment;14 11 import java.awt.Image; 15 12 import java.awt.Point; 16 import java.awt.Toolkit;17 13 import java.awt.Transparency; 18 14 import java.awt.image.BufferedImage; … … 22 18 import java.util.Collections; 23 19 import java.util.List; 20 import java.util.function.UnaryOperator; 24 21 import java.util.logging.Handler; 25 22 import java.util.logging.LogRecord; … … 28 25 import javax.swing.ImageIcon; 29 26 30 import org.junit.Before; 31 import org.junit.BeforeClass; 32 import org.junit.Rule; 33 import org.junit.Test; 27 import org.junit.jupiter.api.BeforeAll; 28 import org.junit.jupiter.api.BeforeEach; 29 import org.junit.jupiter.api.Test; 30 import org.junit.jupiter.api.extension.RegisterExtension; 31 import org.junit.jupiter.params.ParameterizedTest; 32 import org.junit.jupiter.params.provider.ValueSource; 34 33 import org.openstreetmap.josm.JOSMFixture; 35 34 import org.openstreetmap.josm.TestUtils; … … 54 53 * Setup test. 55 54 */ 56 @R ule55 @RegisterExtension 57 56 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 58 57 public JOSMTestRules test = new JOSMTestRules(); … … 80 79 * Setup test. 81 80 */ 82 @Before Class81 @BeforeAll 83 82 public static void setUp() { 84 83 JOSMFixture.createUnitTestFixture().init(); 85 84 } 86 85 87 @Before 86 @BeforeEach 88 87 public void resetPixelDensity() { 89 88 GuiSizesHelper.setPixelDensity(1.0f); … … 204 203 private static void testImage(int width, int height, String reference, ImageIcon icon) throws IOException { 205 204 final BufferedImage image = (BufferedImage) icon.getImage(); 206 final File referenceFile = new File( 207 TestUtils.getTestDataRoot() + "/" + ImageProviderTest.class.getSimpleName() + "/" + reference + ".png"); 205 final File referenceFile = getReferenceFile(reference); 208 206 assertEquals("width", width, image.getWidth(null)); 209 207 assertEquals("height", height, image.getHeight(null)); 210 208 assertImageEquals(reference, referenceFile, image, 0, 0, null); 209 } 210 211 private static File getReferenceFile(String reference) { 212 return new File(TestUtils.getTestDataRoot() + "/" + ImageProviderTest.class.getSimpleName() + "/" + reference + ".png"); 211 213 } 212 214 … … 237 239 * Test getting an image for a crosshair cursor. 238 240 */ 239 @Test 240 public void testGetCursorImageForCrosshair() { 241 if (GraphicsEnvironment.isHeadless()) { 242 // TODO mock Toolkit.getDefaultToolkit().getBestCursorSize() 243 return; 244 } 245 Point hotSpot = new Point(); 246 Image image = ImageProvider.getCursorImage("crosshair", null, hotSpot); 247 assertCursorDimensionsCorrect(new Point.Double(10.0, 10.0), image, hotSpot); 248 } 249 250 /** 251 * Test getting an image for a custom cursor with overlay. 252 */ 253 @Test 254 public void testGetCursorImageWithOverlay() { 255 testCursorImageWithOverlay(1.0f); // normal case 256 testCursorImageWithOverlay(1.5f); // user has configured a GUI scale of 1.5 in the JOSM advanced preferences 257 } 258 259 private void testCursorImageWithOverlay(float guiScale) { 260 if (GraphicsEnvironment.isHeadless()) { 261 // TODO mock Toolkit.getDefaultToolkit().getBestCursorSize() 262 return; 263 } 241 @ParameterizedTest 242 @ValueSource(floats = {1.0f, 1.5f, 3.0f}) 243 public void testGetCursorImageForCrosshair(float guiScale) throws IOException { 264 244 GuiSizesHelper.setPixelDensity(guiScale); 265 245 Point hotSpot = new Point(); 266 Image image = ImageProvider.getCursorImage("normal", "selection", hotSpot); 267 assertCursorDimensionsCorrect(new Point.Double(3.0, 2.0), image, hotSpot); 268 BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getWidth(null), TYPE_INT_ARGB); 269 bufferedImage.getGraphics().drawImage(image, 0, 0, null); 270 271 // check that the square of 1/4 size right lower to the center has some non-empty pixels 272 boolean nonEmptyPixelExistsRightLowerToCenter = false; 273 for (int x = image.getWidth(null) / 2; x < image.getWidth(null) * 3 / 4; ++x) { 274 for (int y = image.getHeight(null) / 2; y < image.getWidth(null) * 3 / 4; ++y) { 275 if (bufferedImage.getRGB(x, y) != 0) 276 nonEmptyPixelExistsRightLowerToCenter = true; 277 } 278 } 279 assertTrue(nonEmptyPixelExistsRightLowerToCenter); 280 } 281 282 private void assertCursorDimensionsCorrect(Point.Double originalHotspot, Image image, Point hotSpot) { 246 final UnaryOperator<Dimension> bestCursorSizeFunction = dim -> dim; 247 Image image = ImageProvider.getCursorImage("crosshair", null, bestCursorSizeFunction, hotSpot); 248 assertCursorDimensionsCorrect(new Point.Double(10.0, 10.0), image, bestCursorSizeFunction, hotSpot); 249 assertImageEquals("cursor", getReferenceFile("cursor-crosshair-" + Math.round(guiScale * 10)), 250 ((BufferedImage) image), 0, 0, null); 251 } 252 253 /** 254 * Test getting an image for a custom cursor with overlay. 255 */ 256 @ParameterizedTest 257 @ValueSource(floats = {1.0f, 1.5f, 3.0f}) 258 public void testGetCursorImageWithOverlay(float guiScale) throws IOException { 259 GuiSizesHelper.setPixelDensity(guiScale); 260 Point hotSpot = new Point(); 261 final UnaryOperator<Dimension> bestCursorSizeFunction = dim -> dim; 262 Image image = ImageProvider.getCursorImage("normal", "selection", bestCursorSizeFunction, hotSpot); 263 assertCursorDimensionsCorrect(new Point.Double(3.0, 2.0), image, bestCursorSizeFunction, hotSpot); 264 assertImageEquals("cursor", getReferenceFile("cursor-normal-selection-" + Math.round(guiScale * 10)), 265 ((BufferedImage) image), 0, 0, null); 266 } 267 268 private void assertCursorDimensionsCorrect(Point.Double originalHotspot, Image image, 269 UnaryOperator<Dimension> bestCursorSizeFunction, Point hotSpot) { 283 270 int originalCursorSize = ImageProvider.CURSOR_SIZE_HOTSPOT_IS_RELATIVE_TO; 284 Dimension bestCursorSize = Toolkit.getDefaultToolkit().getBestCursorSize(originalCursorSize, originalCursorSize);271 Dimension bestCursorSize = bestCursorSizeFunction.apply(new Dimension(originalCursorSize, originalCursorSize)); 285 272 Image bestCursorImage = HiDPISupport.getResolutionVariant(image, bestCursorSize.width, bestCursorSize.height); 286 273 int bestCursorImageWidth = bestCursorImage.getWidth(null);
Note:
See TracChangeset
for help on using the changeset viewer.