Hello Rory, For information, I submitted this question on Swing-dev , I am not sure it is the right list, if so hope you can help.
Regards Philippe ---------- Forwarded message ---------- From: Philippe Mouawad <[email protected]> Date: Wed, Nov 19, 2014 at 3:34 PM Subject: JAVA8u20 and JAVA8u25 Regression in Graphics2D drawing of derived Fonts ? To: [email protected] Hello, We had recently a report of a bug on Apache JMeter: - https://issues.apache.org/bugzilla/show_bug.cgi?id=57221 The bug only occurs on Java 8 (u20 and u25). We use jCharts library. I narrowed the bug and it seems to come from the way derived fonts are drawn: Library uses: public static final AffineTransform VERTICAL_ROTATION = AffineTransform.getRotateInstance( -Math.PI / 2 ); Then this.affineTransform= VERTICAL_ROTATION; this.font.deriveFont( this.affineTransform ) So I build a stupid and ugly isolated class to show issue, run it on Java 7 display is fine , run it on Java8 result is strange. package org.jCharts; 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); } } Regards Philippe M. -- Cordialement. Philippe Mouawad. -- Cordialement. Philippe Mouawad.
