如何配置在Linux上使用的简单Java fontconfig.properties文件



我在自定义linux硬件上使用自定义Java 11运行时,Java运行时不是我自己构建的。但我有一个问题,我的应用程序需要访问字体,并且运行时没有配置任何字体,所以我得到了这个堆栈

Exception in thread "main" java.lang.InternalError: java.lang.reflect.InvocationTargetException
at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:86)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)
at java.desktop/java.awt.Font.getFont2D(Font.java:497)
at java.desktop/java.awt.Font.getFamily(Font.java:1410)
at java.desktop/java.awt.Font.getFamily_NoClientCode(Font.java:1384)
at java.desktop/java.awt.Font.getFamily(Font.java:1376)
at java.desktop/java.awt.Font.toString(Font.java:1869)
at java.base/java.lang.String.valueOf(String.java:2951)
at java.base/java.io.PrintStream.println(PrintStream.java:897)
at Fonts.main(Fonts.java:7)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:84)
... 10 more
Caused by: java.lang.NullPointerException
at java.desktop/sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1262)
at java.desktop/sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:225)
at java.desktop/sun.awt.FontConfiguration.init(FontConfiguration.java:107)
at java.desktop/sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:719)
at java.desktop/sun.font.SunFontManager$2.run(SunFontManager.java:367)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.desktop/sun.font.SunFontManager.<init>(SunFontManager.java:312)
at java.desktop/sun.awt.FcFontManager.<init>(FcFontManager.java:35)
at java.desktop/sun.awt.X11FontManager.<init>(X11FontManager.java:56) 

我可以提供一些字体,我已经计算出我需要创建一个fontconfig.properties并将我放入Java运行时lib文件夹,但我很难理解我需要将什么放入fontconfig.properties。

有人能给我一个例子,说明如何在linux上的fontconfig.properties中指定一组最小的字体来防止异常发生吗。

更具体地说,我有一组truetype字体,我已经将其放入lib文件夹中的fonts中,那么我如何将这组字体用作Java 可用的字体集呢

  • LucidaBrightDemiItalic.ttf
  • LucidaBrightRegular.ttf
  • Lucida SansRegular.ttf
  • Lucida打字机规则ttf
  • LucidaBrightDemiBold.ttf
  • LucidaBrightItalic.ttf
  • LucidaSansDemiBold.tf
  • Lucida打字机粗体.ttf

如果我创建了一个空的fontconfig.properties文件,那么第一个异常将更改为

Caused by: java.lang.NullPointerException
at java.desktop/sun.awt.FontConfiguration.getInitELC(FontConfiguration.java:465)
at java.desktop/sun.awt.FontConfiguration.initFontConfig(FontConfiguration.java:441)
at java.desktop/sun.awt.FontConfiguration.init(FontConfiguration.java:108)
at java.desktop/sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:719)
at java.desktop/sun.font.SunFontManager$2.run(SunFontManager.java:367)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.desktop/sun.font.SunFontManager.<init>(SunFontManager.java:312)
at java.desktop/sun.awt.FcFontManager.<init>(FcFontManager.java:35)
at java.desktop/sun.awt.X11FontManager.<init>(X11FontManager.java:56)

