1

I have the following contents in the same PDF page, in different ObjectX:

First:

[(some text)] TJ ET Q
[(some other text)] TJ ET Q

Very simple and basic so far...

The second:

[( H T M L   E x a m p l e)] TJ ET Q
[( S o m e   s p e c i a l   c h a r a c t e r s :   <   ¬   ¬   ¬   &   ט   ט   ©   >   \\ s l a s h   \\ \\ d o u b l e - s l a s h   \\ \\ \\ t r i p l e - s l a s h  )] TJ ET Q

NOTE: It is not noticeable in text above, but:

'H T M L E x a m p l e' is actually 0H0T0M0L0[32]0E0x0a0m0p0l0e where each 0 is a literal value 0 == ((char)0) so if I ignore all the 0 values, this actually turns to be like the upper example...

Some Bytes:

htmlexample == [0, 72, 0, 84, 0, 77, 0, 76, 0, 32, 0, 69, 0, 120, 0, 97, 0, 109, 0, 112, 0, 108, 0, 101]
<content>  == [0, 32, 32, -84, 0, 32, 32, -84, 0, 32, 32, -84, 0, 32, 0, 38, 0, 32, 0, -24, 0, 32, 0, -24, 0, 32, 0, -87, 0, 32, 0]

But in the next line I need to combine every two bytes into a char because of the following:

< ¬ ¬ ¬...> is actually <0[32][32]¬0[32][32]¬0[32][32]¬...> where the combination of [32]¬ is €</p>

The problem I'm facing is not the conversion itself I use: new String(sb.toString().getBytes("UTF-8"),"UTF-16BE")

The problem is to know when to apply it and when to keep the UTF-8.

== UPDATE ==

The font used for the problematic Object is:

#7 0# {
    'Name' : "F4"
    'BaseFont' : "AAAAAE+DejaVuSans-Bold"
    'Subtype' : "Type0"
    'ToUnicode' : #41 0# {
        'Filter' : "FlateDecode"
        'Length' : 1679.0f
    } + Stream(5771 bytes)
    'Encoding' : "Identity-H"
    'DescendantFonts' : [#42 0# {
        'FontDescriptor' : #43 0# {
            'MaxWidth' : 2016.0f
            'AvgWidth' : 573.0f
            'FontBBox' : [-1069.0f, -415.0f, 1975.0f, 1174.0f]
            'MissingWidth' : 600.0f
            'FontName' : "AAAAAE+DejaVuSans-Bold"
            'Type' : "FontDescriptor"
            'CapHeight' : 729.0f
            'StemV' : 60.0f
            'Leading' : 0.0f
            'FontFile2' : #34 0# {
                'Filter' : "FlateDecode"
                'Length1' : 83036.0f
                'Length' : 34117.0f
            } + Stream(83036 bytes)
            'Ascent' : 928.0f
            'Descent' : -236.0f
            'XHeight' : 547.0f
            'StemH' : 26.0f
            'Flags' : 32.0f
            'ItalicAngle' : 0.0f
        }
        'Subtype' : "CIDFontType2"
        'W' : [32.0f, [348.0f, 456.0f, 521.0f, 838.0f, 696.0f, 1002.0f, 872.0f, 306.0f, 457.0f, 457.0f, 523.0f, 838.0f, 380.0f, 415.0f, 380.0f, 365.0f], 48.0f, 57.0f, 696.0f, 58.0f, 59.0f, 400.0f, 60.0f, 62.0f, 838.0f, 63.0f, [580.0f, 1000.0f, 774.0f, 762.0f, 734.0f, 830.0f, 683.0f, 683.0f, 821.0f, 837.0f, 372.0f, 372.0f, 775.0f, 637.0f, 995.0f, 837.0f, 850.0f, 733.0f, 850.0f, 770.0f, 720.0f, 682.0f, 812.0f, 774.0f, 1103.0f, 771.0f, 724.0f, 725.0f, 457.0f, 365.0f, 457.0f, 838.0f, 500.0f, 500.0f, 675.0f, 716.0f, 593.0f, 716.0f, 678.0f, 435.0f, 716.0f, 712.0f, 343.0f, 343.0f, 665.0f, 343.0f, 1042.0f, 712.0f, 687.0f, 716.0f, 716.0f, 493.0f, 595.0f, 478.0f, 712.0f, 652.0f, 924.0f, 645.0f, 652.0f, 582.0f, 712.0f, 365.0f, 712.0f, 838.0f], 160.0f, [348.0f, 456.0f, 696.0f, 696.0f, 636.0f, 696.0f, 365.0f, 500.0f, 500.0f, 1000.0f, 564.0f, 646.0f, 838.0f, 415.0f, 1000.0f, 500.0f, 500.0f, 838.0f, 438.0f, 438.0f, 500.0f, 736.0f, 636.0f, 380.0f, 500.0f, 438.0f, 564.0f, 646.0f], 188.0f, 190.0f, 1035.0f, 191.0f, 191.0f, 580.0f, 192.0f, 197.0f, 774.0f, 198.0f, [1085.0f, 734.0f], 200.0f, 203.0f, 683.0f, 204.0f, 207.0f, 372.0f, 208.0f, [838.0f, 837.0f], 210.0f, 214.0f, 850.0f, 215.0f, [838.0f, 850.0f], 217.0f, 220.0f, 812.0f, 221.0f, [724.0f, 738.0f, 719.0f], 224.0f, 229.0f, 675.0f, 230.0f, [1048.0f, 593.0f], 232.0f, 235.0f, 678.0f, 236.0f, 239.0f, 343.0f, 240.0f, [687.0f, 712.0f, 687.0f, 687.0f, 687.0f, 687.0f, 687.0f], 247.0f, [838.0f, 687.0f], 249.0f, 252.0f, 712.0f, 253.0f, [652.0f, 716.0f]]
        'Type' : "Font"
        'BaseFont' : "AAAAAE+DejaVuSans-Bold"
        'CIDSystemInfo' : {
            'Supplement' : 0.0f
            'Ordering' : "Identity" + Stream(8 bytes)
            'Registry' : "Adobe" + Stream(5 bytes)
        }
        'DW' : 600.0f
        'CIDToGIDMap' : #44 0# {
            'Filter' : "FlateDecode"
            'Length' : 10200.0f
        } + Stream(131072 bytes)
    }]
    'Type' : "Font"
}

