Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8156100

xrender: Subpixel drawing bug in Java 8

XMLWordPrintable

    • 2d
    • x86_64
    • linux_ubuntu

      FULL PRODUCT VERSION :


      ADDITIONAL OS VERSION INFORMATION :
      Linux 3.13.0-85-generic #129-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      When drawing (stroking) 1px line on a sub-pixel coordinates in Java 8, its coordinates are rounded up, but in Java 7 they were rounded down. Only affects 1px lines.

      Tried on early 1.8 version, 8u60 and 8u77.
      Doesn't reproduce on Windows/Mac.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      http://i.stack.imgur.com/6egcI.png
      ACTUAL -
      http://i.stack.imgur.com/pNJlB.png

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import static java.awt.BasicStroke.*;

      import java.awt.*;
      import java.awt.geom.*;

      import javax.swing.*;

      public class TestCase
      {
          public static void main(String[] args)
          {
              JFrame frame = new JFrame("Test case");
              frame.setSize(115, 115);
              frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

              frame.getContentPane().add(new TestPanel());

              frame.setVisible(true);
          }

          private static class TestPanel extends JPanel
          {
              TestPanel()
              {
                  setOpaque(true);
              }

              @Override
              protected void paintComponent(Graphics g)
              {
                  Graphics2D g2 = (Graphics2D) g;
                  g2.setColor(Color.white);
                  g2.fill(getBounds());

                  Rectangle2D rect = new Rectangle2D.Double();
                  Color background = new Color(0, 255, 255);
                  Color border = new Color(255, 0, 0, 128);
                  Stroke STROKE_1PX = new BasicStroke(1, CAP_SQUARE, JOIN_MITER);
                  Stroke STROKE_2PX = new BasicStroke(2, CAP_SQUARE, JOIN_MITER);
                  Stroke STROKE_3PX = new BasicStroke(3, CAP_SQUARE, JOIN_MITER);
                  g2.translate(10, 10);

                  /**
                   * Filling and stroking by original coordinates
                   */
                  rect.setRect(0, 0, 25, 25);
                  g2.setColor(background);
                  g2.fill(rect);
                  g2.setColor(border);
                  g2.setStroke(STROKE_1PX);
                  g2.draw(rect);
                  g2.translate(0, 35);
                  g2.setColor(background);
                  g2.fill(rect);
                  g2.setColor(border);
                  g2.setStroke(STROKE_2PX);
                  g2.draw(rect);
                  g2.translate(0, 35);
                  g2.setColor(background);
                  g2.fill(rect);
                  g2.setColor(border);
                  g2.setStroke(STROKE_3PX);
                  g2.draw(rect);

                  /**
                   * Stroking is shrunk to be inside the filling rect
                   */
                  g2.translate(35, -70);
                  rect.setRect(0, 0, 25, 25);
                  g2.setColor(background);
                  g2.fill(rect);
                  rect.setRect(0.5, 0.5, 24, 24);
                  g2.setColor(border);
                  g2.setStroke(STROKE_1PX);
                  g2.draw(rect);
                  g2.translate(0, 35);
                  rect.setRect(0, 0, 25, 25);
                  g2.setColor(background);
                  g2.fill(rect);
                  rect.setRect(1, 1, 23, 23);
                  g2.setColor(border);
                  g2.setStroke(STROKE_2PX);
                  g2.draw(rect);
                  g2.translate(0, 35);
                  rect.setRect(0, 0, 25, 25);
                  g2.setColor(background);
                  g2.fill(rect);
                  rect.setRect(1.5, 1.5, 22, 22);
                  g2.setColor(border);
                  g2.setStroke(STROKE_3PX);
                  g2.draw(rect);

                  /**
                   * Filling rect is additionally shrunk and centered
                   */
                  g2.translate(35, -70);
                  rect.setRect(0.5, 0.5, 24, 24);
                  g2.setColor(background);
                  g2.fill(rect);
                  g2.setColor(border);
                  g2.setStroke(STROKE_1PX);
                  g2.draw(rect);
                  g2.translate(0, 35);
                  rect.setRect(1, 1, 23, 23);
                  g2.setColor(background);
                  g2.fill(rect);
                  g2.setColor(border);
                  g2.setStroke(STROKE_2PX);
                  g2.draw(rect);
                  g2.translate(0, 35);
                  rect.setRect(1.5, 1.5, 22, 22);
                  g2.setColor(background);
                  g2.fill(rect);
                  g2.setColor(border);
                  g2.setStroke(STROKE_3PX);
                  g2.draw(rect);
              }
          }
      }
      ---------- END SOURCE ----------

            ceisserer Clemens Eisserer
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated: