Ignore:
Timestamp:
2016-06-12T12:00:38+02:00 (8 years ago)
Author:
stoecker
Message:

see #9995 - improve handling for HIDPI screens, patch by strump (modified by me)

Location:
trunk/src/org/openstreetmap/josm/tools
Files:
2 edited

Legend:

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

    r10308 r10358  
    6969import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
    7070import org.openstreetmap.josm.gui.tagging.presets.TaggingPresets;
     71import org.openstreetmap.josm.gui.util.GuiSizesHelper;
    7172import org.openstreetmap.josm.io.CachedFile;
    7273import org.openstreetmap.josm.plugins.PluginHandler;
     
    145146        CURSOR(Main.pref.getInteger("iconsize.cursor", 32)),
    146147        /** cursor overlay icon size */
    147         CURSOROVERLAY(CURSOR.imageSize),
     148        CURSOROVERLAY(CURSOR),
    148149        /** menu icon size */
    149         MENU(SMALLICON.imageSize),
     150        MENU(SMALLICON),
    150151        /** menu icon size in popup menus
    151152         * @since 8323
    152153         */
    153         POPUPMENU(LARGEICON.imageSize),
     154        POPUPMENU(LARGEICON),
    154155        /** Layer list icon size
    155156         * @since 8323
     
    159160         * @since 9253
    160161         */
    161         TOOLBAR(LARGEICON.imageSize),
     162        TOOLBAR(LARGEICON),
    162163        /** Side button maximum height
    163164         * @since 9253
    164165         */
    165166        SIDEBUTTON(Main.pref.getInteger("iconsize.sidebutton", 20)),
     167        /** Settings tab icon size
     168         * @since 9253
     169         */
     170        SETTINGS_TAB(Main.pref.getInteger("iconsize.settingstab", 48)),
    166171        /**
    167172         * The default image size
    168173         * @since 9705
    169174         */
    170         DEFAULT(Main.pref.getInteger("iconsize.default", 24));
    171 
    172         private final int imageSize;
     175        DEFAULT(Main.pref.getInteger("iconsize.default", 24)),
     176        /**
     177         * Splash dialog logo size
     178         * @since 10358
     179         */
     180        SPLASH_LOGO(128, 129),
     181        /**
     182         * About dialog logo size
     183         * @since 10358
     184         */
     185        ABOUT_LOGO(256, 258);
     186
     187        private final int virtualWidth;
     188        private final int virtualHeight;
    173189
    174190        ImageSizes(int imageSize) {
    175             this.imageSize = imageSize;
     191            this.virtualWidth = imageSize;
     192            this.virtualHeight = imageSize;
     193        }
     194
     195        ImageSizes(int width, int height) {
     196            this.virtualWidth = width;
     197            this.virtualHeight = height;
     198        }
     199
     200        ImageSizes(ImageSizes that) {
     201            this.virtualWidth = that.virtualWidth;
     202            this.virtualHeight = that.virtualHeight;
    176203        }
    177204
    178205        /**
    179          * Returns the image size in pixels
    180          * @return the image size in pixels
     206         * Returns the image width in virtual pixels
     207         * @return the image width in virtual pixels
     208         */
     209        public int getVirtualWidth() {
     210            return virtualWidth;
     211        }
     212
     213        /**
     214         * Returns the image height in virtual pixels
     215         * @return the image height in virtual pixels
    181216         * @since 9705
    182217         */
    183         public int getImageSize() {
    184             return imageSize;
     218        public int getVirtualHeight() {
     219            return virtualHeight;
    185220        }
    186221
     
    191226         */
    192227        public Dimension getImageDimension() {
    193             return new Dimension(imageSize, imageSize);
     228            return new Dimension(virtualWidth, virtualHeight);
    194229        }
    195230    }
     
    219254    /** directory inside the archive */
    220255    protected String inArchiveDir;
    221     /** width of the resulting image, -1 when original image data should be used */
    222     protected int width = -1;
    223     /** height of the resulting image, -1 when original image data should be used */
    224     protected int height = -1;
    225     /** maximum width of the resulting image, -1 for no restriction */
    226     protected int maxWidth = -1;
    227     /** maximum height of the resulting image, -1 for no restriction */
    228     protected int maxHeight = -1;
     256    /** virtual width of the resulting image, -1 when original image data should be used */
     257    protected int virtualWidth = -1;
     258    /** virtual height of the resulting image, -1 when original image data should be used */
     259    protected int virtualHeight = -1;
     260    /** virtual maximum width of the resulting image, -1 for no restriction */
     261    protected int virtualMaxWidth = -1;
     262    /** virtual maximum height of the resulting image, -1 for no restriction */
     263    protected int virtualMaxHeight = -1;
    229264    /** In case of errors do not throw exception but return <code>null</code> for missing image */
    230265    protected boolean optional;
     
    306341        this.archive = image.archive;
    307342        this.inArchiveDir = image.inArchiveDir;
    308         this.width = image.width;
    309         this.height = image.height;
    310         this.maxWidth = image.maxWidth;
    311         this.maxHeight = image.maxHeight;
     343        this.virtualWidth = image.virtualWidth;
     344        this.virtualHeight = image.virtualHeight;
     345        this.virtualMaxWidth = image.virtualMaxWidth;
     346        this.virtualMaxHeight = image.virtualMaxHeight;
    312347        this.optional = image.optional;
    313348        this.suppressWarnings = image.suppressWarnings;
     
    389424     */
    390425    public ImageProvider setSize(Dimension size) {
    391         this.width = size.width;
    392         this.height = size.height;
     426        this.virtualWidth = size.width;
     427        this.virtualHeight = size.height;
    393428        return this;
    394429    }
     
    407442
    408443    /**
     444     * Set the dimensions of the image.
     445     *
     446     * @param width final width of the image
     447     * @param height final height of the image
     448     * @return the current object, for convenience
     449     * @since 10358
     450     */
     451    public ImageProvider setSize(int width, int height) {
     452        this.virtualWidth = width;
     453        this.virtualHeight = height;
     454        return this;
     455    }
     456
     457    /**
    409458     * Set image width
    410459     * @param width final width of the image
     
    413462     */
    414463    public ImageProvider setWidth(int width) {
    415         this.width = width;
     464        this.virtualWidth = width;
    416465        return this;
    417466    }
     
    424473     */
    425474    public ImageProvider setHeight(int height) {
    426         this.height = height;
     475        this.virtualHeight = height;
    427476        return this;
    428477    }
     
    439488     */
    440489    public ImageProvider setMaxSize(Dimension maxSize) {
    441         this.maxWidth = maxSize.width;
    442         this.maxHeight = maxSize.height;
     490        this.virtualMaxWidth = maxSize.width;
     491        this.virtualMaxHeight = maxSize.height;
    443492        return this;
    444493    }
     
    458507     */
    459508    public ImageProvider resetMaxSize(Dimension maxSize) {
    460         if (this.maxWidth == -1 || maxSize.width < this.maxWidth) {
    461             this.maxWidth = maxSize.width;
    462         }
    463         if (this.maxHeight == -1 || maxSize.height < this.maxHeight) {
    464             this.maxHeight = maxSize.height;
     509        if (this.virtualMaxWidth == -1 || maxSize.width < this.virtualMaxWidth) {
     510            this.virtualMaxWidth = maxSize.width;
     511        }
     512        if (this.virtualMaxHeight == -1 || maxSize.height < this.virtualMaxHeight) {
     513            this.virtualMaxHeight = maxSize.height;
    465514        }
    466515        return this;
     
    498547     */
    499548    public ImageProvider setMaxWidth(int maxWidth) {
    500         this.maxWidth = maxWidth;
     549        this.virtualMaxWidth = maxWidth;
    501550        return this;
    502551    }
     
    509558     */
    510559    public ImageProvider setMaxHeight(int maxHeight) {
    511         this.maxHeight = maxHeight;
     560        this.virtualMaxHeight = maxHeight;
    512561        return this;
    513562    }
     
    557606        if (ir == null)
    558607            return null;
    559         if (maxWidth != -1 || maxHeight != -1)
    560             return ir.getImageIconBounded(new Dimension(maxWidth, maxHeight));
     608        if (virtualMaxWidth != -1 || virtualMaxHeight != -1)
     609            return ir.getImageIconBounded(new Dimension(virtualMaxWidth, virtualMaxHeight));
    561610        else
    562             return ir.getImageIcon(new Dimension(width, height));
     611            return ir.getImageIcon(new Dimension(virtualWidth, virtualHeight));
    563612    }
    564613
     
    656705
    657706    /**
     707     * Load an empty image with a given size.
     708     *
     709     * @param size Target icon size
     710     * @return The requested Image.
     711     * @since 10358
     712     */
     713    public static ImageIcon getEmpty(ImageSizes size) {
     714        Dimension iconRealSize = GuiSizesHelper.getDimensionDpiAdjusted(size.getImageDimension());
     715        return new ImageIcon(new BufferedImage(iconRealSize.width, iconRealSize.height,
     716            BufferedImage.TYPE_INT_ARGB));
     717    }
     718
     719    /**
    658720     * Load an image with a given file name.
    659721     *
     
    689751    public static ImageIcon getIfAvailable(String name) {
    690752        return new ImageProvider(name).setOptional(true).get();
     753    }
     754
     755    /**
     756     * Scale image to virtual dimensions. This util method is used to hide real sizes calculations.
     757     * All other classes should use this method to resize images.
     758     *
     759     * @param im image to be resized
     760     * @param virtualWidth target width of image in virtual pixels
     761     * @param virtualHeight target height of image in virtual pixels
     762     * @return new scaled image in real dimensions
     763     */
     764    public static ImageIcon getScaledIcon(Image im, int virtualWidth, int virtualHeight) {
     765        int realWidth = GuiSizesHelper.getSizeDpiAdjusted(virtualWidth);
     766        int realHeight = GuiSizesHelper.getSizeDpiAdjusted(virtualHeight);
     767
     768        return new ImageIcon(im.getScaledInstance(realWidth, realHeight, Image.SCALE_SMOOTH));
    691769    }
    692770
     
    13331411                    MapImage icon = nodeStyle.mapImage;
    13341412                    if (icon != null) {
    1335                         int backgroundWidth = iconSize.width;
    1336                         int backgroundHeight = iconSize.height;
    1337                         int iconWidth = icon.getWidth();
    1338                         int iconHeight = icon.getHeight();
    1339                         BufferedImage image = new BufferedImage(backgroundWidth, backgroundHeight,
     1413                        int backgroundRealWidth = GuiSizesHelper.getSizeDpiAdjusted(iconSize.width);
     1414                        int backgroundRealHeight = GuiSizesHelper.getSizeDpiAdjusted(iconSize.height);
     1415                        int iconRealWidth = icon.getWidth();
     1416                        int iconRealHeight = icon.getHeight();
     1417                        BufferedImage image = new BufferedImage(backgroundRealWidth, backgroundRealHeight,
    13401418                                BufferedImage.TYPE_INT_ARGB);
    1341                         double scaleFactor = Math.min(backgroundWidth / (double) iconWidth, backgroundHeight
    1342                                 / (double) iconHeight);
     1419                        double scaleFactor = Math.min(backgroundRealWidth / (double) iconRealWidth, backgroundRealHeight
     1420                                / (double) iconRealHeight);
    13431421                        BufferedImage iconImage = icon.getImage(false);
    13441422                        Image scaledIcon;
     
    13471425                        if (scaleFactor < 1) {
    13481426                            // Scale icon such that it fits on background.
    1349                             scaledWidth = (int) (iconWidth * scaleFactor);
    1350                             scaledHeight = (int) (iconHeight * scaleFactor);
     1427                            scaledWidth = (int) (iconRealWidth * scaleFactor);
     1428                            scaledHeight = (int) (iconRealHeight * scaleFactor);
    13511429                            scaledIcon = iconImage.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_SMOOTH);
    13521430                        } else {
    13531431                            // Use original size, don't upscale.
    1354                             scaledWidth = iconWidth;
    1355                             scaledHeight = iconHeight;
     1432                            scaledWidth = iconRealWidth;
     1433                            scaledHeight = iconRealHeight;
    13561434                            scaledIcon = iconImage;
    13571435                        }
    1358                         image.getGraphics().drawImage(scaledIcon, (backgroundWidth - scaledWidth) / 2,
    1359                                 (backgroundHeight - scaledHeight) / 2, null);
     1436                        image.getGraphics().drawImage(scaledIcon, (backgroundRealWidth - scaledWidth) / 2,
     1437                                (backgroundRealHeight - scaledHeight) / 2, null);
    13601438
    13611439                        return new ImageIcon(image);
     
    13941472     */
    13951473    public static BufferedImage createImageFromSvg(SVGDiagram svg, Dimension dim) {
    1396         float realWidth = svg.getWidth();
    1397         float realHeight = svg.getHeight();
    1398         int width = Math.round(realWidth);
    1399         int height = Math.round(realHeight);
    1400         Double scaleX = null, scaleY = null;
     1474        float sourceWidth = svg.getWidth();
     1475        float sourceHeight = svg.getHeight();
     1476        int realWidth = Math.round(GuiSizesHelper.getSizeDpiAdjusted(sourceWidth));
     1477        int realHeight = Math.round(GuiSizesHelper.getSizeDpiAdjusted(sourceHeight));
     1478        Double scaleX, scaleY;
    14011479        if (dim.width != -1) {
    1402             width = dim.width;
    1403             scaleX = (double) width / realWidth;
     1480            realWidth = dim.width;
     1481            scaleX = (double) realWidth / sourceWidth;
    14041482            if (dim.height == -1) {
    14051483                scaleY = scaleX;
    1406                 height = (int) Math.round(realHeight * scaleY);
     1484                realHeight = (int) Math.round(sourceHeight * scaleY);
    14071485            } else {
    1408                 height = dim.height;
    1409                 scaleY = (double) height / realHeight;
     1486                realHeight = dim.height;
     1487                scaleY = (double) realHeight / sourceHeight;
    14101488            }
    14111489        } else if (dim.height != -1) {
    1412             height = dim.height;
    1413             scaleX = scaleY = (double) height / realHeight;
    1414             width = (int) Math.round(realWidth * scaleX);
    1415         }
    1416         if (width == 0 || height == 0) {
     1490            realHeight = dim.height;
     1491            scaleX = scaleY = (double) realHeight / sourceHeight;
     1492            realWidth = (int) Math.round(sourceWidth * scaleX);
     1493        }
     1494        else {
     1495            scaleX = scaleY = (double) realHeight / sourceHeight;
     1496        }
     1497
     1498        if (realWidth == 0 || realHeight == 0) {
    14171499            return null;
    14181500        }
    1419         BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
     1501        BufferedImage img = new BufferedImage(realWidth, realHeight, BufferedImage.TYPE_INT_ARGB);
    14201502        Graphics2D g = img.createGraphics();
    1421         g.setClip(0, 0, width, height);
    1422         if (scaleX != null && scaleY != null) {
    1423             g.scale(scaleX, scaleY);
    1424         }
     1503        g.setClip(0, 0, realWidth, realHeight);
     1504        g.scale(scaleX, scaleY);
    14251505        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    14261506        try {
  • trunk/src/org/openstreetmap/josm/tools/ImageResource.java

    r10356 r10358  
    1414
    1515import com.kitfox.svg.SVGDiagram;
     16import org.openstreetmap.josm.gui.util.GuiSizesHelper;
    1617
    1718/**
     
    5051        CheckParameterUtil.ensureParameterNotNull(img);
    5152        this.baseImage = img;
     53
     54        img = scaleBaseImageIfNeeded(img);
     55
    5256        imgCache.put(DEFAULT_DIMENSION, img);
     57    }
     58
     59    /** Scale image according to screen DPI if needed.
     60     *
     61     * @param img an image loaded from file (it's width and height are virtual pixels)
     62     * @return original img if virtual size is the same as real size or new image resized to real pixels
     63     */
     64    private static Image scaleBaseImageIfNeeded(Image img) {
     65        int imgWidth = img.getWidth(null);
     66        int imgHeight = img.getHeight(null);
     67        int realWidth = GuiSizesHelper.getSizeDpiAdjusted(imgWidth);
     68        int realHeight = GuiSizesHelper.getSizeDpiAdjusted(imgHeight);
     69        if (realWidth != -1 && realHeight != -1 && imgWidth != realWidth && imgHeight != realHeight) {
     70            Image realImage = img.getScaledInstance(realWidth, realHeight, Image.SCALE_SMOOTH);
     71            BufferedImage bimg = new BufferedImage(realWidth, realHeight, BufferedImage.TYPE_INT_ARGB);
     72            bimg.getGraphics().drawImage(realImage, 0, 0, null);
     73            img = bimg;
     74        }
     75        return img;
    5376    }
    5477
     
    88111     */
    89112    public void getImageIcon(AbstractAction a) {
    90         ImageIcon icon = getImageIconBounded(ImageProvider.ImageSizes.SMALLICON.getImageDimension());
     113        Dimension iconDimension = ImageProvider.ImageSizes.SMALLICON.getImageDimension();
     114        ImageIcon icon = getImageIconBounded(iconDimension);
    91115        a.putValue(Action.SMALL_ICON, icon);
    92         icon = getImageIconBounded(ImageProvider.ImageSizes.LARGEICON.getImageDimension());
     116
     117        iconDimension = ImageProvider.ImageSizes.LARGEICON.getImageDimension();
     118        icon = getImageIconBounded(iconDimension);
    93119        a.putValue(Action.LARGE_ICON_KEY, icon);
    94120        a.putValue("ImageResource", this);
     
    123149        }
    124150        if (svg != null) {
    125             BufferedImage bimg = ImageProvider.createImageFromSvg(svg, dim);
     151            Dimension realDim = GuiSizesHelper.getDimensionDpiAdjusted(dim);
     152            BufferedImage bimg = ImageProvider.createImageFromSvg(svg, realDim);
    126153            if (bimg == null) {
    127154                return null;
     
    137164            if (baseImage == null) throw new AssertionError();
    138165
    139             int width = dim.width;
    140             int height = dim.height;
     166            int realWidth = GuiSizesHelper.getSizeDpiAdjusted(dim.width);
     167            int realHeight = GuiSizesHelper.getSizeDpiAdjusted(dim.height);
    141168            ImageIcon icon = new ImageIcon(baseImage);
    142             if (width == -1 && height == -1) {
    143                 width = icon.getIconWidth();
    144                 height = icon.getIconHeight();
    145             } else if (width == -1) {
    146                 width = Math.max(1, icon.getIconWidth() * height / icon.getIconHeight());
    147             } else if (height == -1) {
    148                 height = Math.max(1, icon.getIconHeight() * width / icon.getIconWidth());
    149             }
    150             Image i = icon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
    151             BufferedImage bimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
     169            if (realWidth == -1 && realHeight == -1) {
     170                realWidth = GuiSizesHelper.getSizeDpiAdjusted(icon.getIconWidth());
     171                realHeight = GuiSizesHelper.getSizeDpiAdjusted(icon.getIconHeight());
     172            } else if (realWidth == -1) {
     173                realWidth = Math.max(1, icon.getIconWidth() * realHeight / icon.getIconHeight());
     174            } else if (realHeight == -1) {
     175                realHeight = Math.max(1, icon.getIconHeight() * realWidth / icon.getIconWidth());
     176            }
     177            Image i = icon.getImage().getScaledInstance(realWidth, realHeight, Image.SCALE_SMOOTH);
     178            BufferedImage bimg = new BufferedImage(realWidth, realHeight, BufferedImage.TYPE_INT_ARGB);
    152179            bimg.getGraphics().drawImage(i, 0, 0, null);
    153180            if (overlayInfo != null) {
     
    172199        if (maxSize.width < -1 || maxSize.width == 0 || maxSize.height < -1 || maxSize.height == 0)
    173200            throw new IllegalArgumentException(maxSize+" is invalid");
    174         float realWidth;
    175         float realHeight;
     201        float sourceWidth;
     202        float sourceHeight;
    176203        int maxWidth = maxSize.width;
    177204        int maxHeight = maxSize.height;
    178205        if (svg != null) {
    179             realWidth = svg.getWidth();
    180             realHeight = svg.getHeight();
     206            sourceWidth = svg.getWidth();
     207            sourceHeight = svg.getHeight();
    181208        } else {
    182209            if (baseImage == null) throw new AssertionError();
    183210            ImageIcon icon = new ImageIcon(baseImage);
    184             realWidth = icon.getIconWidth();
    185             realHeight = icon.getIconHeight();
    186             if (realWidth <= maxWidth) {
     211            sourceWidth = icon.getIconWidth();
     212            sourceHeight = icon.getIconHeight();
     213            if (sourceWidth <= maxWidth) {
    187214                maxWidth = -1;
    188215            }
    189             if (realHeight <= maxHeight) {
     216            if (sourceHeight <= maxHeight) {
    190217                maxHeight = -1;
    191218            }
     
    198225        else if (maxHeight == -1)
    199226            return getImageIcon(new Dimension(maxWidth, -1));
    200         else if (realWidth / maxWidth > realHeight / maxHeight)
     227        else if (sourceWidth / maxWidth > sourceHeight / maxHeight)
    201228            return getImageIcon(new Dimension(maxWidth, -1));
    202229        else
Note: See TracChangeset for help on using the changeset viewer.