阿拉伯语中的某些单词在 Swing 中显示为书法
Some words in Arabic appear calligraphic in Swing
似乎 Swing 自动修饰了一些阿拉伯语单词,使它们看起来像某种书法。其中一个词是穆罕默德,在阿拉伯语中拼写为 محمد。
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class TestProject extends JFrame {
public static void main(String[] args) {
TestProject frame = new TestProject();
frame.setVisible(true);
}
public TestProject() {
this.setSize(200, 100);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("محمد");
label.setFont(new Font("Arial", Font.BOLD, 28));
this.add(label);
}
}
该问题至少适用于所有广泛使用的字体。
我正在使用 Windows 10 & Java 8。我在另一台 PC 上尝试过相同的程序(也是 Windows 10)同样的问题。
我们怎样才能禁用它?
(注意:我不懂阿拉伯语。)
似乎与字体有关
默认情况下,我没有看到您的屏幕截图中显示的更长的表示(3 个字?)。
- 当我用文本
"محمد"
编写一个最小的 Swing 应用程序时,我得到了你想要的那个短字符串(4 个字符?)。
- 当使用特定字体时,我确实得到了我未经训练的眼睛看起来是你试图避免的书法渲染。
请注意,我的字符串不是您的字符串。我从 Google T运行slate, t运行slating Muhammad
复制了你的问题。
https://translate.google.com/?sl=en&tl=ar&text=Muhammad%0A&op=translate
我只用 JLabel
编写了这个最小的 Swing 应用程序,仅通过增加字体大小来增强。
package work.basil.example;
import javax.swing.*;
import java.awt.*;
/**
* Hello world!
*/
public class App {
public static void main ( String[] args ) {
System.out.println( Runtime.version() );
javax.swing.SwingUtilities.invokeLater( () -> createAndShowGUI() );
}
private static void createAndShowGUI () {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated( true );
//Create and set up the window.
JFrame frame = new JFrame( "Test Arabic rendering" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
//Add the ubiquitous "Hello World" label.
JLabel label = new JLabel( "محمد" );
label.setFont( new Font( label.getFont().getName() , label.getFont().getStyle() , 40 ) ); // Override default font size.
System.out.println( "Font name: " + label.getFont().getName() + " | " + "Font style: " + label.getFont().getStyle() );
frame.getContentPane().add( label );
//Display the window.
frame.pack();
frame.setVisible( true );
}
}
当 运行 在我的 MacBook Pro(13 英寸,M1,2020 年)、Apple Silicon(不是英特尔)、16 GB 内存上时。 OS 是 macOS Big Sur,11.5.1。使用来自 this page.
的 Java 17 (17+35-2724) 的早期访问版本
(顺便说一句,这是您应该随问题一起发布的 MCVE 类型。)
我的字体查询结果是:
Font name: Lucida Grande | Font style: 0
… 但我怀疑这是 JLabel
小部件的默认字体,而不是用于呈现这些阿拉伯字符的实际字体。我依稀记得,最新版本的 macOS 包含丰富的各种专用于阿拉伯语的字体。请参阅:Fonts included with macOS Big Sur for three lists: fonts included, fonts available for download, and older fonts available for document support. Using the Font Book app bundled with macOS, and defining a "smart collection" where languages include Arabic, I get a list of 32 such fonts installed by default in macOS Big Sur. (The four items for Pragmata Pro 不适用 — 这是我购买的商业字体,我强烈推荐给开发人员。)
我运行这个修改版本的代码来自在同一台macOS上面描述的Big Sur。
package work.basil.text;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
public class TestProject extends JFrame {
public static void main ( String[] args ) {
TestProject frame = new TestProject();
frame.setVisible( true );
}
public TestProject () {
this.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
this.setLayout( new FlowLayout() );
String input = "محمد";
String[] fontFamilies = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for ( String fontFamily : fontFamilies ) {
Font font = new Font( fontFamily , Font.PLAIN , 40 );
if ( font.canDisplayUpTo( input ) < 0 ) {
JLabel label = new JLabel( input );
label.setFont( font );
label.setBorder( new TitledBorder( fontFamily ) );
this.add( label );
}
}
this.pack();
}
}
这是结果的屏幕截图。
尝试 运行 下面的代码。它在我安装的字体范围内生成了这张图片。
另请注意,Arial(一种无衬线或未装饰字体)的阿拉伯字形似乎默认为 Times New Roman(一种衬线或装饰字体)。这是字体(或系统,不确定)经常做的事情,当用衬线字体替换无衬线字体时,它会产生相当奇怪的渲染。
另请注意,此系统安装了 255 种字体,但其中只有 23 种支持阿拉伯字符。
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class TestProject extends JFrame {
public static void main(String[] args) {
TestProject frame = new TestProject();
frame.setVisible(true);
}
public TestProject() {
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel p = new JPanel(new GridLayout(0, 5));
String arabic = "محمد";
String[] fontFamilies = GraphicsEnvironment.
getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for (String fontFamily : fontFamilies) {
Font font = new Font(fontFamily, Font.PLAIN, 25);
if (font.canDisplayUpTo(arabic) < 0) {
JLabel label = new JLabel(arabic);
label.setFont(font);
label.setBorder(new TitledBorder(fontFamily));
p.add(label);
}
}
this.add(new JScrollPane(p));
this.pack();
}
}
这似乎是旧的(即最多 Java 8)字体渲染引擎中的错误。
这是 Java 8 在我的机器上的样子:
这是 Java9 的结果:
我不知道是否针对此特定问题报告了明确的错误报告。但是由于 JEP 258: HarfBuzz Font-Layout Engine.
,字体引擎已被完全替换
Replace the existing ICU OpenType font-layout engine with HarfBuzz.
因此旧字体渲染的错误消失也就不足为奇了。
似乎 Swing 自动修饰了一些阿拉伯语单词,使它们看起来像某种书法。其中一个词是穆罕默德,在阿拉伯语中拼写为 محمد。
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class TestProject extends JFrame {
public static void main(String[] args) {
TestProject frame = new TestProject();
frame.setVisible(true);
}
public TestProject() {
this.setSize(200, 100);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("محمد");
label.setFont(new Font("Arial", Font.BOLD, 28));
this.add(label);
}
}
该问题至少适用于所有广泛使用的字体。
我正在使用 Windows 10 & Java 8。我在另一台 PC 上尝试过相同的程序(也是 Windows 10)同样的问题。
我们怎样才能禁用它?
(注意:我不懂阿拉伯语。)
似乎与字体有关
默认情况下,我没有看到您的屏幕截图中显示的更长的表示(3 个字?)。
- 当我用文本
"محمد"
编写一个最小的 Swing 应用程序时,我得到了你想要的那个短字符串(4 个字符?)。 - 当使用特定字体时,我确实得到了我未经训练的眼睛看起来是你试图避免的书法渲染。
请注意,我的字符串不是您的字符串。我从 Google T运行slate, t运行slating Muhammad
复制了你的问题。
https://translate.google.com/?sl=en&tl=ar&text=Muhammad%0A&op=translate
我只用 JLabel
编写了这个最小的 Swing 应用程序,仅通过增加字体大小来增强。
package work.basil.example;
import javax.swing.*;
import java.awt.*;
/**
* Hello world!
*/
public class App {
public static void main ( String[] args ) {
System.out.println( Runtime.version() );
javax.swing.SwingUtilities.invokeLater( () -> createAndShowGUI() );
}
private static void createAndShowGUI () {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated( true );
//Create and set up the window.
JFrame frame = new JFrame( "Test Arabic rendering" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
//Add the ubiquitous "Hello World" label.
JLabel label = new JLabel( "محمد" );
label.setFont( new Font( label.getFont().getName() , label.getFont().getStyle() , 40 ) ); // Override default font size.
System.out.println( "Font name: " + label.getFont().getName() + " | " + "Font style: " + label.getFont().getStyle() );
frame.getContentPane().add( label );
//Display the window.
frame.pack();
frame.setVisible( true );
}
}
当 运行 在我的 MacBook Pro(13 英寸,M1,2020 年)、Apple Silicon(不是英特尔)、16 GB 内存上时。 OS 是 macOS Big Sur,11.5.1。使用来自 this page.
的 Java 17 (17+35-2724) 的早期访问版本(顺便说一句,这是您应该随问题一起发布的 MCVE 类型。)
我的字体查询结果是:
Font name: Lucida Grande | Font style: 0
… 但我怀疑这是 JLabel
小部件的默认字体,而不是用于呈现这些阿拉伯字符的实际字体。我依稀记得,最新版本的 macOS 包含丰富的各种专用于阿拉伯语的字体。请参阅:Fonts included with macOS Big Sur for three lists: fonts included, fonts available for download, and older fonts available for document support. Using the Font Book app bundled with macOS, and defining a "smart collection" where languages include Arabic, I get a list of 32 such fonts installed by default in macOS Big Sur. (The four items for Pragmata Pro 不适用 — 这是我购买的商业字体,我强烈推荐给开发人员。)
我运行这个修改版本的代码来自
package work.basil.text;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
public class TestProject extends JFrame {
public static void main ( String[] args ) {
TestProject frame = new TestProject();
frame.setVisible( true );
}
public TestProject () {
this.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
this.setLayout( new FlowLayout() );
String input = "محمد";
String[] fontFamilies = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for ( String fontFamily : fontFamilies ) {
Font font = new Font( fontFamily , Font.PLAIN , 40 );
if ( font.canDisplayUpTo( input ) < 0 ) {
JLabel label = new JLabel( input );
label.setFont( font );
label.setBorder( new TitledBorder( fontFamily ) );
this.add( label );
}
}
this.pack();
}
}
这是结果的屏幕截图。
尝试 运行 下面的代码。它在我安装的字体范围内生成了这张图片。
另请注意,Arial(一种无衬线或未装饰字体)的阿拉伯字形似乎默认为 Times New Roman(一种衬线或装饰字体)。这是字体(或系统,不确定)经常做的事情,当用衬线字体替换无衬线字体时,它会产生相当奇怪的渲染。
另请注意,此系统安装了 255 种字体,但其中只有 23 种支持阿拉伯字符。
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class TestProject extends JFrame {
public static void main(String[] args) {
TestProject frame = new TestProject();
frame.setVisible(true);
}
public TestProject() {
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel p = new JPanel(new GridLayout(0, 5));
String arabic = "محمد";
String[] fontFamilies = GraphicsEnvironment.
getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for (String fontFamily : fontFamilies) {
Font font = new Font(fontFamily, Font.PLAIN, 25);
if (font.canDisplayUpTo(arabic) < 0) {
JLabel label = new JLabel(arabic);
label.setFont(font);
label.setBorder(new TitledBorder(fontFamily));
p.add(label);
}
}
this.add(new JScrollPane(p));
this.pack();
}
}
这似乎是旧的(即最多 Java 8)字体渲染引擎中的错误。
这是 Java 8 在我的机器上的样子:
这是 Java9 的结果:
我不知道是否针对此特定问题报告了明确的错误报告。但是由于 JEP 258: HarfBuzz Font-Layout Engine.
,字体引擎已被完全替换Replace the existing ICU OpenType font-layout engine with HarfBuzz.
因此旧字体渲染的错误消失也就不足为奇了。