Ignore:
Timestamp:
2017-09-04T18:52:06+02:00 (7 years ago)
Author:
bastiK
Message:

see #9995 - fix blurry GUI-icons and map view for Java 9 HiDPI mode

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/MapView.java

    r12651 r12722  
    99import java.awt.Point;
    1010import java.awt.Rectangle;
     11import java.awt.Shape;
    1112import java.awt.event.ComponentAdapter;
    1213import java.awt.event.ComponentEvent;
     
    1516import java.awt.event.MouseEvent;
    1617import java.awt.event.MouseMotionListener;
     18import java.awt.geom.AffineTransform;
    1719import java.awt.geom.Area;
    1820import java.awt.image.BufferedImage;
     
    511513
    512514    private void drawMapContent(Graphics g) {
     515        // In HiDPI-mode, the Graphics g will have a transform that scales
     516        // everything by a factor of 2.0 or so. At the same time, the value returned
     517        // by getWidth()/getHeight will be reduced by that factor.
     518        //
     519        // This would work as intended, if we were to draw directly on g. But
     520        // with a temporary buffer image, we need to move the scale transform to
     521        // the Graphics of the buffer image and (in the end) transfer the content
     522        // of the temporary buffer pixel by pixel onto g, without scaling.
     523        // (Otherwise, we would upscale a small buffer image and the result would be
     524        // blurry, with 2x2 pixel blocks.)
     525        Graphics2D gg = (Graphics2D) g;
     526        AffineTransform trOrig = gg.getTransform();
     527        double uiScaleX = gg.getTransform().getScaleX();
     528        double uiScaleY = gg.getTransform().getScaleY();
     529        // width/height in full-resolution screen pixels
     530        int width = (int) Math.round(getWidth() * uiScaleX);
     531        int height = (int) Math.round(getHeight() * uiScaleY);
     532        // This transformation corresponds to the original transformation of g,
     533        // except for the translation part. It will be applied to the temporary
     534        // buffer images.
     535        AffineTransform trDef = AffineTransform.getScaleInstance(uiScaleX, uiScaleY);
     536        // The goal is to create the temporary image at full pixel resolution,
     537        // so scale up the clip shape
     538        Shape scaledClip = trDef.createTransformedShape(g.getClip());
     539
    513540        List<Layer> visibleLayers = layerManager.getVisibleLayersInZOrder();
    514541
     
    529556                && nonChangedLayers.equals(visibleLayers.subList(0, nonChangedLayers.size()));
    530557
    531         if (null == offscreenBuffer || offscreenBuffer.getWidth() != getWidth() || offscreenBuffer.getHeight() != getHeight()) {
    532             offscreenBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_3BYTE_BGR);
    533         }
    534 
    535         Graphics2D tempG = offscreenBuffer.createGraphics();
    536         tempG.setClip(g.getClip());
     558        if (null == offscreenBuffer || offscreenBuffer.getWidth() != width || offscreenBuffer.getHeight() != height) {
     559            offscreenBuffer = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
     560        }
    537561
    538562        if (!canUseBuffer || nonChangedLayersBuffer == null) {
    539563            if (null == nonChangedLayersBuffer
    540                     || nonChangedLayersBuffer.getWidth() != getWidth() || nonChangedLayersBuffer.getHeight() != getHeight()) {
    541                 nonChangedLayersBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_3BYTE_BGR);
     564                    || nonChangedLayersBuffer.getWidth() != width || nonChangedLayersBuffer.getHeight() != height) {
     565                nonChangedLayersBuffer = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
    542566            }
    543567            Graphics2D g2 = nonChangedLayersBuffer.createGraphics();
    544             g2.setClip(g.getClip());
     568            g2.setClip(scaledClip);
     569            g2.setTransform(trDef);
    545570            g2.setColor(PaintColors.getBackgroundColor());
    546             g2.fillRect(0, 0, getWidth(), getHeight());
     571            g2.fillRect(0, 0, width, height);
    547572
    548573            for (int i = 0; i < nonChangedLayersCount; i++) {
     
    553578            if (nonChangedLayers.size() != nonChangedLayersCount) {
    554579                Graphics2D g2 = nonChangedLayersBuffer.createGraphics();
    555                 g2.setClip(g.getClip());
     580                g2.setClip(scaledClip);
     581                g2.setTransform(trDef);
    556582                for (int i = nonChangedLayers.size(); i < nonChangedLayersCount; i++) {
    557583                    paintLayer(visibleLayers.get(i), g2);
     
    565591        lastClipBounds = g.getClipBounds();
    566592
     593        Graphics2D tempG = offscreenBuffer.createGraphics();
     594        tempG.setClip(scaledClip);
     595        tempG.setTransform(new AffineTransform());
    567596        tempG.drawImage(nonChangedLayersBuffer, 0, 0, null);
     597        tempG.setTransform(trDef);
    568598
    569599        for (int i = nonChangedLayersCount; i < visibleLayers.size(); i++) {
     
    572602
    573603        try {
    574             drawTemporaryLayers(tempG, getLatLonBounds(g.getClipBounds()));
     604            drawTemporaryLayers(tempG, getLatLonBounds(new Rectangle(
     605                    (int) Math.round(g.getClipBounds().x * uiScaleX),
     606                    (int) Math.round(g.getClipBounds().y * uiScaleY))));
    575607        } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {
    576608            BugReport.intercept(e).put("temporaryLayers", temporaryLayers).warn();
     
    597629
    598630        try {
    599             g.drawImage(offscreenBuffer, 0, 0, null);
     631            gg.setTransform(new AffineTransform(1, 0, 0, 1, trOrig.getTranslateX(), trOrig.getTranslateY()));
     632            gg.drawImage(offscreenBuffer, 0, 0, null);
    600633        } catch (ClassCastException e) {
    601634            // See #11002 and duplicate tickets. On Linux with Java >= 8 Many users face this error here:
     
    623656            // But the application seems to work fine after, so let's just log the error
    624657            Logging.error(e);
     658        } finally {
     659            gg.setTransform(trOrig);
    625660        }
    626661    }
Note: See TracChangeset for help on using the changeset viewer.