[OpenJDK 2D-Dev] HiDPI support issues on Windows

Anton Tarasov anton.tarasov at jetbrains.com
Tue Oct 4 20:46:25 UTC 2016


On 10/4/2016 11:30 PM, Jim Graham wrote:
> I wasn't familiar with the test code for this particular case.  Is it 
> in a bug report somewhere?
Jim, I'm re-attaching it (it was in my first e-mail).

Thanks,
Anton.

>
>             ...jim
>
> On 10/4/16 1:01 PM, Anton Tarasov wrote:
>> Also, the problem with primitives rendering 
>> (http://cr.openjdk.java.net/%7Eant/hidpi_pics/Scaling-150-percent.png) 
>> is
>> still there. But it seems to relate to line-thikness 
>> (border-thickness) rounding inaccuracy. What we can do with that?...

-------------- next part --------------
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package testscalingrectangles;

import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
import javax.swing.border.LineBorder;

public class MinimalSwingApplication {
    public static void main(String[] args) {
        MinimalSwingApplication app = new MinimalSwingApplication();
        app.buildAndDisplayGui();
    }

    private void buildAndDisplayGui(){
        JFrame frame = new JFrame("Test Frame");
        frame.setPreferredSize(new Dimension(240, 120));
        buildContent(frame);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
        frame.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentMoved(ComponentEvent e) {
                frame.repaint();
            }
        });
    }

    private void buildContent(JFrame aFrame){
        JButton repaintButton = new JButton();
        repaintButton.setText("Repaint");
        repaintButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                aFrame.repaint();
            }
        });

        JLabel scaleFactorLabel = new JLabel();
        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.LINE_AXIS));
        topPanel.add(new JLabel());
        topPanel.add(Box.createHorizontalGlue());
        topPanel.add(scaleFactorLabel);
        topPanel.add(Box.createHorizontalGlue());
        topPanel.add(new JLabel());

        JPanel panel = new JPanel(new BorderLayout());
        panel.add(topPanel, BorderLayout.NORTH);
        panel.add(new MyPanel(scaleFactorLabel), BorderLayout.CENTER);
        panel.add(repaintButton, BorderLayout.SOUTH);
        aFrame.getContentPane().add(panel);
    }

    private class MyPanel extends JPanel {
        private JLabel myLabel;

        public MyPanel(JLabel label) {
            super();
            myLabel = label;

            setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
            setBorder(new LineBorder(Color.BLUE, 2));

            Map<RenderingHints.Key,Object> renderingHints1 = new HashMap<>();
            renderingHints1.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
            add(new MyPaintRectPanel(renderingHints1));

            Map<RenderingHints.Key,Object> renderingHints2 = new HashMap<>();
            renderingHints1.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            add(new MyPaintRectPanel(renderingHints2));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (g instanceof Graphics2D) {
                Graphics2D g2d = (Graphics2D)g;
                myLabel.setText("Scale=" + (int)(g2d.getTransform().getScaleX() * 100) + "%");
            }

//            int wRect = 5;
//            int hRect = 5;
//            int xRect0 = this.getSize().width / 2 - wRect;
//            int yRect0 = this.getSize().height / 2 - hRect;
//            int xRect1 = xRect0 + wRect + 1;
//            int yRect1 = yRect0 + hRect + 1;
            //myLabel2.setText("X=" + xRect0 + ", Y= " + yRect0);
        }
    }

    private class MyPaintRectPanel extends JPanel {
        private Map<RenderingHints.Key, ?> myRenderingHints;

        public MyPaintRectPanel(Map<RenderingHints.Key, Object> renderingHints) {
            myRenderingHints = renderingHints;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (g instanceof Graphics2D) {
                Graphics2D g2d = (Graphics2D)g;
                for (RenderingHints.Key key : myRenderingHints.keySet()) {
                    g2d.setRenderingHint(key, myRenderingHints.get(key));
                }
                //((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                //g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
                //g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            }

            int wRect = 5;
            int hRect = 5;

            int xRect0 = this.getSize().width / 2 - wRect;
            int yRect0 = this.getSize().height / 2 - hRect;

            int xRect1 = xRect0 + wRect + 1;
            int yRect1 = yRect0 + hRect + 1;

            //myLabel.setText("X=" + xRect0 + ", Y= " + yRect0);

            // Fill the background as RED to illustrate the problem. We are filling
            // a red rectangle of size (0, 0, w, h * 2 + 1)
            // This happens` because of the way rounding works in the default transform.
            // From a API perspective, you would not expect any "red" to remain, since
            // we cover it up
            g.setColor(Color.RED);
            g.fillRect(xRect0, yRect0, wRect * 2 + 1, hRect * 2 + 1);

            // Draw 4 rectangles
            g.setColor(Color.PINK);
            g.fillRect(xRect0, yRect0, wRect, hRect);
            g.fillRect(xRect1, yRect0, wRect, hRect);
            g.fillRect(xRect0, yRect1, wRect, hRect);
            g.fillRect(xRect1, yRect1, wRect, hRect);

            // Draw borders of 4 rectangles
            g.setColor(Color.GREEN);
            g.drawRect(xRect0, yRect0, wRect - 1, hRect - 1);
            g.drawRect(xRect1, yRect0, wRect - 1, hRect - 1);
            g.drawRect(xRect0, yRect1, wRect - 1, hRect - 1);
            g.drawRect(xRect1, yRect1, wRect - 1, hRect - 1);

            // Draw horiz/vert lines in the middle of the 4 rectangles
            g.setColor(Color.BLUE);
            int xMiddle = xRect1 - 1;
            int yMiddle = yRect1 - 1;
            g.drawLine(xRect0, yMiddle, xRect0 + wRect * 2, yMiddle);
            g.drawLine(xMiddle, yRect0, xMiddle, yRect0 + hRect * 2);
        }
    }
}


More information about the 2d-dev mailing list