iText + HTMLWorker - 如何更改默认字体?

mon*_*zek 10 html java itext character-encoding

我必须从HTML源创建PDF文件.目前,我正在处理有关输出文件中特殊(抛光)字符的问题,正是因为它们缺乏.

HTML源代码:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<table width="100%" border="0.5" align="center" cellpadding="0" style="border-collapse:collapse; border:1px solid black; font-family:Arial, Helvetica, sans-serif; font-size:16px">
  <tr>
    <td align="center" ><b>Test: ???ó????Ó??????????ó</b></td>
  </tr>
</table>
Run Code Online (Sandbox Code Playgroud)

Java来源:

Document document = new Document(PageSize.A4, 38, 38, 50, 38);  
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("iTextExample.pdf"));  
document.open();  
HTMLWorker htmlWorker = new HTMLWorker(document);  
htmlWorker.parse(new StringReader(readFileAsString("index.html")));  
document.close();


public static String readFileAsString(String filePath) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
    try {
        long len = new File(filePath).length();
        if (len > Integer.MAX_VALUE) {
            throw new IOException("File " + filePath + " too large, was " + len + " bytes.");
        }
        byte[] bytes = new byte[(int) len];
        dis.readFully(bytes);
        return new String(bytes, "UTF-8");
    } finally {
        dis.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:如何将默认字体(Helvetica)更改为例如.Arial Bold整个PDF文档?

我已经测试了许多与StyleSheet相关的示例,但没有一个能够工作.我必须更改默认字体,因为没有抛光字符 - 这是我希望能够解决的解决方案.

谢谢你的帮助!

编辑:

My FontProvider:  
    class defaultFontProvider extends FontFactoryImp {

    private String _default;

    public defaultFontProvider(String def) {
        _default = def;
    }

    public Font getFont(String fontName, String encoding, boolean embedded, float size, int style, BaseColor color, boolean cached) {
        if (fontName == null || size == 0) {
            fontName = _default;
        }

        return super.getFont(fontName, encoding, embedded, size, style, color, cached);
    }
    }
Run Code Online (Sandbox Code Playgroud)

上面的代码嵌入了arial.ttf可以,但是如何使它成为整个文档的默认字体(而不是Helvetica).

然后..

        Map<String,Object> providers = new HashMap<String, Object>();

        defaultFontProvider dfp = new defaultFontProvider("arial.ttf");


        providers.put(HTMLWorker.FONT_PROVIDER, dfp);

        HTMLWorker htmlWorker = new HTMLWorker(document);
        htmlWorker.setProviders(providers);
Run Code Online (Sandbox Code Playgroud)

Mar*_*rer 3

想法#1

我立即想到一个答案:更改 iText。具体来说,Font.getCalculatedBaseFont第 644 行。

String fontName = BaseFont.HELVETICA;
Run Code Online (Sandbox Code Playgroud)

实际上,我不认为这会起作用,除非你也改变字体的创建方式......第 712 行

cfont = BaseFont.createFont(fontName, encoding, false);
Run Code Online (Sandbox Code Playgroud)

除非字体是“Base 14”之一,否则您必须提供字体文件的路径,而不是简单的字体名称。

另一种选择:XSLT

转换输入,以便将字体定义添加到包含文本的任何节点的样式。

最后:注册一个fontProvider

您可以坐在 FontFactoryImp 之上,只需将空白字符串映射到您选择的字体即可。

class DefaultFontProvider extends FontFactoryImp {
  private String default;
  public DefaultFontProvider(String def) {
    default = def;
  }

  // I believe this is the correct override, but there are quite a few others.
  public Font getFont(String fontname, String encoding, boolean embedded, float size, int style, BaseColor color, boolean cached) {
    if (fontName == null || fontName.size() == 0) {
      fontName = default;
    }
    return super.getFont(fontName, encoding, embedded, size, style, color, cached);
  }
}


Map<String,Object> providers = new HashMap<String, Object)();
providers.put(HTMLWorker.FONT_PROVIDER, new DefaultFontProvider("Arial Bold"));

myHTMLWorker.setProviders(providers);
Run Code Online (Sandbox Code Playgroud)

我认为这是技术上最合理的想法。它是为新发布的 iText 5.0.6 版本编写的。以前的版本通过改为设置字体提供程序setInterfaceProps()。在这一点上,“Providers”更多的是一个名称的改变。我怀疑 5.1 中情况将不再如此。

PS:FontFactoryImp有两个您可能也感兴趣的公共成员:defaultEncodingdefaultEmbedding。您应该能够将其调整defaultEncoding为对波兰语更友好的内容。我推荐“Identity-H”(又名BaseFont.IDENTITY_H),但这确实会强制将所有字体嵌入子集,从而忽略defaultEmbedding,并使您的文件比根本不嵌入字体时要大一些。


两个可能的问题:

  1. 明确请求“Helvetica”。

    可以肯定的是,我建议将其填充System.out.println(("Requested font: " + fontName);到 getFont 函数的开头。这将使您看到所有字体调用,并确保您已正确替换所有字体。如果是这种情况,您只需测试它并将其替换为_default.

  2. 您的 fontFactory 可能找不到“Arial Bold”的任何内容,因此会退回到默认值(再次是 Helvetica)。

    我想你需要打电话dfp.registerDirectories()。这将找出几个不同操作系统上的所有字体,并让您通过字体名称而不是路径来引用它们(这是 FontFactoryImp 最初应该做的事情)。