用 libharu 生成对账单,英文和数字都正常,中文全是方块。文件能打开,就是认不出字。
这不是编码写错,是字体没嵌进去。PDF 阅读器只认文件里带的字体,系统装没装思源黑体跟它没关系。
libharu 要先打开 CJK 支持
HPDF_UseCNSFonts 和 HPDF_UseCNSEncodings 这两个调用,要在创建文档之后、写内容之前执行。漏了这一步,后面设中文字体直接返回错误码。
更稳的做法是加载 TTF:HPDF_LoadTTFontFromFile 指定字体文件路径,最后一个参数传 true 表示嵌入。思源黑体、文泉驿都能用,注意字体授权允不允许商用。
UTF-8 字符串不能直接往里塞,得转成字体对应的编码,或者走 libharu 的 UTF-8 接口。转错一步,出来就是问号。
嵌入整份字体会让文件变大,一份中文字体十几兆。用子集化只带用到的字形,体积能压到几百 K,代价是生成时多花一点 CPU。
读 PDF 是另一套库
生成用 libharu 或者 PDFium,读取和提取文字常用 poppler。Windows 上编译 poppler 比较折腾,vcpkg 装完省事不少。
扫描件提取不到文字很正常,那是图片,得先做 OCR。判断方法很简单:看页面里有没有文字对象,没有就是纯图。
还有个小问题:中文和数字用同一款字体,数字会显得宽。分开设两种字体,或者直接用等宽数字的思源,排版更整齐。
生成完别只看文件大小,用不同阅读器各打开一次,福昕和 Chrome 内置渲染器对字体的处理不完全一致。
不推荐自己拼 PDF 字节
PDF 有对象表、交叉引用表和压缩流,手写一遍能跑,改一次就崩。中文还要处理 CMap,工作量比调库大得多。
选型上,只是导出报表,libharu 够用;要渲染现有 PDF 或者做预览,PDFium 更合适,Chrome 用的就是它。
最后一句话:中文乱码先查字体嵌入,再看编码,这两步能解决九成问题。