使用Java PDFBox库编写俄语PDF

Bra*_*rad 11 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.
Run Code Online (Sandbox Code Playgroud)

WinAnsiEncoding源代码是:点击这里

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

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

我不知道如何使用它,但这是我迄今为止尝试过的:

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

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

DictionaryEncoding源代码是:点击这里

pli*_*nth 5

长话故事是这样的 - 为了从TrueType字体中进行PDF格式的unicode输出,输出必须包含大量详细且看似多余的信息.它归结为 - 在TrueType字体内,字形存储为字形ID.这些字形ID与特定Unicode字符相关联的(和IIRC,一个unicode字形内部可指几个代码点 - 状é参照e和重音的 - 我的记忆是朦胧).PDF确实没有比其他Unicode支持地说,存在着一个字符串从utf16be应按值映射到字形ID的TrueType字体,以及从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
Run Code Online (Sandbox Code Playgroud)

endstream%请注意流的格式错误

  • 子类型CIDFontTYpe2的字体字典
    • 一个CIDSsytemInfo
    • 一个FontDescriptor
    • 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
Run Code Online (Sandbox Code Playgroud)

我为什么告诉你这个?它与PDFBox有什么关系?就是这样:坦率地说,PDF格式的Unicode输出是对手的皇家痛苦.Acrobat是在有Unicode之前开发的,从一开始就很难有没有Unicode的CJK编码(我知道 - 我当时在Acrobat上工作过).后来增加了Unicode支持,但它确实感觉它已经被搞砸了.人们希望你能说/ Encoding/Unicode,并且拥有以刺和y-dieresis字符开头的字符串,然后离开.没有这样的运气.如果你没有放入每一个详细的东西(实际上,Acrobat,嵌入一个PostScript程序来翻译成Unicode?WTH?),你​​会在Acrobat中得到一个空白页面.我发誓,我不是这样做的.

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


小智 1

尝试使用这种结构:

\n\n
PDFont font = PDType0Font.load( pdfFile, new File( "fonts/VREMACCI.TTF" ) );  // Windows Russian font imported to write the Russian text.\n// Some code here to open the PDF & define a new page.\ncontentStream.beginText();\ncontentStream.setFont(font, 12);\ncontentStream.showText( "\xd0\xbe\xd1\x82\xd0\xb4\xd0\xb5\xd0\xbb\xd0\xbe\xd0\xbc \xd0\xba\xd0\xbe\xd0\xbc\xd0\xbf\xd1\x8c\xd1\x8e\xd1\x82\xd0\xb5\xd1\x80\xd0\xbd\xd0\xbe\xd0\xb9" ); // Write the Russian text.\ncontentStream.endText();\n
Run Code Online (Sandbox Code Playgroud)\n