java - 使用 Java PDFBox 库编写俄语 PDF

标签 java pdf encoding

我正在使用名为 PDFBox 的 Java 库尝试将文本写入 PDF。它非常适合英文文本,但是当我尝试在 PDF 中写入俄文文本时,字母看起来很奇怪。看来问题出在使用的字体上,但我对此不太确定,所以我希望有人能指导我解决这个问题。这是重要的代码行:

PDTrueTypeFont font = PDTrueTypeFont.loadTTF( pdfFile, new File( "fonts/VREMACCI.TTF" ) );  // Windows Russian font imported to write the Russian text.
font.setEncoding( new WinAnsiEncoding() );  // Define the Encoding used in writing.
// Some code here to open the PDF & define a new page.
contentStream.drawString( "отделом компьютерной" ); // Write the Russian text.

WinAnsiEncoding 源代码是:Click here

-------------------- 2009 年 11 月 18 日编辑

经过一些调查,我现在确定这是一个编码问题,这可以通过使用名为 DictionaryEncoding 的有用 PDFBox 类定义我自己的编码来解决。

我不确定如何使用它,但这是我到目前为止尝试过的:

COSDictionary cosDic = new COSDictionary();
cosDic.setString( COSName.getPDFName("Ercyrillic"), "0420 " ); // Russian letter.
font.setEncoding( new DictionaryEncoding( cosDic ) );

这不起作用,因为我似乎以错误的方式填写字典,当我使用它编写 PDF 页面时,它显示为空白。

DictionaryEncoding 源代码是:Click here

最佳答案

长话短说 - 为了从 TrueType 字体输出 PDF 中的 unicode,输出必须包含大量详细且看似多余的信息。归根结底是这样的——在 TrueType 字体中,字形存储为字形 ID。这些字形 id 与特定的 unicode 字符相关联(IIRC,一个 unicode 字形在内部可能指代几个代码点——比如 é 指的是 e 和一个尖锐的重音——我的内存是模糊的)。 PDF 实际上没有 unicode 支持,只是说存在从字符串中的 UTF16BE 值到 TrueType 字体中的字形 ID 的映射,以及从 UTF16BE 值到 Unicode 的映射——即使它是身份。

  • 子类型 Type0 的字体字典
    • DescendantFonts 数组,其中包含如下所述的条目
    • 将 UTF16BE 值映射到 unicode 的 ToUnicode 条目
    • 编码设置为 Identity-H

我对自己的工具进行的单元测试之一的输出如下所示:

13 0 obj
<< 
   /BaseFont /DejaVuSansCondensed 
   /DescendantFonts [ 4 0 R  ]   
   /ToUnicode 14 0 R 
   /Type /Font 
   /Subtype /Type0 
   /Encoding /Identity-H 
>> endobj

14 0 obj
<< /Length 346 >> stream
/CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo <<
/Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def /CMapName /Adobe-Identity-UCS
def /CMapType 2 def 1 begincodespacerange <0000> <FFFF> endcodespacerange 1
beginbfrange <0000> <FFFF> <0000> endbfrange endcmap CMapName currentdict /CMap
defineresource pop end end

endstream % 请注意流的格式错误

  • 子类型 CIDFontTYpe2 的字体字典
    • CIDS 系统信息
    • 一个字体描述符
    • DW 和 W
    • 一个从字符 ID 映射到字形 ID 的 CIDToGIDMap

这是同一测试中的那个 - 这是 DescendantFonts 数组中的对象:

4 0 obj
<< 
   /Subtype /CIDFontType2 
   /Type /Font 
   /BaseFont /DejaVuSansCondensed 
   /CIDSystemInfo 8 0 R 
   /FontDescriptor 9 0 R 
   /DW 1000 
   /W 10 0 R 
   /CIDToGIDMap 11 0 R 
>>

8 0 obj
<< 
   /Registry (Adobe)
   /Ordering (UCS)
   /Supplement 0 
>>
endobj

我为什么要告诉你这个?它与 PDFBox 有什么关系?就是这样:坦率地说,PDF 中的 Unicode 输出是一个令人头疼的问题。 Acrobat 是在 Unicode 出现之前开发的,从一开始就使用没有 Unicode 的 CJK 编码是很痛苦的(我知道 - 我当时在 Acrobat 上工作)。后来加入了对 Unicode 的支持,但感觉真的像是被蒙上了一层阴影。人们希望您只说/Encoding/Unicode 并拥有以 thorn 和 y-dieresis 字符开头的字符串,然后就可以了。没有这样的运气。如果您不输入所有详细信息(实际上,Acrobat,嵌入一个 PostScript 程序以转换为 Unicode?WTH?),您将在 Acrobat 中得到一个空白页。我发誓,这不是我编造的。

在这一点上,我为一家独立的公司编写 PDF 生成工具(现在是.NET,所以它对你没有帮助),我把隐藏所有这些废话作为设计目标。所有文本都是 unicode - 如果您只使用那些与 WinAnsi 相同的字符代码,那么这就是您在幕后得到的。使用其他任何东西,您会得到所有其他东西。如果 PDFBox 为您完成这项工作,我会感到惊讶 - 这是一个严重的麻烦。

关于java - 使用 Java PDFBox 库编写俄语 PDF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1713751/

相关文章:

java - 为什么 TestNG 优先级功能未按预期顺序运行

r - 在 R 中保存多个 pdf 文件时出现问题

c - 以宽字符作为索引的全局 C 数组

android - 检测 Android 中 rss feed 的编码

java - Spring aop 切入点表达式访问方法返回类型

java - 构造函数对象上的 AspectJ 切入点

java - 将 Jersey 从 1.x 迁移到 2.x 时出现编译错误

java - 使用 Java 从 PDF 文件中提取大纲(或书签)

php - 将pdf文件上传到服务器并获取其url

ruby - Ruby 中的特殊编码问题 : ASCII ! = UTF-8 但 UTF-8 == ASCII