gpt4 book ai didi

java - 如果文本中有阿拉伯语或波斯语字母,通过 fontmetrics 计算的字符串宽度非常慢

转载 作者:搜寻专家 更新时间:2023-10-30 19:46:08 24 4
gpt4 key购买 nike

我有一个问题。如果我在那里使用东方语言,我的应用程序界面工作起来会慢得多。特别是在 JList、JCombobox、JTable 等组件中,我感受到了它。

如果文本中至少有一个字母是阿拉伯语或波斯语,我发现 FontMetrics.stringWidth 方法的性能非常慢(500 次以上)。我怎么知道它是各种 Swing 组件中常用的方法。

有没有办法提高这个方法的性能?

这是演示问题的示例类:

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

public class FontMetricsSpeedTest
{

public static void main( String args[] ) {
String persian="صصصصصصصصصصصصصصصصصصصصص";
String english="abcde()agjklj;lkjelwk";
FontMetrics fm=createFontMetrics(new Font("dialog",Font.PLAIN,12));
int size=50000;
long start=System.currentTimeMillis();
for(int i=0;i<size;i++)
{
fm.stringWidth(persian);
}
System.out.println("Calculation time for persian: "+(System.currentTimeMillis()-start)+" ms");
start=System.currentTimeMillis();
for(int i=0;i<size;i++)
{
fm.stringWidth(english);
}
System.out.println("Calculation time for english: "+(System.currentTimeMillis()-start)+" ms");
}
private static FontMetrics createFontMetrics(Font font)
{
BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);
Graphics g = bi.getGraphics();
FontMetrics fm = g.getFontMetrics(font);
g.dispose();
bi = null;
return fm;
}
}

对我来说,它给出了下一个输出:

波斯语的计算时间:5482 毫秒

英语的计算时间:11 毫秒

最佳答案

我挖掘了一下,发现了下一个:

从FontDesignMetrics的源码我们可以看到主要的 Action 序列

public int stringWidth(String str) {
float width = 0;
if (font.hasLayoutAttributes()) {
/* TextLayout throws IAE for null, so throw NPE explicitly */
if (str == null) {
throw new NullPointerException("str is null");
}
if (str.length() == 0) {
return 0;
}
width = new TextLayout(str, font, frc).getAdvance();
} else {
int length = str.length();
for (int i = 0; i < length; i++) {
char ch = str.charAt(i);
if (ch < 0x100) {
width += getLatinCharWidth(ch);
} else if (FontManager.isNonSimpleChar(ch)) {
width = new TextLayout(str, font, frc).getAdvance();
break;
} else {
width += handleCharWidth(ch);
}
}
}
return (int) (0.5 + width);

对于拉丁字符,使用方法 getLatinCharWidth(ch)。它缓存所有字符宽度。但对于波斯语和阿拉伯语字符,使用 TextLayout 代替。主要目的是因为东方字符可能具有不同的形状和宽度,具体取决于上下文。可以添加缓存字符宽度的方法,但它不会给出准确的值,例如它会忽略不同字符宽度的细微差别。它还会忽略各种连字。

我已经分别测试了 TextLayout,它对于英语和波斯语都很慢。所以性能缓慢的真正原因是 sun.font.TextLayout 类的工作缓慢。它用于确定字符串宽度,以防字符串中的字符不简单。不幸的是,我暂时不知道如何提高 TextLayout 的性能。

如果有人对这里感兴趣,可以阅读有关各种字体和文本布局细微差别的文章 http://download.oracle.com/javase/1.4.2/docs/guide/2d/spec/j2d-fonts.html

关于java - 如果文本中有阿拉伯语或波斯语字母,通过 fontmetrics 计算的字符串宽度非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4333577/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com