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

Incorrect text rendering with fractional font metrics and transform

XMLWordPrintable

    • 2d
    • 11
    • x86_64
    • windows_10

      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


            prr Philip Race
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: