Changeset 16486 in josm for trunk/test


Ignore:
Timestamp:
2020-05-23T21:19:14+02:00 (4 years ago)
Author:
simon04
Message:

fix #18694 - Wrongly rendered cursors on HiDPI screen (patch by johsin18)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/test/unit/org/openstreetmap/josm/tools/ImageProviderTest.java

    r15897 r16486  
    22package org.openstreetmap.josm.tools;
    33
     4import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
    45import static org.junit.Assert.assertEquals;
    56import static org.junit.Assert.assertFalse;
    67import static org.junit.Assert.assertNotNull;
    78import static org.junit.Assert.assertNull;
    8 
     9import static org.junit.Assert.assertTrue;
     10
     11import java.awt.Color;
    912import java.awt.Dimension;
     13import java.awt.GraphicsEnvironment;
     14import java.awt.GridLayout;
     15import java.awt.Graphics;
     16import java.awt.Image;
     17import java.awt.Point;
     18import java.awt.Toolkit;
    1019import java.awt.Transparency;
     20import java.awt.event.MouseEvent;
     21import java.awt.event.MouseListener;
    1122import java.awt.image.BufferedImage;
    1223import java.io.File;
    1324import java.io.IOException;
    1425import java.util.EnumSet;
     26import java.util.List;
    1527import java.util.logging.Handler;
    1628import java.util.logging.LogRecord;
     
    1830
    1931import javax.swing.ImageIcon;
    20 
     32import javax.swing.JFrame;
     33import javax.swing.JPanel;
     34
     35import org.junit.Before;
    2136import org.junit.BeforeClass;
     37import org.junit.Ignore;
    2238import org.junit.Rule;
    2339import org.junit.Test;
     
    7288    }
    7389
     90    @Before
     91    public void resetPixelDensity() {
     92        GuiSizesHelper.setPixelDensity(1.0f);
     93    }
     94
    7495    /**
    7596     * Non-regression test for ticket <a href="https://josm.openstreetmap.de/ticket/9984">#9984</a>
     
    149170        assertNotNull(ImageProvider.getPadded(OsmUtils.createPrimitive("relation type=route route=railway"), iconSize, noDefault));
    150171    }
     172
     173    /**
     174     * Test getting a bounded icon given some UI scaling configured.
     175     */
     176    @Test
     177    public void testGetImageIconBounded() {
     178        int scale = 2;
     179        GuiSizesHelper.setPixelDensity(scale);
     180
     181        ImageProvider imageProvider = new ImageProvider("open").setOptional(true);
     182        ImageResource resource = imageProvider.getResource();
     183        Dimension iconDimension = ImageProvider.ImageSizes.SMALLICON.getImageDimension();
     184        ImageIcon icon = resource.getImageIconBounded(iconDimension);
     185        Image image = icon.getImage();
     186        List<Image> resolutionVariants = HiDPISupport.getResolutionVariants(image);
     187        if (resolutionVariants.size() > 1) {
     188            assertEquals(2, resolutionVariants.size());
     189            int expectedVirtualWidth = ImageProvider.ImageSizes.SMALLICON.getVirtualWidth();
     190            assertEquals(expectedVirtualWidth * scale, resolutionVariants.get(0).getWidth(null));
     191            assertEquals((int) Math.round(expectedVirtualWidth * scale * HiDPISupport.getHiDPIScale()),
     192                         resolutionVariants.get(1).getWidth(null));
     193        }
     194    }
     195
     196    public static final int ORIGINAL_CURSOR_SIZE = 32;
     197
     198    /**
     199     * Test getting an image for a crosshair cursor.
     200     */
     201    @Test
     202    public void testGetCursorImageForCrosshair() {
     203        if (GraphicsEnvironment.isHeadless()) {
     204            // TODO mock Toolkit.getDefaultToolkit().getBestCursorSize()
     205            return;
     206        }
     207        Point hotSpot = new Point();
     208        Image image = ImageProvider.getCursorImage("crosshair", null, hotSpot);
     209        assertCursorDimensionsCorrect(new Point.Double(10.0, 10.0), image, hotSpot);
     210    }
     211
     212    /**
     213     * Test getting an image for a custom cursor with overlay.
     214     */
     215    @Test
     216    public void testGetCursorImageWithOverlay() {
     217        if (GraphicsEnvironment.isHeadless()) {
     218            // TODO mock Toolkit.getDefaultToolkit().getBestCursorSize()
     219            return;
     220        }
     221        Point hotSpot = new Point();
     222        Image image = ImageProvider.getCursorImage("normal", "selection", hotSpot);
     223        assertCursorDimensionsCorrect(new Point.Double(3.0, 2.0), image, hotSpot);
     224        BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getWidth(null), TYPE_INT_ARGB);
     225        bufferedImage.getGraphics().drawImage(image, 0, 0, null);
     226
     227        // check that the square of 1/4 size right lower to the center has some non-emtpy pixels
     228        boolean nonEmptyPixelExistsRightLowerToCenter = false;
     229        for (int x = image.getWidth(null) / 2; x < image.getWidth(null) * 3 / 4; ++x) {
     230            for (int y = image.getHeight(null) / 2; y < image.getWidth(null) * 3 / 4; ++y) {
     231                if (bufferedImage.getRGB(x, y) != 0)
     232                    nonEmptyPixelExistsRightLowerToCenter = true;
     233            }
     234        }
     235        assertTrue(nonEmptyPixelExistsRightLowerToCenter);
     236    }
     237
     238    private void assertCursorDimensionsCorrect(Point.Double originalHotspot, Image image, Point hotSpot) {
     239        Dimension bestCursorSize = Toolkit.getDefaultToolkit().getBestCursorSize(ORIGINAL_CURSOR_SIZE, ORIGINAL_CURSOR_SIZE);
     240        Image bestCursorImage = HiDPISupport.getResolutionVariant(image, bestCursorSize.width, bestCursorSize.height);
     241        int bestCursorImageWidth = bestCursorImage.getWidth(null);
     242        assertEquals((int) Math.round(bestCursorSize.getWidth()), bestCursorImageWidth);
     243        int bestCursorImageHeight = bestCursorImage.getHeight(null);
     244        assertEquals((int) Math.round(bestCursorSize.getHeight()), bestCursorImageHeight);
     245        assertEquals(originalHotspot.x / ORIGINAL_CURSOR_SIZE * bestCursorImageWidth, hotSpot.x, 1 /* at worst one pixel off */);
     246        assertEquals(originalHotspot.y / ORIGINAL_CURSOR_SIZE * bestCursorImageHeight, hotSpot.y, 1 /* at worst one pixel off */);
     247    }
     248
     249
     250    /**
     251     * Test getting a cursor
     252     */
     253    @Ignore("manual execution only, as the look of the cursor cannot be checked automatedly")
     254    @Test
     255    public void testGetCursor() throws InterruptedException {
     256        JFrame frame = new JFrame();
     257        frame.setSize(500, 500);
     258        frame.setLayout(new GridLayout(2, 2));
     259        JPanel leftUpperPanel = new JPanel(), rightUpperPanel = new JPanel(), leftLowerPanel = new JPanel(), rightLowerPanel = new JPanel();
     260        leftUpperPanel.setBackground(Color.DARK_GRAY);
     261        rightUpperPanel.setBackground(Color.DARK_GRAY);
     262        leftLowerPanel.setBackground(Color.DARK_GRAY);
     263        rightLowerPanel.setBackground(Color.DARK_GRAY);
     264        frame.add(leftUpperPanel);
     265        frame.add(rightUpperPanel);
     266        frame.add(leftLowerPanel);
     267        frame.add(rightLowerPanel);
     268
     269        leftUpperPanel.setCursor(ImageProvider.getCursor("normal", "select_add")); // contains diagonal sensitive to alpha blending
     270        rightUpperPanel.setCursor(ImageProvider.getCursor("crosshair", "joinway")); // combination of overlay and hotspot not top left
     271        leftLowerPanel.setCursor(ImageProvider.getCursor("hand", "parallel_remove")); // reasonably nice bitmap cursor
     272        rightLowerPanel.setCursor(ImageProvider.getCursor("rotate", null)); // ugly bitmap cursor, cannot do much here
     273
     274        frame.setVisible(true);
     275
     276        // hover over the four quadrant to observe different cursors
     277
     278        // draw red dot at hotspot when clicking
     279        frame.addMouseListener(new MouseListener() {
     280            @Override
     281            public void mouseClicked(MouseEvent e) {
     282                Graphics graphics = frame.getGraphics();
     283                graphics.setColor(Color.RED);
     284                graphics.drawRect(e.getX(), e.getY(), 1, 1);
     285            }
     286
     287            @Override
     288            public void mousePressed(MouseEvent e) { }
     289
     290            @Override
     291            public void mouseReleased(MouseEvent e) { }
     292
     293            @Override
     294            public void mouseEntered(MouseEvent e) { }
     295
     296            @Override
     297            public void mouseExited(MouseEvent e) { }
     298        });
     299        Thread.sleep(9000); // test would time out after 10s
     300    }
    151301}
Note: See TracChangeset for help on using the changeset viewer.