通过 PHP 嵌入 PDF 字体 |编辑:如何解析 OpenType 字体以嵌入 PDF 中? [已关闭]

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

编辑:解析 OpenType 字体

经过@Olivier 和@KJ 的一些指点,我想这次我有一个正确的问题。

现在,我面临的主要问题是解析字体文件(即.otf)。 现在,我知道它们有这样的结构:https://ccjktype.fonts.adobe.com/wp-content/uploads/2012/10/atypi2012-afdko-hattori.pdf

另外,我发现 PDF 结构应该具有:

  • CID 键控字体
    • 其中包括 CMap 和 CIDFont 字典
  • CID 键控字体应该是一种复合字体,以便允许将一个或多个字节序列解码为字形
  • /FontFile3 条目应为 OpenType(对于 OTF)
  • CIDFont 需要具有 .notdef 将代码映射到不存在的字形的 CID0 描述符

所以,CMap 就在那里,现在的问题是 - 如何正确解析 OTF 并将它们嵌入到 PDF 中?

非常感谢 Olivier 和 KJ 为我指明了正确的方向,因为我不知道该去哪里。


这是出于学术目的,我并不是想在这里重新发明威尔,但我正在尝试制作一个合适的PDF验证器,因为没有(或者至少我找不到)。另外,我正在尝试在业余时间学习一些新东西,PDF 是列表中的下一个。

我遇到的难题是将字体嵌入到 PDF 中。我需要能够嵌入字体并扩展标准字体以包含非 ASCII 字符(扩展拉丁字符,如德语、法语、西班牙语、西里尔字符、俄语、乌克兰语、塞尔维亚语、阿拉伯语字符和印度教字符)。

我了解 TCPDF 和 FPDF 以及所有这些库,因此生成 PDF 不是问题,我只是想了解它的内部工作原理。

我正在阅读这里的官方文档:PDF32000.bookCID-Keyed技术说明甚至还查看了PostScript语言参考。我一生都无法弄清楚第 9 章(字体子章节)和附录 D 以及如何利用它们来嵌入字体,甚至扩展字体以包含多字节字符序列。

这是我到目前为止所得到的,请注意,现在所有内容都是手写的,字节偏移量都是手工计算的,以便了解在哪里以及什么影响了哪一部分,哪些封闭标签确实需要位于至少间隔一个空格。

<?php

$mypdf = "%PDF-1.7\n"; //9
$mypdf .= "%\u{01C7}\u{01C7}\u{01C7}\u{01C7}\n"; //10
$mypdf .= "1 0 obj\n<< /Type /Catalog /Pages 2 0 R /PageMode /UseNone >>\nendobj\n"; //67
$mypdf .= "2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 /MediaBox [0 0 300 300] /Resources << /F1 << /Type /Font /Subtype /Type1 /BaseFont /Times-Roman >> >> >>\nendobj\n"; //159
$mypdf .= "3 0 obj\n<</Type/Page/Parent 2 0 R/Contents 4 0 R >>\nendobj\n"; //59
$mypdf .= "4 0 obj\n<< /Length 51 >>\n";
$mypdf .= "stream\n";
$mypdf .= "BT\n";
$mypdf .= "/F1 24 Tf\n";
$mypdf .= "0 0 Td\n";
$mypdf .= "(Hello world!ČĆŠĐŽ) Tj\n";
$mypdf .= "ET\n";
$mypdf .= "\n";
$mypdf .= "endstream\n";
$mypdf .= "endobj\n";
$mypdf .= "xref\n";
$mypdf .= "0 4\n";
$mypdf .= "0000000000 65535 f \n";
$mypdf .= "0000000020 00000 n \n";
$mypdf .= "0000000088 00000 n \n";
$mypdf .= "0000000247 00000 n \n";
$mypdf .= "0000000306 00000 n \n";
$mypdf .= "trailer<< /Root 1 0 R /Size 4 >>\n";
$mypdf .= "startxref\n";
$mypdf .= "407\n";
$mypdf .= '%%EOF';

//echo strlen($mypdf);
file_put_contents('testpdf.pdf', $mypdf);

上述代码生成此 pdf。

The above code produces this pdf

提前谢谢大家。

php pdf font-embedding
1个回答
0
投票

嵌入 PDF 字体实际上是指在 PDF 中实际包含一个“字体文件”。

通常但并非总是,这是一个 TTF(True Type Font)文件。

然而,“字体”文件需要其内容字符“映射”,因此 CMAP 用于从二进制字节值进行转换,以便转换为字符串的编码字形。

字符串格式的类型可以是

(String Literals)
<UTF-16>
值。

将“文字”字符串从十进制 # 32 作为空格字符处理为数字 127=(),很容易,它们看起来像 ASCII 文本,所以 ABC。

但是,一旦我们进入 ANSI 和 ANSI Extended 的上限,最好对 \Octal 值使用文字字符串。就像这样

(\226\315\227\320\231)
。请注意,页面文本 ### 与查找表中使用的其他 CMAPS 类似,用于将“页内”内容转换为将用于渲染的内容。

这只是映射字符的多种方式之一。但更容易将它们的输入和输出视为 UTF 字符(它们不是)。这将出现在 PDF 版本 2.0 及更高版本中。目前,旧的名称字节对于许多欧洲语言来说是完全可行的。它被认为是不可取的,因为它无法满足任何更严格的 PDF/A 的“嵌入”验证。

注意,这不是嵌入字体或字体的子集,它只是将编码字符“映射”到渲染的“字形”中,并且因为我使用了自定义数字,所以结果并不总是如所见。我实际上创造了后来被称为“Mojibake”的东西。那根绳子

(He)(l)(lo w)(or)(ld!)15(\226\315\227\320\231)

提取时将按预期变为

Hello world!ČĆŠÐŽ
,但数字输出在另一个 PDF 中并非如 True Type Unicode 那样。

因此,在不同的 PDF 导入或构建/提取中,它可能会有所不同!

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