尝试将简单的 UTF16 字符嵌入手动创建的 PDF 但失败
Posted
技术标签:
【中文标题】尝试将简单的 UTF16 字符嵌入手动创建的 PDF 但失败【英文标题】:Trying to embed simple UTF16 character into manually created PDF but failing 【发布时间】:2021-09-26 23:38:33 【问题描述】:我正在尝试手动创建 PDF 文档(使用 github 上的 PDFGen C 代码)。这是在存储空间有限的小型设备上。
在我想嵌入(比如)Unicode Ohms 字符 (U+2126) 之前,一切正常。
下面是我正在使用的测试文件,它应该在“H”之后显示带有欧姆符号的“Hello”。
但是,它实际上显示“H!&ello”。
%PDF-1.4
<hex chars removed>
1 0 obj
<< /Pages 2 0 R /Type /Catalog >>
endobj
2 0 obj
<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >>
endobj
3 0 obj
<< /Contents 4 0 R /MediaBox [ 0 0 500 800 ] /Parent 2 0 R /Resources 5 0 R /Type /Page >>
endobj
4 0 obj
<< /Length 57 >>
stream
BT /F1 24 Tf 175 720 Td <FEFF004821260065006C006C006F> Tj ET
endstream
endobj
5 0 obj
<< /Font << /F1 6 0 R >> >>
endobj
6 0 obj
<< /BaseFont /Courier /Subtype /Type1 /Type /Font >>
endobj
xref
0 7
0000000000 65535 f
0000000015 00000 n
0000000064 00000 n
0000000123 00000 n
0000000229 00000 n
0000000335 00000 n
0000000378 00000 n
trailer << /Root 1 0 R /Size 7 /ID [<89311a609a751f1666063e6962e79bd5><89311a609a751f1666063e6962e79bd5>] >>
startxref
448
%%EOF
我只能假设我的 Unicode 十六进制字符串 <FEFF004821260065006C006C006F>
格式错误。
还是字体定义不正确?
还是我对如何嵌入 Unicode 的理解有误?
我最终不想要嵌入任何字体,因为我没有存储空间或处理能力。我只想添加 Unicode 字符并依靠 PDF 渲染器来确定如何使用默认的 Courier 字体显示它们。
这可能吗?
提前感谢您提供任何帮助/建议/cmets。
更新
在以下一些有用的建议之后,我现在已经设法实现了我所需要的。
我修改了我的代码,以便在 Courier 和 Symbol 之间按字符切换字体,现在支持(几乎)所有标准字符。
我还添加了一些字符缩放以保持符号字符与 Courier 字体对齐,但最终结果对我有用 :)
这是我的测试 PDF 的图像...
【问题讨论】:
【参考方案1】:奇怪的是原始 PC IBM 437 代码集包含 Ω wiki note i [03A9] (234) 但没有送达 Courier ?? 您可以尝试将您需要的少数字符编码为嵌入的子集符号字体,并且很可能使用 ascii(7bit) 或 ansi(8bit) 来实现,但对于您的少数字符来说开销将是巨大的。
更简单的尝试将字体(根据目标字符的需要)切换为Symbol
字体,它可能看起来像这样
附:代码不需要是“单词”双打,只有 256 个字符。
<< /BaseFont /Symbol /Subtype /Type1 /Type /Font >>
BT /F2 24 Tf 175 720 Td <4857657C7C6F20766FC27C64> Tj ET
通过交替快递和符号,您将获得您想要的
在您的代码中,它可能类似于(包含转换)
BT
/F0 24 Tf 1 0 0 1 0 .0675 Tm (H) Tj
ET
BT
/F1 24 Tf 1 0 0 1 14.4 .0675 Tm <003a> Tj
ET
BT
/F0 24 Tf 1 0 0 1 32.832 .0675 Tm (ello) Tj
ET
请注意,我的编辑器使用 F0 表示 Courier,F1 表示符号(以 0 为底更正常)
它还使用了一种稍微不同的代码方法,将 Omega 定义为<003a>
在这里,我正在调整 Windows 记事本中的文本,以观察编译 (Ctrl+S) 如何移动 Omega 字符间距,同时在预览器中观看它横向滑动。另请注意,原始符号字体中的 大写 Omega 为 W
!!
所以我的代码替换修复看起来像这样(通过删除空格和换行符,您可以轻松使它看起来更接近您的,并且更精简)
%PDF-1.4
%µ¶
1 0 obj
<<
/Pages 2 0 R
/Type /Catalog
>>
endobj
2 0 obj
<<
/Count 1
/Kids [ 3 0 R ]
/Type /Pages
>>
endobj
3 0 obj
<<
/Contents 4 0 R
/MediaBox [ 0 0 500 800 ]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 5 0 R
/F2 6 0 R
>>
>>
/Type /Page
>>
endobj
4 0 obj
<<
/Length 133
>>
stream
q
BT
/F1 24 Tf
1 0 0 1 175 720 Tm
(H) Tj
ET
BT
/F2 24 Tf
1 0 0 1 189 720 Tm
(W) Tj
ET
BT
/F1 24 Tf
1 0 0 1 206 720 Tm
(ello) Tj
ET
Q
endstream
endobj
5 0 obj
<<
/BaseFont /Courier
/Subtype /Type1
/Type /Font
>>
endobj
6 0 obj
<<
/BaseFont /Symbol
/Subtype /Type1
/Type /Font
>>
endobj
xref
0 7
0000000000 65536 f
0000000016 00000 n
0000000070 00000 n
0000000136 00000 n
0000000307 00000 n
0000000494 00000 n
0000000569 00000 n
trailer
<<
/Size 7
/Root 1 0 R
/ID [ <89311A609A751F1666063E6962E79BD5> <EE408A115072E92E3A34C8BB8BDC6AE6> ]
>>
startxref
643
%%EOF
【讨论】:
是的,这就是我现在正在研究的解决方案……它似乎可以满足我的需求。非常感谢:)【参考方案2】:你做不到。
注意:您要插入 Unicode 字符(不是 UTF-16,它只是 Unicode 的众多表示/编码之一)。
没有字体包含所有字形,据我所知,只有少数 Latin-1 字体对于 PDF 是安全的(并且是必需的)。注意:此类字体需要 Latin-1 编码(与所有其他字体相反,这只是“pre Unicode epoch”的可移植性问题)。一个额外的问题。 Type1 使用字形索引,这可能与 Unicode Codepoints 不同(实际上,我认为它们总是不同的)。 IIRC Adobe 有一些关于此的文档。而且 type1 几乎不支持了,也许 2021 年的项目最好不要使用它。
您可能假设人们将使用 Microsoft Windows,因此您可以使用 Symbol 字体(并使用 Omega,而不是 Ohm,它可能用相同的字形表示)。但在这种情况下,您正在创建“非便携式”便携式文档格式 (PDF)。
【讨论】:
好的,看来我只能支持 PDF 规范附件 D 中定义的字符/字体集。必须按字符切换字体以上是关于尝试将简单的 UTF16 字符嵌入手动创建的 PDF 但失败的主要内容,如果未能解决你的问题,请参考以下文章
用于在 linux 上搜索 utf16le 中的字符串的 Hexeditor