U+2f04 ⼄
U+4e59 乙
在使用 itext 的 html2pdf 生成 PDF 文件,发现一个奇怪的问题。 举个例子,我的原始文本是:乙方。这个乙方就是输入法正常打出来的乙方,拼音:yifang 。Unicode 为 U+4e59 。
但是生成的 PDF 文件,却变成了:⼄。Unicode 为 U+2f04 。拼音查不出来,好像因为是一个部首?
我是用的思源宋体的粗体,然后产生了这个问题。后面我换了一个字体,狮尾四季春。PDF 生成的文字就正常了,生成的也是乙方。拼音:yifang 。Unicode 为 U+4e59 。
我去查了一下,确实这是 2 个字符:
但是思源宋体也是同时有这 2 个字符:
那导致这个转换不一致的原因是什么呢?
困扰了半天了,求助下了解的大佬~
1
tabris17 2023-08-16 16:00:10 +08:00 1
应该是 iText 的 bug
我用字体工具查看了思源宋体,发现代码点$2F04,$4E59 共用一个字形,可能 iText 在处理字体输出后就取了小的那个 Unicode 码 |
2
NessajCN 2023-08-16 16:05:41 +08:00
你是怎么查看转换完的 pdf 的字符编码的?
|
4
bard99 OP |
5
mw2c 2023-08-16 16:15:45 +08:00
https://juejin.cn/post/6844903729439703053
https://gist.github.com/gettalong/d894c29b551917573c708cd5110653a0 找到这两篇文章,猜测是生成 PDF 时 itext 对文字进行了 NFC Normalization 处理 |
6
tabris17 2023-08-16 16:15:46 +08:00
@bard99 https://font.qqe2.com/ 在线字体编辑器
|
10
bard99 OP @NessajCN #9 感谢指正,试了下确实如你所说。 实际上我中间省略了一些过程,我是 debug 过程中,使用 itext 的 PdfReaderContentParser 读取生成后 PDF 文件,然后取出文本内容,在这里拿到了异常的 ⼄⽅ u2f04 。
|
12
NessajCN 2023-08-16 16:37:59 +08:00 1
@bard99 pdf 呈现内容的方式是这样的:拿到字体绘制逻辑,然后根据实际的字显示字形。而 pdf 文件里本身只会存这种「显示方式」也就是只会存字形,除非它另外也存了一份 toUnicode 映射,这个是可存可不存的。所以你 copy pdf 出现编码不对是很正常的。这是 pdf 为了应付盗版山寨而特意为之的行为。
|
13
bard99 OP @mw2c 这 2 篇文字涨知识了,感谢。然后我本地试了一下 4 种正规化的结果,打印如下: 。
这个结果看上去,好像可以得出: - 只有「部首」字符(如:2f04 )在正规化后,可以变成正常的「单音」字符(如:4e59 )。 - 而「单音」字符的正规化,得到的仍然是它本身。 如果这 2 个结论对的话,在我的场景里,却是「单音」字符,转换后得到了「部首」字符,那就不符合这个结论了。 |
14
tabris17 2023-08-16 17:41:55 +08:00
|
15
mw2c 2023-08-16 18:01:08 +08:00
@bard99 不好意思,我没仔细看帖子。应该是和 PDF 嵌入字体的方式有关。找到另一篇文章,作者也是换了一个字体就正常了。作者最后也有补充:
```PDF 内部存储文字并不是以 Unicode 的方式,而是有独立的编码方式 ANSI 、Identity-H 等。然后在用户复制文字的时候通过/ToUnicode 转换出 Unicode 编码。``` https://xobo.org/unicode-normalization-nfd-nfc-nfkd-nfkc/ |
16
bard99 OP @tabris17 #14 刚用 fontstore 试了狮尾四季春、SiHei 字体,发现他们都没有给 2F04 编码添加字型!所以这 2 个字体生成的 PDF ,文字都是正常的,都是 4E59 编码的「乙」!
|
17
bard99 OP @mw2c #15 @tabris17
我刚才做了几个实验,猜测找到了原因: 我使用 WPS 先生成 word ,再将 word 转成 PDF 。使用的是思源宋体: 然后使用 Python 脚本读取 PDF 内容和 Unicode 编码值: 发现 WPS 生成 PDF 的文字是正常的「 4e59 」编码! 对比之下,我之前使用 itext 生成的 PDF 。使用的是思源宋体: 使用 Python 脚本读取 PDF 内容和 Unicode 编码值: 这个 PDF 的文字是异常的「 2f04 」编码! 所以猜测可能就是 itext 的 bug: 1. 对于共用字型的字体,如:2f04 和 4e59 ,字型为「⼄」和「乙」。 2. itext 程序的 bug ,导致了在使用 html 生成 PDF 的过程中 3. 首先 html 文本传入的是 4e59 ,然后 itext 根据 4e59 找到了字体「乙-2f04/4e59 」 4. 然后写入生成 PDF 的过程中,使用了「乙」的字型,但错误的使用了 2f04 的 Unicode 编码! a. 对于 WPS 来说没有这个问题,会使用 4e59 的 Unicode 编码。 5. 所以原因,还是 itext 的问题! [至于具体的原因,还得 debug 去看了;看了半天没看出来逻辑在哪里...] ! a. 初步推测,itext 根据 4e59 找到了字体「乙-2f04/4e59 」,然后写入 PDF 时写入了「乙-2f04 」,很可能就是获取了第一个 Unicode 编码值!而 WPS 可能是写入了「乙」,然后 Unicode 编码值则从原始文本获取,这样就关联正确了! |