Dims
Dims

Reputation: 51229

Java bug? Why draws rectangle instead of ellipse?

The code below draws rectangle and 2 ellipses.

enter image description here

While should draw 3 ellipses.

My OS is Windows 7 prof 64 bit

My Java is 1.6 x86 also 1.7 x64 tested.

Why?

package tests;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import net.miginfocom.swing.MigLayout;

public class AntialiacingScaleTester {

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {

                JPanel circlePanel = new JPanel() {
                    @Override
                    public void paintComponent(Graphics g) {

                        super.paintComponent(g);

                        Graphics2D g2d = (Graphics2D)g;
                        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                        g2d.setColor(Color.RED);
                        g2d.setStroke(new BasicStroke(1));
                        //g2d.drawOval(0, 0, 200, 200);
                        g2d.draw(new Ellipse2D.Double(0, 0, 200, 200));

                        AffineTransform old = g2d.getTransform();

                        g2d.setColor(Color.GREEN);
                        g2d.scale(1000, 1000);
                        g2d.setStroke(new BasicStroke(0.001f));
                        g2d.draw(new Ellipse2D.Double(0, 0, 0.225, 0.225));

                        g2d.setColor(Color.BLUE);
                        g2d.scale(10, 10);
                        g2d.setStroke(new BasicStroke(0.001f));
                        g2d.draw(new Ellipse2D.Double(0, 0, 0.025, 0.025));

                        g2d.setTransform(old);

                    }
                };

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


                //frame.setLayout(new MigLayout("fill"));
                //frame.add(circlePanel, "w 300, h 300, grow");

                //frame.add(circlePanel);

                frame.setLayout(null);
                circlePanel.setBounds(new Rectangle(0, 0, 300, 300));
                frame.add(circlePanel);

                frame.setBounds(0, 0, 350, 300);

                //frame.pack();
                frame.setVisible(true);

            }
        });

    }

}

Upvotes: 4

Views: 841

Answers (2)

dinox0r
dinox0r

Reputation: 16059

I copy/pasted your code and it drew the 2 ellipses you wrote about, the only change I made was to replace your MigLayout by null, set the frame and panel dimensions by hand and remove the frame.pack() invocation:

import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {
    /**
     * @param args
     */
    public static void main(String[] args) {
        JPanel circlePanel = new JPanel() {
            @Override
            public void paint(Graphics g) {

                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                g2d.setStroke(new BasicStroke(1));
                //g2d.drawOval(0, 0, 200, 200);
                g2d.draw(new Ellipse2D.Double(0, 0, 200, 200));

                AffineTransform old = g2d.getTransform();

                g2d.scale(10000, 10000);
                g2d.setStroke(new BasicStroke(0.001f));
                g2d.draw(new Ellipse2D.Double(0, 0, 0.025, 0.025));

                g2d.setTransform(old);

            }
        };

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setLayout(null);
        circlePanel.setBounds(new Rectangle(0, 0, 300, 300));
        frame.add(circlePanel);

        frame.setBounds(0, 0, 350, 300);

        //frame.pack();
        frame.setVisible(true);
    }
}

enter image description here

Update: Could reproduce the problem using the Oracle JDK (java version "1.8.0-ea") instead of the OpenJDK. Got the diamond shape, as pointed out in another answers, the scale factor is the root cause of the shape degenaration, don't know if that should be the appropiate behaviour though, so, there must be a bug in one these JRE's. The following test program works fine for both JRE's:

import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {
    /**
     * @param args
     */
    public static void main(String[] args) {
        JPanel circlePanel = new JPanel() {
            @Override
            public void paint(Graphics g) {

                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                g2d.setStroke(new BasicStroke(1));
                //g2d.drawOval(0, 0, 200, 200);
                g2d.draw(new Ellipse2D.Double(0, 0, 200, 200));

                AffineTransform old = g2d.getTransform();

                g2d.scale(10, 10);
                g2d.setStroke(new BasicStroke(1.0f));
                g2d.draw(new Ellipse2D.Double(0, 0, 25.0, 25.0));

                g2d.setTransform(old);

            }
        };

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setLayout(null);
        circlePanel.setBounds(new Rectangle(0, 0, 300, 300));
        frame.add(circlePanel);

        frame.setBounds(0, 0, 350, 300);

        //frame.pack();
        frame.setVisible(true);
    }
}

Upvotes: 2

Philip Whitehouse
Philip Whitehouse

Reputation: 4157

Replicated on Java 7, Windows 7 in Eclipse, removing the Layout Manager.

My feeling is that it's due to the combination of the high scaling and inaccuracies at small floating point values, reducing the number of points generated.

If you substitute values you find between 0.0363 and 0.0362 the rendering API breaks. It no longer generates an Arc, but instead a square.

The work-around is to stop combining the huge scaling with tiny sized objects. Scale down and increase the size.

Upvotes: 1

Related Questions