There is no indication to the encoding type of the font.

== Update ==

As for the ToUnicode object, in the case of these font it is an unnecessary it should have been Identity-H but instead it is an X == X mapping here are some examples that goes from until FFFF:

<0000> <00ff> <0000>
<0100> <01ff> <0100>
<0200> <02ff> <0200>
<0300> <03ff> <0300>
<0400> <04ff> <0400>
<0500> <05ff> <0500>
<0600> <06ff> <0600>
<0700> <07ff> <0700>
<0800> <08ff> <0800>
<0900> <09ff> <0900>
<0a00> <0aff> <0a00>
<0b00> <0bff> <0b00>
<0c00> <0cff> <0c00>
<0d00> <0dff> <0d00>
<0e00> <0eff> <0e00>
<0f00> <0fff> <0f00>
<1000> <10ff> <1000>
<1100> <11ff> <1100>
....
....
....
<fc00> <fcff> <fc00>
<fd00> <fdff> <fd00>
<fe00> <feff> <fe00>
<ff00> <ffff> <ff00>

So the mapping is not in the ToUnicode object, but still other renderers can render it well!

Any Ideas?

4

2 回答 2

4

我使用: new String(sb.toString().getBytes("UTF-8"),"UTF-16BE")

问题是知道何时应用它以及何时保留 UTF-8。

OP 可能在检查了一些示例 PDF 文件之后假设 PDF 内容流中的字符串是使用 UTF-8 或 UTF-16BE 编码的。

这个假设是错误的。

PDF 允许一些标准的单字节编码(MacRomanEncodingMacExpertEncodingWinAnsiEncoding),它们都不是 UTF-8(由于不同编码之间的关系,尤其是 ASCII、Latin1 和 UTF-8,它们在遇到时可能会相互混淆样本有限)。此外,还允许使用许多预定义的多字节编码,其中一些确实与 UTF-16 相关。

但是 PDF 也允许使用完全自定义的编码,包括单字节和多字节!

eg this text 绘制操作

(ABCCD) Tj

对于具有这种编码的简单字体:

<<
 /Type /Encoding
 /Differences [ 65 /H /e /l /o ] 
>>

显示单词Hello

虽然这可能看起来像是一个人工构建的示例,但创建这样的自定义编码的过程(即,按照它们在页面或文档中首次出现的顺序将代码从某个起始值向上分配给字形)是相当的经常使用。

此外,OP当前的解决方案

如果您的字体对象具有 CMap,那么您将其视为 UTF-16,否则不会。

只适用于极少数文件,因为

a) 简单字体(使用单字节编码)也可以提供ToUnicode CMap 和 b) 复合字体 CMap 也不需要类似于 UTF,而是可以使用混合的多字节编码。

因此,无法对使用的字体信息进行深入分析,参见。PDF 规范ISO 32000-1的 9.5..9.9 。

PS关于OP的一些评论:

这:new String(sb.toString().getBytes("UTF-8"),"UTF-16BE")是问题如何解决的一个例子,而不是解决方案!无论我将数据视为 16 位还是 8 位,解决方案都是在获取字形时完成的

ToUnicode 映射是每个键 16 位(我见过的唯一的),

数据可能是混合数据,例如查看Adob​​e CMap 和 CIDFont 文件规范,此处 CMap 示例 9 包含该部分

4 begincodespacerange
<00> <80>
<8140> <9ffc>
<a0> <de>
<e040> <fbec>
endcodespacerange

这被解释为

图 6 显示了此示例中的代码空间定义如何包含两个单字节线性代码范围(<00>to<80><A0>to <DF>)和两个双字节矩形代码范围(<8140>to<9FFC><E040>to <FBFC>)。第一个双字节区域包括由 81 到 9F 的第一个字节值和 40 到 FC 的第二个字节值限制的所有代码。因此,输入代码<86A9>在区域内,因为两个字节都在边界内。该代码有效。输入代码<8210>不在区域内,即使它的第一个字节在 81 和 9F 之间,因为它的第二个字节不在范围内。该代码无效。第二个双字节区域也有类似的界限。

图 6 83pv-RKSJ-H 字符集编码的代码空间范围

于 2014-10-15T10:55:30.003 回答
0

好的,所以这似乎很复杂,而且这个错误的原因很愚蠢,尤其是在我这边,但是关于何时将字符视为UTF-16以及何时不处理,有一个教训需要学习。

我的问题不是在解析字体时,而是在渲染它们时。根据 Font 对象中指定的详细信息,您可以确定字体的类型并对其应用正确的逻辑。

于 2014-10-15T00:00:01.107 回答