iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题

  本章是一些问题的总结,iText官网罗列了常见的一些问题,让我们能更加了解pdfTML。一下是原文和链接,在这会一一翻译:

Over the years, we’ve received many questions about converting PDF to
HTML.

In this chapter, we’ll answer those questions that were asked most
frequently.

  • Can I convert an HTML form to a PDF?
  • Can I generate a PDF from a URL instead of from a file on disk?
  • Can pdfHTML render Base64 images to PDF?
  • Does my HTML have to be valid XML?
  • Do we need a browser engine to render HTML+CSS to PDF?
  • How do the measurement systems in HTML relate to the measurement system in PDF?
  • How to convert an ASP or JSP page to PDF?
  • How to convert HTML containing Arabic/Hebrew characters to PDF?
  • How to make a particular sub-string Bold when converting HTML to PDF?
  • How to parse multiple HTML files into one PDF?
  • How to render certain HTML entities (such as arrows) to PDF?
  • Why can’t I embed a font due to licensing restrictions?
  • Why is my PDF missing several characters?

1. 我可以把HTML表单转换为PDF?

  将HTML表单转换为PDF文档的支持有限。如果有一个HTML文件,其中包含要转换为PDF的文本输入框,则还必须指明是否希望生成的PDF为交互式表单。

  我们看一下form.html文件,如图7.1所示:

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第1张图片

图7.1 一个简单的HTML表单

  如果我们想将此HTML表单转换为PDF表单(基于AcroForm技术),我们需要在ConverterProperties中明确提到这一点。请参阅C07E10_HelloAcroForm.java示例:

public void createPdf(String src, String dest) throws IOException {
    ConverterProperties properties = new ConverterProperties();
    properties.setCreateAcroForm(true);
    HtmlConverter.convertToPdf(new File(src), new File(dest), properties);
}

  因为代码行setCreateAcroForm(true)/properties.SetCreateAcroForm(true)创建交互式PDF表单。我们可以手动更改带有蓝色背景的s输入中的文本,如图7.2所示:

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第2张图片

图7.2 一个简单的PDF表单

  如果我们不改变ConverterProperties,也就是C07E11_HelloFormFlattened.java里面的样例,我们将会得到一个"扁平"的PDF:

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第3张图片

图7.3 一个扁平的表单

  输入框里面还保存,但文件中没有交互性。曾经是HTML字段的内容在PDF查看器中无法更改。
  使用交互式PDF表单进行手动数据输入有些过时。当需要手动填写表单时,通常建议首选HTML5。

2. 我可以从URL而不是从磁盘上的文件生成PDF吗?

  你可以从任何HTML的输入流(InputStream)生成PDF。在大多数示例中,我们使用了FileOutputStream,但在第4章中,我们创建了仅存在于内存中的报告(byte[])。在这种情况下,我们使用了ByteArrayInputStream。我们还可以使用从URL对象创建的InputStream

  假设我们使用以下URL:

public static final String ADDRESS = "https://stackoverflow.com/help/on-topic";

  如果我们在浏览器中打开此URL,将看到以下页面:

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第4张图片

图7.4 浏览器中的stackoverflow页面

  在C07E04_CreateFromURL.java样例,我们使用ADDRESS创建JavaURL对象:

new C07E04_CreateFromURL().createPdf(new URL(ADDRESS), DEST);

  我们使用如下的createPdf()方法:

public void createPdf(URL url, String dest) throws IOException {
    HtmlConverter.convertToPdf(url.openStream(), new FileOutputStream(dest));
}

  openStream()方法为我们提供了一个InputStream,iText将使用它来获取HTML——显然,这只适用于可以访问互联网的机器。

  对于包含大量图片的页面,iText可能需要一段时间才能下载所有资源,但Stack Overflow中的这个FAQ页面应该很快加载,结果如图7.5所示:

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第5张图片

图7.5 页面以PDF格式呈现为A4页面

  也许A4页面不是网页的理想页面大小,因为缺少完整的侧边栏。让我们调整示例,并引入一个媒体查询。

  C07E05_CreateFromURL2.java代码中的createPdf()方法如下

public void createPdf(URL url, String dest) throws IOException {
    PdfWriter writer = new PdfWriter(dest);
    PdfDocument pdf = new PdfDocument(writer);
    PageSize pageSize = new PageSize(850, 1700);
    pdf.setDefaultPageSize(pageSize);
    ConverterProperties properties = new ConverterProperties();
    MediaDeviceDescription mediaDeviceDescription =
        new MediaDeviceDescription(MediaType.SCREEN);
    mediaDeviceDescription.setWidth(pageSize.getWidth());
    properties.setMediaDeviceDescription(mediaDeviceDescription);
    HtmlConverter.convertToPdf(url.openStream(), pdf, properties);
}

  我们使用850*1700用户单位的自定义页面大小,并使用第3章中所述的Screen媒体类型。现在内容适合页面,我们得到了更好的结果,如图7.6所示:

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第6张图片

图7.6 页面以PDF格式呈现为自定义大小页面

  当然,还有一些不完美之处。例如:上面中的项目显示为列表了,而不是导航栏中的项,但我们计划在未来版本的pdfHTML中解决这些问题。

  我们也可以使用媒体类型PRINT而不是SCREEN。请参见C07E06_CreateFromURL3.java示例:

public void createPdf(URL url, String dest) throws IOException {
    ConverterProperties properties = new ConverterProperties();
    MediaDeviceDescription mediaDeviceDescription =
        new MediaDeviceDescription(MediaType.PRINT);
    properties.setMediaDeviceDescription(mediaDeviceDescription);
    HtmlConverter.convertToPdf(url.openStream(), new FileOutputStream(dest), properties);
}

  因为Stack Overflow使用print.css,我们现在有几个裸露的页面,其中故意省略了侧边栏。也许这正是我们想要的,如图7.7所示

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第7张图片

图7.7 页面以PDF格式呈现为A4页面(打印模式)

  重要提示:pdfHTML正在开发中。如果你尝试从浏览器将网页打印到纸页,会注意到结果并不总是像希望的那样好。使用pdfHTML作为URL2PDF工具时也是如此。大多数HTML页面不打算打印,但使用pdfHTML,我们正在不断努力改进转换过程。

实际上stackoverflow的页面嵌套的元素有点多,我这边生成的PDF除了打印模式以外效果不是很好,大家可以试试换成别的网页

3. pdfHTML能否将Base64图像转换为PDF?

  可以! iText支持前面章节中不同示例所示的外部图像,但它也支持以Base64字符串存储的内联图像。

  样例可以查看 C07E03_Base64Image.java代码,在createPdf()/CreatePdf()中没有什么特别的地方:

public void createPdf(String html, String dest) throws IOException {
    HtmlConverter.convertToPdf(html, new FileOutputStream(dest));
}

  本示例唯一特别的地方是base64.html文件(请注意,base64编码的图像被截断以适合此页面):

<html>
    <head><title>Testtitle>head>
    <body>
        <h1>Testh1>
        <p>Hello Worldp>
        <img alt="Embedded Image" src="data:image/png;base64,iVBORw0...ErkJggg==" />
    body>
html>

  结果与我们在第1章中使用外部图像时的结果相同。如图7.8所示:
iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第8张图片

图7.8 带有base64编码图像的文件的源代码、浏览器视图和生成的PDF

4. 我的HTML必须是有效的XML吗?

  如果你仍在使用iText 5和XML Worker,则必须提供XHTML。例如:HTML中不允许使用单个
;需要一个
。所有标签都需要关闭。需要正确嵌套标签。为了解决当遇到不完整的HTML语法时的这个问题,我们建议使用jsoup在使用XMLWorker将HTML转换为PDF之前对其进行整理。

  pdfHTML不再需要此功能。我们已经将jsoup集成到pdfHTML插件中,因此您不需要单独调用它。所有HTML在转换为PDF之前都会被清理。以incomplete.html文件为例:

<html>
<head><title>Test incomplete HTMLtitle>head>
<h1>Test
<p>Hello World
<p>Hello Universe
<br>
<img src="img/logo.png" alt="iText logo">

  它没有任何标记,


标记永远不会关闭。这是一个非常不完整的HTML文件,但浏览器无论如何都会呈现它,pdfHTML也是如此。如图7.9所示:

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第9张图片

图7.9 在浏览器和PDF中呈现不完整HTML

  可以通过运行C07E07_CompleteHTML,java自行尝试。

5. 我们需要浏览器引擎来将HTML+CSS转换为PDF吗?

  不需要,pdfHTML完成所有工作,解析HTML和CSS,并将它们映射到iText对象和样式。然后iText引擎基于这些对象和样式渲染PDF。

  然而,pdfHTML目前不支持SVG,也不解析JavaScript。对SVG的支持已在开发路线图上,您可以通过使用浏览器引擎对HTML+CSS+JS进行预处理来解决JavaScript问题。这种浏览器引擎的例子有WebKit(Chrome、Safari)和Gecko(Firefox)。它们可以解释JavaScript,并为您提供可由pdfHTML呈现的HTML。

  注意:SVG支持于2018年9月添加到pdfHTML 2.1.0中,并在后续版本中进行了更新和改进。

6. HTML中的测量系统如何与PDF中的测量体系相关联?

  如果你住在美国,你可能会用英寸(in)来测量页面大小、屏幕大小等。如果你住在国外,你可能更熟悉公制,这是一种基于米(mmcm)的十进制测量系统。如果你在国际环境中工作,必须在两个系统之间切换:

1 in. = 25.4 mm = 2.54 cm = 0.254 dm = 0.0254 m

  PDF用户又是一个测量单位。让我们参考ISO 32000:

  ISO 32000-2:8.3.2.3 用户空间
  沿x轴和y轴的单位长度由页面字典(page dictionary)中的UserUnit条目设置。如果该条目不存在或不受支持,则默认值为1/72英寸。默认用户空间(1/72英寸)中的单位大小的默认值与点大致相同,点是印刷行业中广泛使用的单位。然而,情况并不完全相同;点没有普遍的定义。

  ISO 32000-2: 7.7.3.3 页面对象
  UserUnit:一个正数,表示默认用户空间单位的大小,1/72英寸的倍数。支持值的范围应取决于实施。

  UserUnit的默认值为1,因此,除非我们有意更改UserUnit,否则我们不必担心这个特性。我们可以得出结论,PDF使用用户单位作为度量单位。默认情况下,1个用户单位等于1 point(点),这意味着:

1 in. = 25.4 mm = 72 user units.

  在印刷行业中,点(point)通常用来表示字体的大小。例如:当我在电脑上打开Word时,默认字体为Calibri,字体大小为11pt。尽管ISO 32000声称没有点的通用定义,但可以安全地假设1点是1/72英寸,或者:

1 in. = 25.4 mm = 72 pt.

  在数字成像中,我们经常使用像素。在光栅图像的上下文中,像素的大小取决于分辨率。我们经常交替使用术语每英寸点数(DPI)和每英寸像素(PPI)。这是有区别的,但了解细节的话会花费我们很多精力,假设以300 DPI渲染300 x 300像素的图像,那么该图像的尺寸将为1 x 1英寸。但是,如果以96 DPI(Windows显示分辨率的历史值)渲染相同的图像,则该图像的尺寸将为3.125 x 3.125英寸。

  如果你观察在互联网上找到的CSS文件,您会注意到许多大小都以像素表示。例如:。在不知道分辨率的情况下,不可能以英寸或毫米为单位计算宽度,但人们普遍认为,在HTML上下文中,1个像素等于1/96英寸,因此:

1 in. = 25.4 mm = 96 px.

  CSS中可以使用其他几个度量单位(请参阅W3C关于CSS单位的规定)。

  pica (pc)是指小于1/6英寸的头发,包含12个点。Picas通常用于表示固定的水平测量值,最常见的是列宽。

1 in. = 25.4 mm = 6 pc.

  上述测量单位为绝对值;还存在几个相对测量单位:

  • emphemeral unitem)是一个CSS单位,代表元素字体的大小。如果您有一个字体大小定义为12pt的元素,则1em=12pt。最初,em等于大写字母M的宽度,这就是它的名字来源。
  • root emrem)代表HTML文件根元素的字体大小。1 rem的大小与为元素定义的字体大小无关。
  • ex单位与字体的x高度相关。x高度大致是a、c、m或o等小写字母的高度。ex单位很少使用。
  • 也可以将宽度表示为可用宽度的百分比(%

  查看measurements.html文件内容:

<html>
    <head><title>Measurementstitle>
        <style>
            div { border: solid black 1px; }
        style>
    head>
    <body>
        <h1>Measurementsh1>
        <div>Div with width no width specifieddiv>
        <div style="width: 4in">Div with width 5indiv>
        <div style="width: 10cm">Div with width 10cmdiv>
        <div style="width: 100mm">Div with width 100mmdiv>
        <div style="width: 300px">Div with width 300pxdiv>
        <div style="width: 300pt">Div with width 300ptdiv>
        <div style="width: 25pc">Div with width 25pcdiv>
        <div style="width: 25em">Div with width 25emdiv>
        <div style="font-size: 6pt; width: 25em">Div with width 25emdiv>
        <div style="width: 25rem">Div with width 25remdiv>
        <div style="font-size: 6pt; width: 25rem">Div with width 25remdiv>
        <div style="width: 25ex">Div with width 25exdiv>
        <div style="font-size: 6pt; width: 25ex">Div with width 25exdiv>
        <div style="width: 60%">Div with width 60%div>
    body>
html>

  在这个HTML页面中,我们为每个

标签添加一个实心黑色边框,但是我们没有定义宽度。在我们这个例子中,我们使用不同的度量单位:4in,10cm,100mm,300px, 300pt, 25pc, 25em, 25rem, 25ex 和 60%.
  浏览器中显示的结果(如 图7.10)与使用pdfHTML从该HTML文件创建的PDF(C07E09_Measurements.java创建,如 图7.11)中的结果非常相似:
iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第10张图片

图7.10 度量样例(HTML)

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第11张图片

图7.11 度量样例(PDF)

  

Div with width 300px
的宽度为300px,是
Div with width 300pt
的300pt的四分之三(72/96)。300pt的宽度等于25pc的宽度。iText使用的默认字体大小为12pt。
Div with width 25em
使用默认字体大小,宽度为25em,也就是12pt x 25=300pt。对于
Div with width 25rem
来说也是这样。但是当我们改变字体大小为6pt,那么对于
Div with width 25em
来说宽度则变成了一半(150pt)
。但是
Div with width 25rem
并不会改变宽度,因为rem跟根元素有关。ex跟字体大小有关,所以
Div with width 25ex
的宽度是
Div with width 25ex
的2倍。

7. 如何将ASP或JSP页面转换为PDF?

  pdfHTML插件解析HTML和CSS。一句话解释就是这样。

  ASP.Net、JSP、MVC、Razor、Struts、Spring等都是iText和pdfHTML 100%不知道的HTML框架。DataGridViews、Repeaters、Templates、Views等也是如此,它们都是特定于框架的抽象。解释ASP、JSP或任何其他语法并不取决于pdfHTML或iText。

  选择HTML框架并获得HTML文件是开发者的责任。如果您有一个ASP文件,请通过ASP框架运行它以创建HTML。pdfHTML插件将接受HTML转换为PDF。

8. 如何将包含阿拉伯语/希伯来语字符的HTML转换为PDF?

  这个问题其实也是pdfHTML中支持哪些语言的问题?答案可以在第6章中找到,但这个问题被问得太频繁了,因此在常见问题解答部分增加一个条目是合理的。这也是一个提供额外示例的机会。

  在C07E14_SayPeace,java样例中,我们转换saypeace.html文件转换为PDF。如图7.12所示

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第12张图片

图7.12 HTML中各种语言的say peace

  我们在本文中看到了英语、阿拉伯语和希伯来语。我们将为每种语言使用不同的字体文件。

public static final String[] FONTS = {
    "src/main/resources/fonts/noto/NotoSans-Regular.ttf",
    "src/main/resources/fonts/noto/NotoNaskhArabic-Regular.ttf",
    "src/main/resources/fonts/noto/NotoSansHebrew-Regular.ttf"
};

  我们将创建一个仅使用这些字体文件的FontProvider实例,并将此FontProvider用作转换器属性。代码如下:

public void createPdf(String src, String[] fonts, String dest) throws IOException {
    ConverterProperties properties = new ConverterProperties();
    FontProvider fontProvider = new DefaultFontProvider(false, false, false);
    for (String font : fonts) {
        FontProgram fontProgram = FontProgramFactory.createFont(font);
        fontProvider.addFont(fontProgram);
    }
    properties.setFontProvider(fontProvider);
    HtmlConverter.convertToPdf(new File(src), new File(dest), properties);
}

  转的PDF的文本被渲染正确,如图7.13所示:

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第13张图片

图7.13 PDF中各种语言的say peace

  如果您使用了适当的字体,并且得到了不同的结果,即希伯来语和阿拉伯语文本是从左到右呈现的,而不是从右到左呈现的,那么您已经忘记将pdfCalligraph插件添加到CLASSPATH中。

9. 如何在将HTML转换为PDF时使特定子字符串加粗?

  问题:我正在使用Java中的iText将HTML转换为PDF。我想要一个特定的段落,其中一些单词为粗体,一些单词为Bold+下划线,作为字符串传递给Java代码,并使用iText库转换为PDF。我找不到合适的方法。我该怎么做?

  回答:如果要将XHTML转换为PDF,则需要iText+XMLWorker。

  最简单的示例如下:

public void createPdf(String file) throws IOException, DocumentException {
    // step 1
    Document document = new Document();
    // step 2
    PdfWriter writer =
        PdfWriter.getInstance(document, new FileOutputStream(file));
    // step 3
    document.open();
    // step 4
    XMLWorkerHelper.getInstance().parseXHtml(writer, document,
            new FileInputStream(HTML));
    // step 5
    document.close();
}

  注意,在本例中,HTML文件作为FileInputStream传递。如果需要传递字符串。这意味着你必须这样做:

XMLWorkerHelper.getInstance().parseXHtml(writer, document,
        new StringReader("

The String I want to render to PDF

"
));

10. 如何将多个HTML文件解析为一个PDF?

  这个问题有两个答案。答案#2通常比答案#1好,但我给出了两个选项,因为在某些特定情况下,答案#1是首选的。

  测试数据:我们重用之前样例中的HTML文件:

  • invitation.html
  • sxsw.html,和
  • movies.html

  我们将这些文件的路径放在一个数组中:

public static final String[] SRC = {
    String.format("%sinvitation.html", BASEURI),
    String.format("%ssxsw.html", BASEURI),
    String.format("%smovies.html", BASEURI)
};

  我们将使用pdfHTML插件来解析这三个文件,因此我们需要一个PDF文件。

  答案1:在C07E01_CombineHtml.java示例中,我们将每个HTML转换为内存中单独的PDF文件。然后使用PdfMerger将这些文件合并为一个PDF。

public void createPdf(String baseUri, String[] src, String dest) throws IOException {
    ConverterProperties properties = new ConverterProperties();
    properties.setBaseUri(baseUri);
    PdfWriter writer = new PdfWriter(dest);
    PdfDocument pdf = new PdfDocument(writer);
    PdfMerger merger = new PdfMerger(pdf);
    for (String html : src) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfDocument temp = new PdfDocument(new PdfWriter(baos));
        HtmlConverter.convertToPdf(new FileInputStream(html), temp, properties);
        temp = new PdfDocument(
            new PdfReader(new ByteArrayInputStream(baos.toByteArray())));
        merger.merge(temp, 1, temp.getNumberOfPages());
        temp.close();
    }
    pdf.close();
}

  在本例中,我们介绍了PdfMerger类。这个类可以将不同的PDF文件以每页为单位合并到主PdfDocument中,在本例中为变量pdf。如果您有三个单页PDF文档,PdfMerger可以将它们合并为一个具有三页的PDF,无论它们包含多少内容,都可以保持页面原样。原始PDF中半满的页面将在合并的PDF中为半满。
  您可以在的itext7学习笔记——第6章中找到有关PdfMerger类的更多信息。

  在本例中,结果是一个包含9页的PDF文档:1页包含invitation.html的内容,2页包含sxsw.html的内容,以及6页movies.html内容。

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第14张图片

图7.14 使用PdfMerger合并不同的PDF文件

  如果你想避免有太多的空白,就像我们的例子第1页上的情况一样,你需要看看这个问题的第二个答案。

  答案2:在C07E02_CombineHtml2.java示例中,我们将不同的HTML文件解析为一系列iText元素。我们将所有这些元素添加到一个PDF文档中。代码如下:

public void createPdf(String baseUri, String[] src, String dest) throws IOException {
    ConverterProperties properties = new ConverterProperties();
    properties.setBaseUri(baseUri);
    PdfWriter writer = new PdfWriter(dest);
    PdfDocument pdf = new PdfDocument(writer);
    Document document = new Document(pdf);
    for (String html : src) {
        List elements =
            HtmlConverter.convertToElements(new FileInputStream(html), properties);
        for (IElement element : elements) {
            document.add((IBlockElement)element);
        }
    }
    document.close();
}

  在本例中,我们使用了第1章中的技术,但我们没有将从一个HTML文件生成的元素添加到一个PDF中,而是循环三个不同的HTML文件,将这些文件解析为元素列表,然后将这些元素添加到同一个Document实例中。

  这导致PDF文档只有8页,而不是之前的9页。

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第15张图片

图7.15 将不同的HTML文件解析为iText元素

  在第一页上面,invitation.html文件的内容后面紧跟着swsx.html的内容。sxsw.html内容继续在第二页显示,并且后面紧跟着movies.html的内容。

11.如何将某些HTML实体(如箭头)呈现为PDF?

  当我们在第6章中讨论字体时,我们提到Symbol和ZapfDingbats不能很好地处理HTML,当您需要特殊符号时,其他字体更适合。当我们讨论国际化时,我们注意到我们可以渲染希腊字符,而不需要使用Symbol这样的字体。C07E12_SpecialCharacters.java示例显示,我们不需要ZapfDingbats来渲染箭头、笑脸或任何其他特殊符号。可以使用其他字体,如FreeSans和FreeSerif。

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第16张图片

图7.16 PDF中特殊的字符

  HTML代码使用HTML实体来表示这些特殊符号:

public static final String HTML = "" +
    "" +
    "

Special symbols: " + "← ↓ ↔ ↑ → € © ☺

"
+ "";

  pdfHTML插件完全能够解析此类实体。createPdf()方法中不需要特殊设置:

public void createPdf(String html, String dest) throws IOException {
    HtmlConverter.convertToPdf(html, new FileOutputStream(dest));
}

  如果应用程序在Windows计算机上运行,还可以使用系统字体,如symbol.ttf和几种WebDings和WingDings字体(如果您需要符号或特殊字符)。

12. 为什么由于许可限制,我不能嵌入字体?

  在回答这个具体的问题之前,我们看一下另一个问题Do I need a license for Windows fonts when using iText?

  就像所有软件(包括iText)一样,字体都有许可证,但有不同类型的许可证。

  • 你拥有的字体有一个像SIL这样的开放字体许可证(这是第一个想到的字体许可证,因为这是我们在第6章中使用的Cardo字体的许可证),但还有许多其他许可证允许你完全免费使用字体。
  • 你拥有的是专有的,因为你不能重新分发它们,但它们允许将字体嵌入文档中。例如:MS Windows附带的字体是专有的。您不允许复制它们并免费发货,但是,这些字体中的大多数可能嵌入在文档文件中。嵌入允许字体随文档移动。嵌入式字体只能用于打印、预览和在某些情况下编辑嵌入字体的文档。(请参阅Microsoft常见问题解答中的字体重新分发和许可问题)。
  • 如果您想使用和/或嵌入某些字体,则需要完全(付费)许可证。如果我没有记错的话,您可以下载为Adobe Acrobat/Reader字体包的字体只能在Acrobat环境中使用。不允许使用Adobe未销售的软件将其嵌入文档中。
  • 有些字体有一些限制,根本不允许嵌入字体。

  你应该检查你使用的每种字体的字体许可证。让我们看两个例子。

  样例1:Arial(宋体)

  Arial字体是蒙纳公司( Monotype Imaging Corporation)创造的。蒙纳终用户许可协议(Monotype Imaging EULA)声明:

You may embed the Font Software only into an electronic document that (i) is not a Commercial Product, (ii) is distributed in a secure format that does not permit the extraction of the embedded Font Software, and (iii) in the case where a recipient of an electronic document is able to Use the Font Software for editing, only if the recipient of such document is within your Licensed Unit.
您只能将字体软件嵌入电子文档中,该电子文档(i)不是商业产品,(ii)以不允许提取嵌入字体软件的安全格式分发,以及(iii)如果电子文档的接收者能够使用字体软件进行编辑,则该文档的接收者必须在您的许可单位内。

  如果你在C:\\Windows\Fonts\目录中有arial.ttf,您可能没有从Monotype获取字体。它可能是随您的Microsoft Windows合法副本一起提供的,Monotype可能已根据不太严格的许可证将其字体许可给Windows。

  让我们右击点击arial.ttf文件,更进一步查看相关属性:

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第17张图片

图7.17 arial.ttf的属性

  我们幸运:字体嵌入性设置为“可编辑”。这意味着我们可以在文档中嵌入字体,不仅可以打印和(预)查看文档,还可以编辑文档(例如编辑表单字段)。此字体程序的完整许可如下所示:

Microsoft supplied font. You may use this font to create, display, and print content as permitted by the license terms or terms of use, of the Microsoft product, service, or content in which this font was included. You may only (i) embed this font in content as permitted by the embedding restrictions included in this font; and (ii) temporarily download this font to a printer or other output device to help print content. Any other use is prohibited.
Microsoft提供的字体。您可以使用此字体创建、显示和打印包含此字体的Microsoft产品、服务或内容的许可条款或使用条款允许的内容。您只能(i)在本字体中包含的嵌入限制允许的内容中嵌入本字体;以及(ii)将该字体临时下载到打印机或其他输出设备以帮助打印内容。禁止任何其他用途。

  只要使用的arial.ttf在我们购买的Windows许可证的上下文中,我们就可以使用这种字体。这意味着我们不允许把arial.ttf复制到另一台计算机,例如,我们不允许将此字体复制到Linux计算机。如果我们需要一种可以分发的字体(例如iText分发了12种字体,可以用pdfHTML嵌入到PDF文件中),我们应该寻找具有更宽松许可证的替代字体,例如OpenSans、OpenSerif和OpenMono。

  样例2:Celtic Garamond the 2nd

  一位iText用户希望在非商业环境中的PDF中使用字体Celtic Garamond the 2nd,但每当他尝试嵌入该字体时,都会引发以下异常:

Exception in thread "main" com.itextpdf.kernel.PdfException:
    CelticGaramondthe2ndRegular cannot be embedded due to licensing restrictions.
    at com.itextpdf.kernel.font.PdfType0Font.(PdfType0Font.java:108)
    at com.itextpdf.kernel.font.PdfFontFactory.createFont(PdfFontFactory.java:235)
    at com.itextpdf.layout.font.FontProvider.getPdfFont(FontProvider.java:303)
    at com.itextpdf.layout.font.FontSelectorStrategy.getPdfFont(
        FontSelectorStrategy.java:84)
    at com.itextpdf.layout.font.ComplexFontSelectorStrategy.nextGlyphs(
        ComplexFontSelectorStrategy.java:85)
    at com.itextpdf.layout.renderer.TextRenderer.resolveFonts(TextRenderer.java:1145)
    at com.itextpdf.layout.renderer.LineRenderer.resolveChildrenFonts(
        LineRenderer.java:1099)
    at com.itextpdf.layout.renderer.LineRenderer.layout(LineRenderer.java:128)
    at com.itextpdf.layout.renderer.ParagraphRenderer.layout(ParagraphRenderer.java:188)

  .TTF文件附带的readme.txt文件听起来很随意:

This font is made by Levi and may be used free of charge for non-commercial projects. Please contact me if you plan to use it for other purposes. It also may be distributed free of charge on any websites provided this file is intact.
此字体由Levi制作,可免费用于非商业项目。如果您打算将其用于其他用途,请与我联系。它也可以在任何网站上免费分发,前提是该文件完好无损。

  不幸的是,字体属性告诉我们:

iText7高级教程之html2pdf——7.关于pdfHTML经常问的问题_第18张图片

图7.18 Celtic Garamond the 2nd的属性

  你可能会假设,有了宽松的许可证声明,在非商业环境中使用这种字体不会有任何法律问题。然而,从技术角度来看,不允许在文档中嵌入这种字体。字体属性明确表示字体嵌入性为“受限”:这解释了iText引发的异常。不允许嵌入字体。

13. 为什么我的PDF缺少几个字符?

  尽管有大量关于如何使用字体文件以及如何使用不同语言的文本创建文档的文档,但人们仍然在用许多不同的变体提出相同的问题。这就是为什么这个单独的条目是用不同的措辞来回答之前多次回答的同一个问题。

  缺少字符的原因很简单:您没有提供能够呈现这些字符的字体。如何解决这个问题?这在第6章中进行了解释,以及在问题Which languages are supported in pdfHTML?的答案中.

iText7高级教程之html2pdf教程源码下载-CSDN

本章代码资源下载地址:

  1. 关注我的微信公众号CuteXiaoKe,点击代码资源-iText官网代码即可
  2. 或者直接点击微信文章

你可能感兴趣的:(iText,java,java,iText7,pdf)