JDK-8214536 : Incorrect text rendering with fractional font metrics and transform
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 11,12
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2018-11-27
  • Updated: 2018-12-09
  • Resolved: 2018-12-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 13
13Resolved
Related Reports
Duplicate :  
Description
ADDITIONAL SYSTEM INFORMATION :
Windows 10
Ubuntu 16.04

A DESCRIPTION OF THE PROBLEM :
Text that is transformed with a non-translating transform is rendered incorrectly if RenderingHints.KEY_FRACTIONALMETRICS has been set to RenderingHints.VALUE_FRACTIONALMETRICS_ON.

REGRESSION : Last worked in version 10.0.2

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached test case with Java 11 or Java 11.0.1.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The text rendered with fractional font metrics should be transformed in the same way as the text rendered without fractional font metrics.
ACTUAL -
The text rendered with fractional font metrics is incorrectly "distorted".

---------- BEGIN SOURCE ----------
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * Demonstrates transformed text rendering with fractional font metrics.
 */
public class TextTransformationTest {
  private TextTransformationTest() {
  }

  public static void main( String[] args ) {
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        (new TextTransformationTest()).start();
      }
    });
  }

  void start() {
    final JPanel contentPane = new JPanel(new GridLayout(1, 1));
    contentPane.setPreferredSize(new Dimension(1024, 768));
    contentPane.add(new IsometricTextPane());

    final JFrame frame = new JFrame(TextTransformationTest.class.getName());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(contentPane);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }

  private static final class IsometricTextPane extends JComponent {
    public IsometricTextPane() {
      setForeground(Color.BLACK);
    }

    protected void paintComponent( final Graphics g ) {
      super.paintComponent(g);

      final int w = getWidth();
      final int h = getHeight();
      double anchorX = w * 0.33;
      double anchorY = h * 0.33;


      // produces the correct result
      final Graphics2D gfx1 = (Graphics2D) g.create();
      anchorX += drawText(gfx1, anchorX, anchorY) + 50;
      gfx1.dispose();


      // produces an incorrect result
      final Graphics2D gfx2 = (Graphics2D) g.create();
      gfx2.setRenderingHint(
              RenderingHints.KEY_FRACTIONALMETRICS,
              RenderingHints.VALUE_FRACTIONALMETRICS_ON);
      drawText(gfx2, anchorX, anchorY);
      gfx2.dispose();
    }

    private double drawText( final Graphics2D gfx, final double x, final double y ) {
      final String text = "Sample text";

      gfx.translate(x, y);
      gfx.transform(new AffineTransform(new double[]{0.87, 0.5, 0, 1}));
      gfx.translate(-x, -y);

      gfx.setFont(getFont());
      gfx.setColor(getForeground());

      gfx.drawString(text, (float) x, (float) y);

      final FontMetrics fm = gfx.getFontMetrics();
      final int asc = fm.getMaxAscent();
      final int dsc = fm.getMaxDescent();
      gfx.draw(new Line2D.Double(x, y - asc, x + 100, y - asc));
      gfx.draw(new Line2D.Double(x, y + dsc, x + 100, y + dsc));

      return fm.stringWidth(text);
    }
  }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
There is no workaround if fractional font metrics are needed.

FREQUENCY : always



Comments
This looks to me like a duplicate of https://bugs.openjdk.java.net/browse/JDK-8199537
09-12-2018

Reported as regression in JDK 11 where Text that is transformed with a non-translating transform is rendered incorrectly if RenderingHints.KEY_FRACTIONALMETRICS has been set to RenderingHints.VALUE_FRACTIONALMETRICS_ON. When checked with reported versions could confirm the issue. See attached screenshot as reference. Results: 10.0.2: OK 11: Fail 12 ea b21: Fail To verify, run the attached test case with respective JDK versions.
30-11-2018