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

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/tools/ImageProvider.java

    r16436 r16486  
    13181318     */
    13191319    public static Cursor getCursor(String name, String overlay) {
    1320         ImageIcon img = get("cursor", name);
    1321         if (overlay != null) {
    1322             img = new ImageProvider("cursor", name).setMaxSize(ImageSizes.CURSOR)
    1323                 .addOverlay(new ImageOverlay(new ImageProvider("cursor/modifier/" + overlay)
    1324                     .setMaxSize(ImageSizes.CURSOROVERLAY))).get();
    1325         }
    13261320        if (GraphicsEnvironment.isHeadless()) {
    13271321            Logging.debug("Cursors are not available in headless mode. Returning null for ''{0}''", name);
    13281322            return null;
    13291323        }
    1330         return Toolkit.getDefaultToolkit().createCustomCursor(img.getImage(),
    1331                 "crosshair".equals(name) ? new Point(10, 10) : new Point(3, 2), "Cursor");
     1324
     1325        Point hotSpot = new Point();
     1326        Image image = getCursorImage(name, overlay, hotSpot);
     1327
     1328        return Toolkit.getDefaultToolkit().createCustomCursor(image, hotSpot, name);
     1329    }
     1330
     1331    /**
     1332     * Load a cursor image with a given file name, optionally decorated with an overlay image
     1333     *
     1334     * @param name the cursor image filename in "cursor" directory
     1335     * @param overlay optional overlay image
     1336     * @param hotSpot will be set to the properly scaled hotspot of the cursor
     1337     * @return cursor with a given file name, optionally decorated with an overlay image
     1338     */
     1339    static Image getCursorImage(String name, String overlay, /* out */ Point hotSpot) {
     1340        ImageProvider imageProvider = new ImageProvider("cursor", name);
     1341        if (overlay != null) {
     1342            imageProvider
     1343                .setMaxSize(ImageSizes.CURSOR)
     1344                .addOverlay(new ImageOverlay(new ImageProvider("cursor/modifier/" + overlay)
     1345                                                .setMaxSize(ImageSizes.CURSOROVERLAY)));
     1346        }
     1347        hotSpot.setLocation("crosshair".equals(name) ? new Point(10, 10) : new Point(3, 2));
     1348        ImageIcon imageIcon = imageProvider.get();
     1349        Image image = imageIcon.getImage();
     1350        int width = image.getWidth(null);
     1351        int height = image.getHeight(null);
     1352
     1353        // AWT will resize the cursor to bestCursorSize internally anyway, but miss to scale the hotspot as well
     1354        // (bug JDK-8238734).  So let's do this ourselves, and also scale the hotspot accordingly.
     1355        Dimension bestCursorSize = Toolkit.getDefaultToolkit().getBestCursorSize(width, height);
     1356        if (bestCursorSize.width != 0 && bestCursorSize.height != 0) {
     1357            // In principle, we could pass the MultiResolutionImage itself to AWT, but due to bug JDK-8240568,
     1358            // this results in bad alpha blending and thus jaggy edges.  So let's select the best variant ourselves.
     1359            image = HiDPISupport.getResolutionVariant(image, bestCursorSize.width, bestCursorSize.height);
     1360            if (bestCursorSize.width != image.getWidth(null) || bestCursorSize.height != image.getHeight(null)) {
     1361                image = image.getScaledInstance(bestCursorSize.width, bestCursorSize.height, Image.SCALE_DEFAULT);
     1362            }
     1363
     1364            hotSpot.x = hotSpot.x * bestCursorSize.width / width;
     1365            hotSpot.y = hotSpot.y * bestCursorSize.height / height;
     1366        }
     1367
     1368        return image;
    13321369    }
    13331370
Note: See TracChangeset for help on using the changeset viewer.