【问题标题】:Java takes too long time to initialize large OpenType fontsJava 需要很长时间来初始化大型 OpenType 字体
【发布时间】:2019-04-30 09:11:35
【问题描述】:

我必须在我的应用程序中使用 Noto Sans CJK 字体。 但是当我调用下面的方法时,初始化需要10秒。

Font font = //Noto Sans CJK font
JComponent.getFontMetrics(An instance of Noto Sans CJK font);

我可以解决这个延迟问题吗?如果方法可以帮助解决这个问题,代码可能会很复杂(就像实现 FontMetrics,我不知道如何)。

请不要推荐我将 otf 字体转换为 ttf 字体。我无法转换它,因为字体工具说它是字母字体,甚至无法加载 unicode 字形。另外我必须在应用程序中使用另一种 otf 字体。而且我不会使用已经转换的版本。

  • 如果你能用 Java 代码解决这个问题,我想用这个方法。

  • 如果任何 unicode otf 字体可以转换为 ttf,我将使用该工具(但必须是免费的,不得试用。完全免费)。请告诉我如何将otf转换为ttf。我试过网站和fontforge。两者都返回 7KB 字体,即使这个字体是 7MB。

我英语不好。对不起。

【问题讨论】:

  • 你使用的是什么 Java 版本?
  • 我使用的是 Java 1.8.0_192。我不能使用较新的版本,因为我的目标是 32 位系统。当然,我也不喜欢 32 位,
  • 你能显示minimal reproducible example吗?不仅是为了帮助我们,也是为了帮助您。
  • 字体 baseFont = Font.createFont(Font.TRUETYPE_FONT, getClass().getResourceAsStream("/resources/Noto.otf"));字体 noto = baseFont.deriveFont(Font.PLAIN, 10); System.out.println(noto);
  • 这与我的第二个示例类似(除了在此 sn-p 中您不收集指标)。 a) 你有什么硬件规格(CPU、RAM、HDD/SDD、操作系统)? b) 你从哪里得到Noto.otf?您是否尝试过我在示例中提到的版本?如果是这样,您能注意到其中的不同吗?

标签: java fonts


【解决方案1】:

也许您应该提供逐步说明来重现您的问题。

我在我的系统上进行了跟踪。

  • NotoSansCJKjp-hinted.zip安装字体文件NotoSansCJKjp-Regular.otf
  • 编译示例代码

    $ javac NotoFont.java
    
  • 运行编译后的代码

    $ time java NotoFont
    

在我的系统上执行时间不到一秒。

上述运行的输出

java.awt.Font[family=Noto Sans CJK JP Regular,name=Noto Sans CJK JP Regular,style=plain,size=10]

real    0m0.522s
user    0m0.565s
sys     0m0.056s

NotoFont.java

import java.awt.Font;
class NotoFont {
    public static void main(String[] args) {
        Font noto = new Font("Noto Sans CJK JP Regular", Font.PLAIN, 10);
        System.out.println(noto);
    }
}

edit 从 Jar 中读取字体文件的示例。系统上没有安装字体。

假设以下结构。

build/fonts/NotoSansCJKjp-Regular.otf
dist/
NotoFont.java

NotoFont.java

import java.awt.*;
import java.io.*;
import java.swing.*;
class NotoFont {
    private void run() throws FontFormatException, IOException {
        try (InputStream is = this.getClass().getResourceAsStream("/fonts/NotoSansCJKjp-Regular.otf")) {
            Font baseFont = Font.createFont(Font.TRUETYPE_FONT, is);
            Font noto = baseFont.deriveFont(Font.PLAIN, 10);
            System.out.println(noto);
            FontMetrics metrics = new JPanel().getFontMetrics(noto);
            System.out.println(metrics);
        }
    }
    public static void main(String[] args) throws FontFormatException, IOException {
        new NotoFont().run();
    }
}
  • 编译代码

    $ javac -d build/ NotoFont.java
    
  • 创建罐子

    $ jar cf dist/notofont.jar -C build/ .
    
  • 检查 Jar 内容

    $ cd dist/
    $ jar tf notofont.jar
    META-INF/
    META-INF/MANIFEST.MF
    NotoFont.class
    fonts/
    fonts/NotoSansCJKjp-Regular.otf
    
  • 运行代码

    $ time java -cp notofont.jar NotoFont
    

以上运行的输出

java.awt.Font[family=Noto Sans CJK JP Regular,name=Noto Sans CJK JP Regular,style=plain,size=10]
sun.font.FontDesignMetrics[font=java.awt.Font[family=Noto Sans CJK JP Regular,name=Noto Sans CJK JP Regular,style=plain,size=10]ascent=9, descent=3, height=12]
real 3.02
user 2.11
sys 0.84

【讨论】:

  • otf 文件是资源文件和内部jar 文件。我必须使用 Font.createFont 从 InputStream 获取 Font 实例。并且在使用 JComponent.getFontMetrics 方法获取 FontMetrics 时发生了这种延迟
  • @dhkim0800 我添加了另一个示例。从 Jar 中读取字体并打印字体规格。现在大约需要 3 秒。正如我所说,您应该提供更多信息。例如,可以用来重现您的问题、关于您的系统的 sn-p,...
  • 我是 Windows 用户。我没有时间指令。我会用 system.currentTimeMillis() 试试你的代码
猜你喜欢
  • 1970-01-01
  • 2018-12-27
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 2017-09-03
  • 1970-01-01
  • 2014-10-21
  • 2021-01-15
相关资源
最近更新 更多