所以这表明Java运行时至少找到了(空的(fontconfig.properties文件,所以如果我能正确配置它,这应该可以工作。

我试图用一个文件创建一个非常小的fontconfig.properties文件,但没有成功。

version=1
allfonts.plain.latin-1=-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1
filename.-monotype-times new roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/SongKong/songkong/jre/lib/fonts/ipag.ttf
awtfontpath.latin-1=/mnt/app/opt/SongKong/songkong/jre/lib/fonts

Jdk版本没有任何字体,Oracle版本通常都有,所以我想下载一个Oracle版本,看看它们的作用,但Windows和UNIX版本之间的fontconfig.properties文件有很大不同,所以我需要一个UNIX版本。

我首先下载了jdk-11.0.6_linux-x64_bin.tar.gz,但它没有fontconfig.properties文件,可能是因为它只是一个通用的linux构建,而不是与任何特定的绑定。由于我的主要开发机器是Windows,我不想尝试.deb或.rpm版本,因为安装它们没有简单的途径。因此,我下载了Solaris jdk-11.0.6_Solaris-sparcv9_bin.tar.gz并解压缩了它。

它确实包含以下结构后面的font.properties.src文件

Version =1
# Component Font Mappings
# Search Sequences
# Font Filenames
# AWT X11 font paths

我的理解是组件字体映射Java组件字体映射到逻辑字体名称搜索序列指定了基于Java组件字体搜索字体的顺序Font文件名从逻辑字体名映射到机器上字体所在的实际文件名AWT X11字体路径指定从组件字体名称到包含机器上实际字体的实际文件夹

因此,我在文件上进行了搜索并替换,将实际文件名替换为服务器上我的字体上的位置,并将实际文件夹更换为包含实际字体的文件夹上的位置。

然后,我将修改后的fontconfig.prrties.src重命名为font config.properties,并将其存储在jre/lib文件夹中

一个以前失败的简单测试程序现在可以工作

import java.awt.*;
public class Fonts
{
public static void main(String[] args) throws Exception
{
Font defaultFont = Font.decode(null);
System.out.println(defaultFont);
}
}

然而,我只指定了一种字体(ipag.ttf(,用于不同的脚本和不同的风格(普通、粗体等(。

当我运行该程序时,jakarta.poi(用于创建excel电子表格文件(需要使用字体,现在出现以下异常:

java.lang.ClassCastException: class sun.font.CompositeFont cannot be cast to class sun.font.PhysicalFont (sun.font.CompositeFont and sun.font.PhysicalFont are in module java.desktop of loader 'bootstrap')
at java.desktop/sun.font.SunFontManager.getDefaultPhysicalFont(SunFontManager.java:1086)
at java.desktop/sun.font.SunFontManager.initialiseDeferredFont(SunFontManager.java:965)
at java.desktop/sun.font.SunFontManager.findOtherDeferredFont(SunFontManager.java:903)
at java.desktop/sun.font.SunFontManager.findDeferredFont(SunFontManager.java:919)
at java.desktop/sun.font.SunFontManager.findFont2D(SunFontManager.java:2120)
at java.desktop/java.awt.Font.getFont2D(Font.java:506)
at java.desktop/java.awt.Font.canDisplayUpTo(Font.java:2246)
at java.desktop/java.awt.font.TextLayout.singleFont(TextLayout.java:469)
at java.desktop/java.awt.font.TextLayout.<init>(TextLayout.java:530)
at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:275)

我认为这里的问题是,应该使用物理字体,但由于我没有指定粗体、斜体字体,ectera Java试图根据对物理字体的修改创建一种字体,从而创建

复合字体因此,我将Lucida字体复制到字体目录中,修改了fontconfig。属性文件使用这些字体变体,如下

filename.-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaSansRegular.ttf
filename.-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaSansRegular.ttf
filename.-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaSansDemiBold.ttf
filename.-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaSansDemiBold.ttf
filename.-monotype-courier_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaTypewriterRegular.ttf
filename.-monotype-courier_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaTypewriterRegular.ttf
filename.-monotype-courier_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaTypewriterBold.ttf
filename.-monotype-courier_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaTypewriterBold.ttf
filename.-monotype-times_new_roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaBrightRegular.ttf
filename.-monotype-times_new_roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaBrightItalic.ttf
filename.-monotype-times_new_roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaBrightDemiBold.ttf
filename.-monotype-times_new_roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/mnt/app/opt/jre/lib/fonts/LucidaBrightDemiItalic.ttf

刚刚保留了用于东南亚脚本的ipag.ttf并重新启动了应用程序,一切正常。我不确定这是否在任何情况下都有效。

最新更新