有个思源宋体的字体使用疑惑,请大佬指点 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bard99
V2EX    Java

有个思源宋体的字体使用疑惑,请大佬指点

  •  
  •   bard99 2023-08-16 15:33:31 +08:00 2921 次点击
    这是一个创建于 837 天前的主题,其中的信息可能已经有所发展或是发生改变。

    U+2f04

    U+4e59 乙

    在使用 itext 的 html2pdf 生成 PDF 文件,发现一个奇怪的问题。 举个例子,我的原始文本是:乙方。这个乙方就是输入法正常打出来的乙方,拼音:yifang 。Unicode 为 U+4e59 。

    但是生成的 PDF 文件,却变成了:。Unicode 为 U+2f04 。拼音查不出来,好像因为是一个部首?

    我是用的思源宋体的粗体,然后产生了这个问题。后面我换了一个字体,狮尾四季春。PDF生成的文字就正常了,生成的也是乙方。拼音:yifang 。Unicode 为 U+4e59 。

    我去查了一下,确实这是 2 个字符:

    但是思源宋体也是同时有这 2 个字符:

    那导致这个转换不一致的原因是什么呢?

    1. 我看了下 html2pdf 的源码 debug ,找了半天没找到关于字体这里转换字符的逻辑。
    2. 但是我想了下,原始文本是乙方,乙的 Unicode 是 U+4e59 ,那应该 html2pdf 在思源宋体里面找 U+4e59 编码的字符使用就好了,但这里不应该会找错啊?

    困扰了半天了,求助下了解的大佬~

    17 条回复    2023-08-16 19:59:40 +08:00
    tabris17
        1
    tabris17  
       2023-08-16 16:00:10 +08:00   1
    应该是 iText 的 bug
    我用字体工具查看了思源宋体,发现代码点$2F04,$4E59 共用一个字形,可能 iText 在处理字体输出后就取了小的那个 Unicode 码
    NessajCN
        2
    NessajCN  
       2023-08-16 16:05:41 +08:00
    你是怎么查看转换完的 pdf 的字符编码的?
    bard99
        3
    bard99  
    OP
       2023-08-16 16:13:10 +08:00
    @tabris17 大佬,怎么看是共用了一个字型呢?
    bard99
        4
    bard99  
    OP
       2023-08-16 16:14:56 +08:00
    @NessajCN 直接复制 PDF 的文本出来,然后就可以查询了:
    我帖子里用的是 birdfont: https://birdfont.org/
    mw2c
        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 处理
    tabris17
      &nbp; 6
    tabris17  
       2023-08-16 16:15:46 +08:00
    @bard99 https://font.qqe2.com/ 在线字体编辑器
    bard99
        7
    bard99  
    OP
       2023-08-16 16:18:51 +08:00
    @tabris17 难道上面截图里,表示的是 2f04 引用了 4e59 的字型?感觉可以说得通啊!
    bard99
        8
    bard99  
    OP
       2023-08-16 16:21:05 +08:00
    @tabris17 #6
    看到了,果然共用了字型!
    NessajCN
        9
    NessajCN  
       2023-08-16 16:22:23 +08:00
    @bard99 你从 pdf 里直接拷贝是不能准确到编码的,只能靠识别,所以就是你 copy 的时候识别错了
    bard99
        10
    bard99  
    OP
       2023-08-16 16:31:33 +08:00
    @NessajCN #9 感谢指正,试了下确实如你所说。 实际上我中间省略了一些过程,我是 debug 过程中,使用 itext 的 PdfReaderContentParser 读取生成后 PDF 文件,然后取出文本内容,在这里拿到了异常的 u2f04 。
    uleh
        11
    uleh  
       2023-08-16 16:32:18 +08:00
    @NessajCN 文本型的 PDF 是可以直接复制的。全图的那种才是 OCR 识别
    NessajCN
        12
    NessajCN  
       2023-08-16 16:37:59 +08:00   1
    @bard99 pdf 呈现内容的方式是这样的:拿到字体绘制逻辑,然后根据实际的字显示字形。而 pdf 文件里本身只会存这种「显示方式」也就是只会存字形,除非它另外也存了一份 toUnicode 映射,这个是可存可不存的。所以你 copy pdf 出现编码不对是很正常的。这是 pdf 为了应付盗版山寨而特意为之的行为。
    bard99
        13
    bard99  
    OP
       2023-08-16 17:30:13 +08:00
    @mw2c 这 2 篇文字涨知识了,感谢。然后我本地试了一下 4 种正规化的结果,打印如下:

    这个结果看上去,好像可以得出:
    - 只有「部首」字符(如:2f04 )在正规化后,可以变成正常的「单音」字符(如:4e59 )。
    - 而「单音」字符的正规化,得到的仍然是它本身。

    如果这 2 个结论对的话,在我的场景里,却是「单音」字符,转换后得到了「部首」字符,那就不符合这个结论了。
    tabris17
        14
    tabris17  
       2023-08-16 17:41:55 +08:00
    @bard99 如果是 NFC 的话,不至于换一个字体就正常了。

    可以查看一下狮尾四季春字体,2F04 和 4E59 两个字有没有共用一个字形,如果不是,则 BUG 的可能性更大一些
    mw2c
        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/
    bard99
        16
    bard99  
    OP
       2023-08-16 19:09:54 +08:00
    @tabris17 #14 刚用 fontstore 试了狮尾四季春、SiHei 字体,发现他们都没有给 2F04 编码添加字型!所以这 2 个字体生成的 PDF ,文字都是正常的,都是 4E59 编码的「乙」!
    bard99
        17
    bard99  
    OP
       2023-08-16 19:59:40 +08:00   1
    @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 编码值则从原始文本获取,这样就关联正确了!
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     861 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 19:24 PVG 03:24 LAX 11:24 JFK 14:24
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86