在OpenJdk中如何使用appendedfontpath属性设置字体目录

问题描述 投票:0回答:5

我试图让我的应用程序使用 OpenJdk 安装中特定位置的字体,使用 appendedfontpath 属性,但它对我不起作用。

../jre1.8.0_121+1/bin/java  -Dappendedfontpath=/usr/lib/fonts/  -jar lib/songkong-4.7.jar -m /mnt/disk1/share

报告没有安装字体,但 /usr/lib/fonts 文件夹确实包含字体

ipag.ttf

请注意:

  • OpenJdk 没有预装字体,它依赖于系统上安装的字体
  • 这是一个嵌入式系统,报告服务器上没有安装字体,
    fc-list
    不返回任何内容
  • 如果我将字体复制到 jre/lib/fonts 文件夹中,它可以工作,但不允许我将任何内容复制到此文件夹中。
  • 我也不允许运行 root 命令,例如
    fc-cache -f

如果我只需指定包含字体的字体文件夹即可使其工作,那么这对我来说将是一个可行的解决方案。

fonts java
5个回答
2
投票

您可以尝试在启动 JVM 之前设置

JAVA_FONTS
环境变量,以使其了解目录路径。 对于您的情况,这可以通过
export JAVA_FONTS=/usr/lib/fonts
来完成。 我的答案基于 archlinux wiki 的 Java Runtime Enviroment fonts 文章。


编辑:
在未安装字体的虚拟机中进行测试表明设置 JAVA_FONTS 不起作用 我得出的结论是,按照您的设置,可能无法实现您的目标。
我使用以下程序在未安装字体的虚拟机上重现错误:

import javax.swing.*;
public class example{

    public static void main(String[] tArgs){
        JFrame j = new JFrame();
        j.add(new JButton("Test"));
        j.setVisible(true);
        j.pack();
   }

}

这是我的堆栈跟踪: https://pastebin.com/fy3JDnkN
鉴于 X11FontManager 的来源 在使用

for (int i=0; i<fontConfigFonts.length; i++) {
的行中构建字体管理器时会发生错误。

public String[] getDefaultPlatformFont() {
    if (defaultPlatformFont != null) {
        return defaultPlatformFont;
    }
    String[] info = new String[2];
    getFontConfigManager().initFontConfigFonts(false);
    FontConfigManager.FcCompFont[] fontConfigFonts =
        getFontConfigManager().getFontConfigFonts();
    for (int i=0; i<fontConfigFonts.length; i++) {
        if ("sans".equals(fontConfigFonts[i].fcFamily) &&
            0 == fontConfigFonts[i].style) {
            info[0] = fontConfigFonts[i].firstFont.familyName;
            info[1] = fontConfigFonts[i].firstFont.fontFile;
            break;
        }
    }
    /* Absolute last ditch attempt in the face of fontconfig problems.
     * If we didn't match, pick the first, or just make something
     * up so we don't NPE.
     */
    if (info[0] == null) {
        if (fontConfigFonts.length > 0 &&
            fontConfigFonts[0].firstFont.fontFile != null) {
            info[0] = fontConfigFonts[0].firstFont.familyName;
            info[1] = fontConfigFonts[0].firstFont.fontFile;
        } else {
            info[0] = "Dialog";
            info[1] = "/dialog.ttf";
        }
    }
    defaultPlatformFont = info;
    return defaultPlatformFont;
}

这使得手动添加字体变得不可能,因为 NullPointerException 发生在我们访问字体管理器之前,考虑到几行后面的注释,这种行为似乎不是有意的。

如果有另一个适用于 Linux 的 FontManager 在没有安装默认系统字体的情况下不会崩溃,也许仍然可以实现你的目标,但我找不到这样的替代品。


1
投票

一种解决方案可能是将字体打包到您自己的 jar 中,并尝试执行类似 this 的操作。


1
投票

您不需要指定字体目录。如果您的机器上安装了它,JRE 将自动选择字体。

我过去也遇到过这个问题,并在 github 中找到了带有字体的预构建开放 JRE 包。这些软件包是根据 GNU GPL v. 2 发布的,但类路径例外。

https://github.com/ojdkbuild/ojdkbuild/releases/tag/1.8.0.121-1

您可以下载 Linux 版本 (java-1.8.0-openjdk-1.8.0.121-0.b13.el6_8.x86_64.zip),或者您也可以在版本下查找 121 以外的更新。

注意:如果需要,您还可以在 jre/lib/fonts 下包含缺少的 True Type 字体。

替代选项 I

在您的机器中安装所需的字体。这将无缝工作,您无需在 JRE 中配置任何内容。

注:

  • 如果您没有安装字体的权限,您可以很好地复制 字体 /usr/share/fonts 目录。
  • 如果是只读分区,可以将该分区挂载为可读写模式,并复制字体文件。
  • 如果 /usr/share/fonts 所在分区没有空间,可以将文件复制到其他目录并建立软链接。

替代方案二

包含jre/lib/fonts目录中的字体(如果不存在则创建fonts目录)并配置jre/lib中的fontconfig.properties文件。我还没有测试过这个选项,但它应该可以工作。

编辑:

  • 如果机器中已经安装了字体,JVM 应该自动选择字体。否则,您可以使用 JAVA_FONTS 环境变量指定@BdoubleB97答案中提到的字体。
  • 如果您没有设置环境变量的权限,您可以在运行时传递环境变量,如下所示。

    ./java -DJAVA_FONTS=/usr/share/fonts 测试


0
投票

字体的标准系统位置是 /usr/share/fonts 和子目录(请参阅 fontconfig 和

# fc-cache -f
)。 /usr/lib/fonts 是 miriad 非标准位置之一,大约 14 年前已被弃用,这就是系统和 OpenJDK 找不到您的字体的原因。

与传统的 SUN JVM 不同,OpenJDK 实际上尝试与系统集成并使用系统资源(不仅在 Windows 下)。


0
投票

如何指定字体目录:

在 OpenJDK 11 和 17 上测试

  1. lib/fontconfig.properties 设置附加字体路径=ADDITIONAL_FONT_PATH。
  2. -Dsun.java2d.fontpath=附加:FONT_PATH|前置:FONT_PATH

提示:至少需要步骤 2 以确保 FontConfiguration 处于活动状态。

© www.soinside.com 2019 - 2024. All rights reserved.