-
Bug
-
Resolution: Fixed
-
P3
-
11
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8205775 | 11.0.1 | Philip Race | P3 | Resolved | Fixed | team |
JDK-8225334 | openjdk8u222 | Philip Race | P3 | Resolved | Fixed | b05 |
A DESCRIPTION OF THE PROBLEM :
Our application programs are rendering rotated string images using Graphics2D#rotate() method.
Running these applications with Java 11, the bounding box of text is properly rotated but each characters included in the string are not rotated and inproperly layouted, so we can't read the text from displayed rendering image.
In addition, the situation seems to be different depending on the font used. With Japanese fonts installed in Windows, this problem is always occured.
REGRESSION : Last worked in version 11
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile attached source code.
2. Change the rotating degrees using JSlider on the north of the JFrame.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
We expect the same rendering with Java 8, 9, 10. With older versions from 11, the whole rendering image of text are properly rotated.
ACTUAL -
The bounding box of text is properly rotated but each characters included in the string are not rotated and inproperly layouted, so we can't read the text from displayed rendering image.
---------- BEGIN SOURCE ----------
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class DrawRotateText {
private static final String TEXT =
"OS[" + System.getProperty("os.name") +
"], Java[" +
System.getProperty("java.version") +
"], text[ããã¹ãå転]";
private static final Color BACKGROUND_COLOR = Color.white;
private static final Color LINE_COLOR = new Color(0,0,255,60);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
// set Windows Look & Feel
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
JPanel content = new JPanel();
content.setLayout(new BorderLayout());
final MyComponent comp = new MyComponent();
// final MyLabel comp = new MyLabel();
content.add(comp, BorderLayout.CENTER);
JSlider slider = new JSlider();
slider.setMinimum(0);
slider.setMaximum(360);
slider.setValue(0);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
comp.setDegree(slider.getValue());
}
});
content.add(slider, BorderLayout.NORTH);
comp.setPreferredSize(new Dimension(500,500));
frame.setContentPane(content);
frame.pack();
frame.setVisible(true);
}
});
}
public static class MyComponent extends JComponent {
private int degree;
public void setDegree(int degree) {
this.degree = degree;
repaint();
}
public int getDegree() {
return this.degree;
}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g.create();
g2d.setColor(BACKGROUND_COLOR);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(getForeground());
Font font = getFont();
FontMetrics fm = getFontMetrics(font);
g2d.drawString(font2string(font), 0, getHeight()-(fm.getDescent()+fm.getLeading()));
g2d.setColor(LINE_COLOR);
g2d.drawLine(0, getHeight()/2, getWidth(), getHeight()/2);
g2d.drawLine(getWidth()/2, 0, getWidth()/2, getHeight());
double theta = (2 * Math.PI * degree) / 360;
g2d.rotate(theta, getWidth()/2, getHeight()/2);
g2d.setColor(getForeground());
g2d.drawString(TEXT, (getWidth()-fm.stringWidth(TEXT))/2, (getHeight()+fm.getAscent())/2);
g2d.dispose();
}
}
public static class MyLabel extends JLabel {
private int degree;
public MyLabel() {
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
setText(TEXT);
}
public void setDegree(int degree) {
this.degree = degree;
repaint();
}
public int getDegree() {
return this.degree;
}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g.create();
g2d.setColor(BACKGROUND_COLOR);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(getForeground());
Font font = getFont();
FontMetrics fm = getFontMetrics(font);
g2d.drawString(font2string(font), 0, getHeight()-(fm.getDescent()+fm.getLeading()));
g2d.setColor(LINE_COLOR);
g2d.drawLine(0, getHeight()/2, getWidth(), getHeight()/2);
g2d.drawLine(getWidth()/2, 0, getWidth()/2, getHeight());
double theta = (2 * Math.PI * degree) / 360;
g2d.rotate(theta, getWidth()/2, getHeight()/2);
g2d.setColor(getForeground());
super.paintComponent(g2d);
g2d.dispose();
}
}
private static String font2string(Font font) {
StringBuilder sb = new StringBuilder();
sb.append("Font[family=");
sb.append(font.getFamily());
sb.append(",name=");
sb.append(font.getFontName());
sb.append(",style=");
if(font.isBold() && font.isItalic()) {
sb.append("bold+italic");
} else if(font.isBold()) {
sb.append("bold");
} else if(font.isItalic()) {
sb.append("italic");
} else {
sb.append("plain");
}
sb.append(",size=");
sb.append(font.getSize());
sb.append("]");
return sb.toString();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
No workaround
FREQUENCY : always
Our application programs are rendering rotated string images using Graphics2D#rotate() method.
Running these applications with Java 11, the bounding box of text is properly rotated but each characters included in the string are not rotated and inproperly layouted, so we can't read the text from displayed rendering image.
In addition, the situation seems to be different depending on the font used. With Japanese fonts installed in Windows, this problem is always occured.
REGRESSION : Last worked in version 11
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile attached source code.
2. Change the rotating degrees using JSlider on the north of the JFrame.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
We expect the same rendering with Java 8, 9, 10. With older versions from 11, the whole rendering image of text are properly rotated.
ACTUAL -
The bounding box of text is properly rotated but each characters included in the string are not rotated and inproperly layouted, so we can't read the text from displayed rendering image.
---------- BEGIN SOURCE ----------
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class DrawRotateText {
private static final String TEXT =
"OS[" + System.getProperty("os.name") +
"], Java[" +
System.getProperty("java.version") +
"], text[ããã¹ãå転]";
private static final Color BACKGROUND_COLOR = Color.white;
private static final Color LINE_COLOR = new Color(0,0,255,60);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
// set Windows Look & Feel
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
JPanel content = new JPanel();
content.setLayout(new BorderLayout());
final MyComponent comp = new MyComponent();
// final MyLabel comp = new MyLabel();
content.add(comp, BorderLayout.CENTER);
JSlider slider = new JSlider();
slider.setMinimum(0);
slider.setMaximum(360);
slider.setValue(0);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
comp.setDegree(slider.getValue());
}
});
content.add(slider, BorderLayout.NORTH);
comp.setPreferredSize(new Dimension(500,500));
frame.setContentPane(content);
frame.pack();
frame.setVisible(true);
}
});
}
public static class MyComponent extends JComponent {
private int degree;
public void setDegree(int degree) {
this.degree = degree;
repaint();
}
public int getDegree() {
return this.degree;
}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g.create();
g2d.setColor(BACKGROUND_COLOR);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(getForeground());
Font font = getFont();
FontMetrics fm = getFontMetrics(font);
g2d.drawString(font2string(font), 0, getHeight()-(fm.getDescent()+fm.getLeading()));
g2d.setColor(LINE_COLOR);
g2d.drawLine(0, getHeight()/2, getWidth(), getHeight()/2);
g2d.drawLine(getWidth()/2, 0, getWidth()/2, getHeight());
double theta = (2 * Math.PI * degree) / 360;
g2d.rotate(theta, getWidth()/2, getHeight()/2);
g2d.setColor(getForeground());
g2d.drawString(TEXT, (getWidth()-fm.stringWidth(TEXT))/2, (getHeight()+fm.getAscent())/2);
g2d.dispose();
}
}
public static class MyLabel extends JLabel {
private int degree;
public MyLabel() {
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
setText(TEXT);
}
public void setDegree(int degree) {
this.degree = degree;
repaint();
}
public int getDegree() {
return this.degree;
}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g.create();
g2d.setColor(BACKGROUND_COLOR);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(getForeground());
Font font = getFont();
FontMetrics fm = getFontMetrics(font);
g2d.drawString(font2string(font), 0, getHeight()-(fm.getDescent()+fm.getLeading()));
g2d.setColor(LINE_COLOR);
g2d.drawLine(0, getHeight()/2, getWidth(), getHeight()/2);
g2d.drawLine(getWidth()/2, 0, getWidth()/2, getHeight());
double theta = (2 * Math.PI * degree) / 360;
g2d.rotate(theta, getWidth()/2, getHeight()/2);
g2d.setColor(getForeground());
super.paintComponent(g2d);
g2d.dispose();
}
}
private static String font2string(Font font) {
StringBuilder sb = new StringBuilder();
sb.append("Font[family=");
sb.append(font.getFamily());
sb.append(",name=");
sb.append(font.getFontName());
sb.append(",style=");
if(font.isBold() && font.isItalic()) {
sb.append("bold+italic");
} else if(font.isBold()) {
sb.append("bold");
} else if(font.isItalic()) {
sb.append("italic");
} else {
sb.append("plain");
}
sb.append(",size=");
sb.append(font.getSize());
sb.append("]");
return sb.toString();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
No workaround
FREQUENCY : always
- backported by
-
JDK-8205775 Fonts with embedded bitmaps are not always rotated
- Resolved
-
JDK-8225334 Fonts with embedded bitmaps are not always rotated
- Resolved
- duplicates
-
JDK-8205203 Rotated Japanese characters are drawn upright
- Closed
-
JDK-8163278 OpenJDK can't support render text with rotation for DBCS fonts
- Closed
- relates to
-
JDK-8335247 Cannot embolden u11BC accent in gulim.ttc fonts
- Open
-
JDK-8312555 Ideographic characters aren't stretched by AffineTransform.scale(2, 1)
- Resolved
(1 relates to)