本文是对PDF Explained(by John Whitington)第七章《 Document Metadata and Navigation》的摘要式翻译,并加入了一些自己的理解。
本章我们讨论四个辅助数据,这些数据并不影响PDF的显示。
文档书签(也被称为文档大纲)是一棵由条目组成的树(条目通常是章节或段落的标题),点击这些条目可以跳转到文档中相应的位置。每个条目由文本和用来描述跳转链接的定位构成。
定位定义了PDF文档中的一个位置,由三部分组成,包括页码,页内位置以及显示缩放比率。定位可以被精确的定义,也可以通过名称引用进行定义。书签通常显示在文档旁边。
定位是使用数组对象定义的,内容取决于定位的类型。其语法如下表所示:
数组 | 描述 |
---|---|
[page /Fit] | 显示page指定的整个页面,页面缩放到刚好合适当前窗口大小。 |
[page /FitH top] | 显示page页,垂直坐标top指定距窗口的上边缘的位置,page水平缩放至适合窗口的宽度。 |
[page /FitV left] | 显示page页,水平坐标left指定距窗口左边缘的位置,page垂直缩放至适合窗口的高度。 |
[page /XYZ left top zoom] | 显示page页,left,top用于指定窗口的左上角,页面通过zoom因子进行缩放。任何参数为null时,表示该参数保持不变。 |
[page /FitR left bottom right top] | 在由left bottom right top指定的矩形区域内显示整个页面。 |
[page /FitB] | 像 /Fit那样显示page页,使用页面内容的边界框而非裁剪框。 |
[page /FitBH top] | 像 /FitH那样显示page页,使用页面内容的边界框而非裁剪框。 |
[page /FitBV left] | 像/FitV那那样显示page页,使用页面内容的边界框而非裁剪框。 |
文档大纲是由大纲条目组成的树。这些大纲条目是通过一个大纲字典和许多大纲项目字典定义的。文档目录中的/Outlines指向大纲字典。条目的子条目可以默认展开或收起。大纲字典中的条目如下:
键 | 值类型 | 值 |
---|---|---|
/Type | 名称 | 如果存在,必须是/Outlines |
/First | 间接引用字典 | 文档大纲中第一个顶级项的大纲项字典。如果存在任何文档大纲条目,则必需 |
/Last | 间接引用字典 | 文档大纲中最后一个顶级项的大纲项字典。如果存在任何文档大纲条目,则必需 |
/Count | 整数 | 打开的大纲条目数。如果没有打开的条目,可以省略。 |
大纲项目字典中的条目如下表所示,*是必选项:
键 | 值类型 | 值 |
---|---|---|
/Title* | 文本字串 | 条目文本 |
/Parent* | 间接引用字典 | 指向该项目在大纲树中的父节点。可以是另一个大纲项目字典或顶级大纲字典。 |
/Prev | 间接引用字典 | 指向同级的前序项目(如果存在的话) |
/Next | 间接引用字典 | 指向同级的下一项目(如果存在的话) |
/First | 间接引用字典 | 指向本条目的第一个子项目(如果存在的话) |
/Last | 间接引用字典 | 指向本条目的最后一个子项目(如果存在的话) |
/Count | 整数 | 该条目下的条目数,如果该条目是展开的则为正值,吧如果是收起的,则为对应的负值。 |
/Dest | 名称,字串或数组 |
考虑一个有三页的文件。我们希望构建以下层次结构:
Part 1 (points to page one)
Part 1A (points to page two)
Part 1B (points to page three)
相关代码如下例所示。第一,第二和第三页对应的页面对象编号分别是号3,5和7。 对象12是文档目录。对象11是文档大纲字典,对象8,9和10是文档大纲项目字典。
8 0 obj
<< /Parent 10 0 R /Title (Part 1B) /Dest [ 7 0 R /Fit ] /Prev 9 0 R >>
endobj
9 0 obj
<< /Parent 10 0 R /Title (Part 1A) /Dest [ 5 0 R /Fit ] /Next 8 0 R >>
endobj
10 0 obj
<< /Parent 11 0 R /First 9 0 R /Dest [ 3 0 R /Fit ] /Title (Part 1) /Last 8 0 R >>
endobj
11 0 obj
<< /First 10 0 R /Last 10 0 R >>
endobj
12 0 obj
<< /Outlines 11 0 R /Pages 1 0 R /Type /Catalog >>
Adobe Reader显示文档及其大纲,如下图所示:
译者注:上例中只给出了大纲部分的代码,下面我们给出一个完整的带大纲的PDF代码。
%PDF-1.4
%忏嫌
1 0 obj
<<
/Outlines 2 0 R
/Pages 3 0 R
/Type /Catalog
>>
endobj
3 0 obj
<<
/Kids [4 0 R 5 0 R 6 0 R]
/Count 3
/Type /Pages
>>
endobj
4 0 obj
<<
/Parent 3 0 R
/MediaBox [0 0 300 500]
/Resources 7 0 R
/Contents 8 0 R
/Type /Page
>>
endobj
7 0 obj
<<
/Font
<<
/F1 9 0 R
>>
>>
endobj
9 0 obj
<<
/BaseFont /Helvetica
/Subtype /Type1
/Type /Font
>>
endobj
8 0 obj
<<
/Length 52
>>
stream
BT /F1 20 Tf 20 460 Td (Preface to this book)Tj ET
endstream
endobj
5 0 obj
<<
/Parent 3 0 R
/MediaBox [0 0 300 500]
/Resources 7 0 R
/Contents 10 0 R
/Type /Page
>>
endobj
10 0 obj
<<
/Length 49
>>
stream
BT /F1 20 Tf 20 460 Td (this is section 2)Tj ET
endstream
endobj
6 0 obj
<<
/Parent 3 0 R
/MediaBox [0 0 300 500]
/Resources 7 0 R
/Contents 11 0 R
/Type /Page
>>
endobj
11 0 obj
<<
/Length 49
>>
stream
BT /F1 20 Tf 20 460 Td (this is section 1)Tj ET
endstream
endobj
12 0 obj
<<
/Title (Section 2)
/Parent 13 0 R
/Dest [5 0 R /Fit]
/Prev 14 0 R
>>
endobj
14 0 obj
<<
/Title (Section 1)
/Parent 13 0 R
/Dest [6 0 R /Fit]
/Next 12 0 R
>>
endobj
13 0 obj
<<
/Title (Chaper1)
/First 14 0 R
/Parent 2 0 R
/Dest [4 0 R /Fit]
/Count 2
/Last 12 0 R
>>
endobj
2 0 obj
<<
/First 13 0 R
/Last 13 0 R
>>
endobj xref
0 15
0000000000 65535 f
0000000015 00000 n
0000001192 00000 n
0000000082 00000 n
0000000153 00000 n
0000000482 00000 n
0000000692 00000 n
0000000259 00000 n
0000000377 00000 n
0000000305 00000 n
0000000589 00000 n
0000000799 00000 n
0000000902 00000 n
0000001082 00000 n
0000000992 00000 n
trailer
<<
/Root 1 0 R
/Size 15
>>
startxref
1241
%%EOF
在Adobe Reader中展现如下:
相应的对象图如下:
从PDF 1.4开始,元数据流可用于将XML元数据附加到整个文档或其中的某个元素上。 文档级元数据流扩展并取代文档信息字典(为了与旧的PDF程序兼容,几乎总是包含该字典)。
元数据以未压缩方式存储,通常不会加密。这样的方式使得外部工具可以很容易地在PDF文件中找到它。
XML使用由可扩展元数据平台(XMP)定义的标记,该标准在Adobe的XMP:可扩展元数据平台, 以及ISO 16684-1中进行了描述。
下面是一个XMP元数据的示例。你可以从文档信息词典中看到一些熟悉的条目。 注意/Type /Metadata /Subtype /XML,该序列将此流标识为XMP元数据。通过使用文档目录中的/Metadata条目将元数据流添加到文档中。
//译者注:原示例的空格和换行有问题,所以换了另外一个真实PDF中的例子
6 0 obj
<</Length 2988/Subtype/XML/Type/Metadata>>stream
<?xpacket begin="锘? id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.4-c006 80.159825, 2016/09/16-03:31:08">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<xmp:ModifyDate>2021-08-17T15:35:07+08:00</xmp:ModifyDate>
<xmp:CreateDate>2021-08-17T15:35:07+08:00</xmp:CreateDate>
<xmp:MetadataDate>2021-08-17T15:35:07+08:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:ca48048c-5b23-4b85-b01b-b6729ddd9a97</xmpMM:DocumentID>
<xmpMM:InstanceID>uuid:f46a0541-f391-4c44-953d-f1fe33ad8ae4</xmpMM:InstanceID>
<dc:format>application/pdf</dc:format>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
PDF中的注释用于在页面内容本身之外添加注解或交互元素。
在。每个查看器应用(例如Adobe Reader或Mac OS X Preview)都可能以不同的方式显示这些注释, 同一软件的不同版本之间都可能有差异。注释不会影响打印输出。
可以使用页面字典中的条目/Annots下的数组将一个或多个注释与页面相关联。 每个注释都是一个字典。字典中的条目在下表中描述,*为必选项。每种类型的注释都有额外的条目。
键 | 值类型 | 值 |
---|---|---|
/Type | 名称 | 如果存在,必须是/Annot |
/Subtype* | 名称 | 该注释的类型 |
/Rect* | 矩形 | 注释的位置和大小,默认用户空间单位 |
/Contents | 文本字串 | 此注释的文本内容。 |
我们来看两种注释:文本注释,以及用于在文档中创建超链接的链接注释。 还有许多其他类型的注释,可用于在文档上绘图,高亮文本以及添加打印机标记。 在“文件附件”中,我们使用文件附件注释为单个页面添加附件。
首先来看文本注释。此处/Subtype的值为/Text。我们将额外的注释字典条目/Open设置为true,表明在打开文档时注释将是可见的。使用/C条目将背景颜色设置为白色。具体代码如下。
6 0 obj
<<
/Subtype /Text
/Open true
/Contents (An example text annotation)
/Type /Annot
/Rect [400 100 500 200]
/C [1 1 1] //RGB (1, 1, 1) i.e., White
>>
/Annots [6 0 R]
//Extra entry in page dictionary
Adobe Reader中的结果下图所示。注意,Adobe Reader会忽略此处的/Rect条目 - 其他查看者可能会使用它。
现在来看链接注释,我们构建从第一页跳转到到第三页的超链接。 链接注释具有子类型/Link和用于指定目标的/Dest条目构成。/Rect条目定义超链接的区域。
代码如下:
6 0 obj
<<
/Subtype /Link
/Dest [4 0 R /Fit]
/Type /Annot
/Rect [45 760 260 800]
>>
/Annots [6 0 R] //Extra entry in page dictionary
Adobe Reader中的结果下图所示。可以使用不同的边框样式,包括使链接矩形不可见的样式。
附件是一种在PDF文档中包含一个或多个文件(任何类型)的方法。文件可以附加到整个文档上,也可以附加到单个页面上。通常,PDF查看器将显示附件列表,允许用户打开或保存它们。 例如,可以使用此功能将示例资源与幻灯片演示文稿的PDF捆绑在一起。
嵌入文件本身只包含在流对象中,此时流字典中将会有附加条目/Type /Embedded File。嵌入文件的代码的代码示例如下:
8 0 obj
<< /Type /EmbeddedFile /Length 35 >>
stream
This is a text file attachment...
endstream
endobj
嵌入式文件流有两种完全不同的引用方式:一种用于整个文档的附件,另一种用于特定页面的附件。
要附加到整个文档, 名称字典中需要包含/EmbeddedFiles条目,该条目会被文档目录中的/Names条目引用。代码示例如下:
//文档级附件。嵌入文件为对象8(参看上例)
9 0 obj
<< /Names
<< /EmbeddedFiles
<< /Names
[ (attachment.txt) << /EF << /F 8 0 R >> /F (attachment.txt) /Type /F >> ] >>
>>
/Pages 1 0 R
/Type /Catalog >>
endobj
要附加到单个页面,需要使用一种特殊类型的注释,通常在页面字典的/Annots字典中列出。代码示例如下:
//特定页面附件。嵌入文件是对象8
9 0 obj
<<
/Type /Page
//(Other dictionary entries as usual)
/Annots
[ << /FS << /EF << /F 8 0 R >> /F (attachment.txt) /Type /F >>
/Subtype /FileAttachment
/Contents (attachment.txt)
/Rect [ 18 796.88976378 45 823.88976378 ]
>> ]
>>
endobj
Adobe Reader在侧栏中显示附件如下图所示。