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

[macosx] jdk8, jdk7u60 Regression in Graphics2D drawing of derived Fonts

    Details

    • Subcomponent:
      2d
    • Resolved In Build:
      b45
    • CPU:
      x86
    • OS:
      os_x

      Backports

        Description

        FULL PRODUCT VERSION :
        java version "1.8.0_25"
        Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
        Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Mac OSX 10.9.5

        A DESCRIPTION OF THE PROBLEM :
        Rotating text is broken when using Font#deriveFont to draw String.
        See sample.
        It seems regression appeared after Java 7 u40.
        It affects currently Apache JMeter project, see:
        https://issues.apache.org/bugzilla/show_bug.cgi?id=57221

        Thanks for help

        ADDITIONAL REGRESSION INFORMATION:
        java version "1.8.0_25"
        Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
        Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Run on Java 7u40, you get a Frame with correclty drawn text
        Run it with Java8 or Java7u71, you get a strange rotation of characters

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Correct rotation of text
        ACTUAL -
        Strange rotation of text which does not comply with previous behaviour

        ERROR MESSAGES/STACK TRACES THAT OCCUR :
        No error message

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------

        import java.awt.Color;
        import java.awt.Dimension;
        import java.awt.Font;
        import java.awt.Graphics;
        import java.awt.Graphics2D;
        import java.awt.RenderingHints;
        import java.awt.font.FontRenderContext;
        import java.awt.font.LineMetrics;
        import java.awt.geom.AffineTransform;
        import java.awt.geom.GeneralPath;
        import java.awt.geom.Rectangle2D;

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

        public class Test extends JPanel {
            Rectangle2D.Float rect = new Rectangle2D.Float(200, 200, 220, 35);
            // float theta = 1.1748778437843f;
            double theta = Math.PI / 6;

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
                g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
                        RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
                        RenderingHints.VALUE_STROKE_PURE);
                g2.setPaint(Color.blue);
                Font font = g2.getFont().deriveFont(18f);
                g2.setFont(font);
                FontRenderContext frc = g2.getFontRenderContext();
                String s = "This text should be rotated";
                float width = (float) font.getStringBounds(s, frc).getWidth();
                LineMetrics lm = font.getLineMetrics(s, frc);
                float height = lm.getAscent() + lm.getDescent();
                // Scale text into rect.
                float xScale = rect.width / width;
                float yScale = rect.height / height;
                float scale = (xScale > yScale) ? yScale : xScale;
                // Locate string origin.
                double x = rect.x;
                double y = rect.y + (rect.height + scale * height) / 2 - scale
                        * lm.getDescent();
                AffineTransform at = AffineTransform.getTranslateInstance(x, y);
                at.scale(scale, scale);
                AffineTransform rotator = new AffineTransform();
                rotator.rotate(theta, rect.getCenterX(), rect.getCenterY());
                GeneralPath rect2 = new GeneralPath(
                        rotator.createTransformedShape(rect));
                // Draw with no rotation.
                g2.draw(rect);
                g2.setPaint(Color.red);
                g2.setFont(font.deriveFont(at));
                g2.drawString(s, 0, 0);
                // Rotate once.
                g2.setPaint(Color.blue);
                g2.draw(rect2);
                rotator.concatenate(at);
                g2.setFont(font.deriveFont(rotator));
                g2.setPaint(Color.red);
                g2.drawString(s, 0, 0);
                // Rotate again.
                rotator.setToIdentity();
                rotator.rotate(2 * theta, rect.getCenterX(), rect.getCenterY());
                rect2 = new GeneralPath(rotator.createTransformedShape(rect));
                g2.setPaint(Color.blue);
                g2.draw(rect2);
                rotator.concatenate(at);
                g2.setFont(font.deriveFont(rotator));
                g2.setPaint(Color.red);
                g2.drawString(s, 0, 0);
                // Check scaled string bounds.
                // this was handled by the fractional metrics rendering hint
            }

            public static void main(String[] args) {
                Test test = new Test();
                test.setPreferredSize(new Dimension(800, 600));
                JFrame f = new JFrame();
                f.getContentPane().add(test);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.pack();
                f.setVisible(true);
            }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        None found

          Issue Links

            Activity

            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk9/client/jdk/rev/5d13458da243
            User: serb
            Date: 2014-12-16 19:47:03 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/client/jdk/rev/5d13458da243 User: serb Date: 2014-12-16 19:47:03 +0000
            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/5d13458da243
            User: lana
            Date: 2014-12-30 21:55:54 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/5d13458da243 User: lana Date: 2014-12-30 21:55:54 +0000
            Hide
            serb Sergey Bylokhov added a comment -
            CPU15_02-critical-request:
            issue impact: Rotated text is drawn in the wrong direction.
            Fix rational: regression, which was introduced in jdk7/8/9
            Suggested testing: jck, regression, functional testing in fonts & 2d area.
            Webrev can be found at: http://cr.openjdk.java.net/~serb/8065373/webrev.00
            jdk9 changeset: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/5d13458da243
            Review: http://mail.openjdk.java.net/pipermail/2d-dev/2014-December/004972.html
            Reviewers: Phil Race, Andrew Brygin
            Show
            serb Sergey Bylokhov added a comment - CPU15_02-critical-request: issue impact: Rotated text is drawn in the wrong direction. Fix rational: regression, which was introduced in jdk7/8/9 Suggested testing: jck, regression, functional testing in fonts & 2d area. Webrev can be found at: http://cr.openjdk.java.net/~serb/8065373/webrev.00 jdk9 changeset: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/5d13458da243 Review: http://mail.openjdk.java.net/pipermail/2d-dev/2014-December/004972.html Reviewers: Phil Race, Andrew Brygin
            Hide
            afomin Alexander Fomin added a comment -
            The issue affects jdk7.
            What about the backport to 7?
            SQE OK to take the fix into CPU15_02.
            Show
            afomin Alexander Fomin added a comment - The issue affects jdk7. What about the backport to 7? SQE OK to take the fix into CPU15_02.
            Hide
            serb Sergey Bylokhov added a comment -
            There is no jdk7u-dev, so I need an approval to push the fix to jdk7u-cpu directly

            Lana Steuck:
            "Please note that 7u-dev is now completely closed. If you accidentally push anything there - it won't get integrated.
            After today's deadline, if you have a fix for 7u80, it should go via the approval process for critical fixes and push your fix into 7u80 (all in closed).
            There won't be 7u80-dev for 7u80."
            Show
            serb Sergey Bylokhov added a comment - There is no jdk7u-dev, so I need an approval to push the fix to jdk7u-cpu directly Lana Steuck: "Please note that 7u-dev is now completely closed. If you accidentally push anything there - it won't get integrated. After today's deadline, if you have a fix for 7u80, it should go via the approval process for critical fixes and push your fix into 7u80 (all in closed). There won't be 7u80-dev for 7u80."

              People

              • Assignee:
                serb Sergey Bylokhov
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                7 Start watching this issue

                Dates

                • Due:
                  Created:
                  Updated:
                  Resolved: