如何使用 iText 和 Flying Saucer 在从 HTML 创建的 PDF 中嵌入字体?

发布于 2024-12-06 11:46:32 字数 866 浏览 1 评论 0原文

我在将波兰语字体嵌入从 HTML 转换为 PDF 时遇到问题。

我的 HTML 代码在正文中具有样式:

<BODY style="font-family: Tahoma, Arial, sans-serif;font-size : 8pt;">

我尝试了两种将此类 HTML 转换为 PDF 的方法:

  • FOP 与 htmlcleaner
  • iText 与飞碟

对于 FOP,我可以将所有使用的字体添加到其配置文件中,然后创建 PDF 嵌入这些字体(如果字体用于 HTML)。在生成的 PDF 中,我有 Identity-H 编码的 Tahoma 字体。看起来不错——所有波兰语字母都按预期显示。

然后我尝试使用 iText 进行此类转换:似乎更简单,因为我不需要为每个 HTML 创建转换。不幸的是,我不知道如何将使用过的字体嵌入到生成的 PDF 中。我发现的大多数示例都是从头开始创建 PDF,我不知道如何将这些方法应用于 Flying Saucer ITextRenderer 或转换中使用的其他对象。

我当前的代码尝试通过获取 ITextFontResolver 并添加字体 fs.addFont(path, true); 来在 PDFCreationListener.preOpen() 中添加字体。但我创建的所有 .pdf 都没有我想要的字体。

第二个问题是结果 PDF 没有波兰语字母。是飞碟问题还是iText问题? Acrobat 显示创建的 PDF 文档使用带有 Ansi 编码的 Helvetica 和 ArialMT 作为字体。我觉得这个Ansi编码不好。如何设置波兰编码(Identity-H)?

I have problem with embedding Polish fonts into PDF converted from HTML.

My HTML code have style in body:

<BODY style="font-family: Tahoma, Arial, sans-serif;font-size : 8pt;">

I tried 2 ways of converting such HTML into PDF:

  • FOP with htmlcleaner
  • iText with flying-saucer

For FOP I can add all used fonts into its config file and then created PDF have those fonts embedded (if font is used in HTML). In resulting PDF I have Tahoma font in Identity-H encoding. It looks good -- all Polish letters are displayed as expected.

Then I tried such conversion with iText: seems simplier because I do not need to create transformation for every HTML. Unfortunately I don't know how to embed used fonts into resulting PDF. Most examples I found create PDF from scratch and I don't know how to apply those methods to the Flying Saucer ITextRenderer or other object used in conversion.

My current code tries to add fonts in PDFCreationListener.preOpen() by getting ITextFontResolver and adding font fs.addFont(path, true);. But all .pdf I create do not have fonts I want.

The second problem is that result PDF do not have Polish letters. Is it problem in Flying Saucer or in iText? Acrobat shows that created PDF document uses Helvetica with Ansi encoding and ArialMT as font. I think this Ansi encoding is not good. How can I set Polish encoding (Identity-H)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

猫七 2024-12-13 11:46:32

您可以尝试 -fs-pdf-font-embed 和 -fs-pdf-font-encoding css 规则。

来自用户指南

-fs-pdf-font-embed:与字体规则内嵌入的值一起使用
让 Flying Saucer 在 PDF 文档中嵌入字体文件,
避免调用 FontResolver 的 addFont() 方法

-fs-pdf-font-encoding:在字体规则内使用来指定
enconding 用于嵌入 PDF 中的自定义字体;采取
编码名称作为值。

例如在你的打印CSS中:

@font-face {
    font-family: DejaVu Serif;
    src: url(fonts/DejaVuSerif.ttf);
    -fs-pdf-font-embed: embed;
    -fs-pdf-font-encoding: Identity-H;
}

You may try the -fs-pdf-font-embed, and -fs-pdf-font-encoding css rules.

From the User's Guide:

-fs-pdf-font-embed: use with the value embed inside a font-face rule
to have Flying Saucer embed a font file within a PDF document,
avoiding the need to call the addFont() method of the FontResolver
class

-fs-pdf-font-encoding: use inside a font-face rule to specify the
enconding for a custom font you are embedding inside a PDF; takes the
name of the encoding as value.

For example in your print css:

@font-face {
    font-family: DejaVu Serif;
    src: url(fonts/DejaVuSerif.ttf);
    -fs-pdf-font-embed: embed;
    -fs-pdf-font-encoding: Identity-H;
}
暮倦 2024-12-13 11:46:32

工作示例:

根项目目录中的文件:

  • Calibri.ttf
  • input.html

代码:

File inputFile = new File("input.html");
File outputFile = new File("example.pdf");

ITextRenderer renderer = new ITextRenderer();

String url = inputFile.toURI().toURL().toString();
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);

renderer.setDocument(url);
renderer.getFontResolver().addFont("Calibri.ttf", BaseFont.IDENTITY_H, true);
renderer.layout();
renderer.createPDF(fileOutputStream);

fileOutputStream.close();       

HTML:

<style type="text/css">
    body {
        font-family: Calibri, sans-serif;
    }
</style>

令人惊讶的是不需要 @font-face css

Working example:

Files in the root project directory:

  • Calibri.ttf
  • input.html

Code:

File inputFile = new File("input.html");
File outputFile = new File("example.pdf");

ITextRenderer renderer = new ITextRenderer();

String url = inputFile.toURI().toURL().toString();
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);

renderer.setDocument(url);
renderer.getFontResolver().addFont("Calibri.ttf", BaseFont.IDENTITY_H, true);
renderer.layout();
renderer.createPDF(fileOutputStream);

fileOutputStream.close();       

HTML:

<style type="text/css">
    body {
        font-family: Calibri, sans-serif;
    }
</style>

Surprisingly @font-face css is not needed

还给你自由 2024-12-13 11:46:32

我的错误是在 PDFCreationListener.preOpen() 中使用 FontResolver.addFont() 。我把它移到了 renderer.layout(); 之前,现在它可以工作了!

My mistake was to use FontResolver.addFont() in PDFCreationListener.preOpen(). I moved it just before renderer.layout(); and it works now!

千纸鹤带着心事 2024-12-13 11:46:32

如果您已尝试了所有选项但仍然不起作用,则很可能是 font-family 值与文件名不匹配的问题。

您可以找出正确的值使用 FontForge。在此程序中打开字体文件,然后选择菜单项 Element ->字体信息。正确的值将位于 Family Name 字段中

所需的最低 html 代码:

<html>
<head>
    <style>
        body {
            font-family: 'Calibri 123', sans-serif;
        }
    </style>
</head>
<body>
<p>
    Hello, Calibri 123
</p>
</body>
</html>

所需的最低 java 代码:

ITextRenderer renderer = new ITextRenderer();
renderer.getFontResolver().addFont("/path/to/font/Calibri.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
renderer.setDocumentFromString(/*read html from file*/);
renderer.layout();
renderer.createPDF(/*stream here*/);

If you've tried all the options and it still doesn't work, it's most likely a problem with with a font-family value that doesn't match the file name

You can find out the correct value using FontForge. Open font file in this program, then select the menu item Element -> Font Info. The correct value will be in the Family Name field

Minimum required html code:

<html>
<head>
    <style>
        body {
            font-family: 'Calibri 123', sans-serif;
        }
    </style>
</head>
<body>
<p>
    Hello, Calibri 123
</p>
</body>
</html>

Minimum required java code:

ITextRenderer renderer = new ITextRenderer();
renderer.getFontResolver().addFont("/path/to/font/Calibri.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
renderer.setDocumentFromString(/*read html from file*/);
renderer.layout();
renderer.createPDF(/*stream here*/);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文