origami-docspring 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/examples/attachments/attachment.rb +7 -8
- data/examples/attachments/nested_document.rb +6 -5
- data/examples/encryption/encryption.rb +5 -4
- data/examples/events/events.rb +7 -6
- data/examples/flash/flash.rb +10 -9
- data/examples/forms/javascript.rb +14 -13
- data/examples/forms/xfa.rb +67 -66
- data/examples/javascript/hello_world.rb +6 -5
- data/examples/javascript/js_emulation.rb +26 -26
- data/examples/loop/goto.rb +12 -11
- data/examples/loop/named.rb +17 -16
- data/examples/signature/signature.rb +11 -11
- data/examples/uri/javascript.rb +25 -24
- data/examples/uri/open-uri.rb +5 -4
- data/examples/uri/submitform.rb +11 -10
- data/lib/origami/3d.rb +330 -334
- data/lib/origami/acroform.rb +267 -268
- data/lib/origami/actions.rb +266 -278
- data/lib/origami/annotations.rb +659 -670
- data/lib/origami/array.rb +192 -196
- data/lib/origami/boolean.rb +66 -70
- data/lib/origami/catalog.rb +360 -363
- data/lib/origami/collections.rb +132 -133
- data/lib/origami/compound.rb +125 -129
- data/lib/origami/destinations.rb +226 -237
- data/lib/origami/dictionary.rb +155 -154
- data/lib/origami/encryption.rb +967 -923
- data/lib/origami/extensions/fdf.rb +270 -275
- data/lib/origami/extensions/ppklite.rb +323 -328
- data/lib/origami/filespec.rb +170 -173
- data/lib/origami/filters/ascii.rb +162 -167
- data/lib/origami/filters/ccitt/tables.rb +248 -252
- data/lib/origami/filters/ccitt.rb +309 -312
- data/lib/origami/filters/crypt.rb +31 -34
- data/lib/origami/filters/dct.rb +47 -50
- data/lib/origami/filters/flate.rb +57 -60
- data/lib/origami/filters/jbig2.rb +50 -53
- data/lib/origami/filters/jpx.rb +40 -43
- data/lib/origami/filters/lzw.rb +151 -155
- data/lib/origami/filters/predictors.rb +250 -255
- data/lib/origami/filters/runlength.rb +111 -115
- data/lib/origami/filters.rb +319 -325
- data/lib/origami/font.rb +173 -177
- data/lib/origami/functions.rb +62 -66
- data/lib/origami/graphics/colors.rb +203 -208
- data/lib/origami/graphics/instruction.rb +79 -81
- data/lib/origami/graphics/path.rb +141 -144
- data/lib/origami/graphics/patterns.rb +156 -160
- data/lib/origami/graphics/render.rb +51 -47
- data/lib/origami/graphics/state.rb +144 -142
- data/lib/origami/graphics/text.rb +185 -188
- data/lib/origami/graphics/xobject.rb +818 -804
- data/lib/origami/graphics.rb +25 -26
- data/lib/origami/header.rb +63 -65
- data/lib/origami/javascript.rb +718 -651
- data/lib/origami/linearization.rb +284 -285
- data/lib/origami/metadata.rb +156 -135
- data/lib/origami/name.rb +98 -100
- data/lib/origami/null.rb +49 -51
- data/lib/origami/numeric.rb +133 -135
- data/lib/origami/obfuscation.rb +180 -182
- data/lib/origami/object.rb +634 -631
- data/lib/origami/optionalcontent.rb +147 -149
- data/lib/origami/outline.rb +46 -48
- data/lib/origami/outputintents.rb +76 -77
- data/lib/origami/page.rb +637 -596
- data/lib/origami/parser.rb +214 -221
- data/lib/origami/parsers/fdf.rb +44 -45
- data/lib/origami/parsers/pdf/lazy.rb +147 -154
- data/lib/origami/parsers/pdf/linear.rb +104 -109
- data/lib/origami/parsers/pdf.rb +109 -107
- data/lib/origami/parsers/ppklite.rb +44 -46
- data/lib/origami/pdf.rb +886 -896
- data/lib/origami/reference.rb +116 -120
- data/lib/origami/signature.rb +617 -625
- data/lib/origami/stream.rb +560 -558
- data/lib/origami/string.rb +366 -368
- data/lib/origami/template/patterns.rb +50 -52
- data/lib/origami/template/widgets.rb +111 -114
- data/lib/origami/trailer.rb +153 -157
- data/lib/origami/tree.rb +55 -57
- data/lib/origami/version.rb +19 -19
- data/lib/origami/webcapture.rb +87 -90
- data/lib/origami/xfa/config.rb +409 -414
- data/lib/origami/xfa/connectionset.rb +113 -117
- data/lib/origami/xfa/datasets.rb +38 -42
- data/lib/origami/xfa/localeset.rb +33 -37
- data/lib/origami/xfa/package.rb +49 -52
- data/lib/origami/xfa/pdf.rb +54 -59
- data/lib/origami/xfa/signature.rb +33 -37
- data/lib/origami/xfa/sourceset.rb +34 -38
- data/lib/origami/xfa/stylesheet.rb +35 -39
- data/lib/origami/xfa/template.rb +1630 -1634
- data/lib/origami/xfa/xdc.rb +33 -37
- data/lib/origami/xfa/xfa.rb +132 -123
- data/lib/origami/xfa/xfdf.rb +34 -38
- data/lib/origami/xfa/xmpmeta.rb +34 -38
- data/lib/origami/xfa.rb +50 -53
- data/lib/origami/xreftable.rb +462 -462
- data/lib/origami.rb +37 -38
- data/test/test_actions.rb +22 -20
- data/test/test_annotations.rb +54 -52
- data/test/test_forms.rb +23 -21
- data/test/test_native_types.rb +82 -78
- data/test/test_object_tree.rb +25 -24
- data/test/test_pages.rb +43 -41
- data/test/test_pdf.rb +2 -0
- data/test/test_pdf_attachment.rb +23 -21
- data/test/test_pdf_create.rb +16 -15
- data/test/test_pdf_encrypt.rb +69 -66
- data/test/test_pdf_parse.rb +131 -129
- data/test/test_pdf_parse_lazy.rb +53 -53
- data/test/test_pdf_sign.rb +67 -67
- data/test/test_streams.rb +145 -143
- data/test/test_xrefs.rb +46 -45
- metadata +64 -8
data/lib/origami/catalog.rb
CHANGED
@@ -1,418 +1,415 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This file is part of Origami, PDF manipulation framework for Ruby
|
5
|
+
# Copyright (C) 2016 Guillaume Delugré.
|
6
|
+
#
|
7
|
+
# Origami is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# Origami is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
20
|
|
21
21
|
module Origami
|
22
|
+
class PDF
|
23
|
+
#
|
24
|
+
# Sets PDF extension level and version. Only supported values are "1.7" and 3.
|
25
|
+
#
|
26
|
+
def set_extension_level(version, level)
|
27
|
+
exts = (self.Catalog.Extensions ||= Extensions.new)
|
22
28
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
#
|
27
|
-
def set_extension_level(version, level)
|
28
|
-
exts = (self.Catalog.Extensions ||= Extensions.new)
|
29
|
-
|
30
|
-
exts[:ADBE] = DeveloperExtension.new
|
31
|
-
exts[:ADBE].BaseVersion = Name.new(version)
|
32
|
-
exts[:ADBE].ExtensionLevel = level
|
33
|
-
|
34
|
-
self
|
35
|
-
end
|
36
|
-
|
37
|
-
#
|
38
|
-
# Returns the current Catalog Dictionary.
|
39
|
-
#
|
40
|
-
def Catalog
|
41
|
-
cat = trailer_key(:Root)
|
42
|
-
raise InvalidPDFError, "Broken catalog" unless cat.is_a?(Catalog)
|
29
|
+
exts[:ADBE] = DeveloperExtension.new
|
30
|
+
exts[:ADBE].BaseVersion = Name.new(version)
|
31
|
+
exts[:ADBE].ExtensionLevel = level
|
43
32
|
|
44
|
-
|
45
|
-
|
33
|
+
self
|
34
|
+
end
|
46
35
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
36
|
+
#
|
37
|
+
# Returns the current Catalog Dictionary.
|
38
|
+
#
|
39
|
+
def Catalog
|
40
|
+
cat = trailer_key(:Root)
|
41
|
+
raise InvalidPDFError, "Broken catalog" unless cat.is_a?(Catalog)
|
52
42
|
|
53
|
-
|
43
|
+
cat
|
44
|
+
end
|
54
45
|
|
55
|
-
|
56
|
-
|
46
|
+
#
|
47
|
+
# Sets the current Catalog Dictionary.
|
48
|
+
#
|
49
|
+
def Catalog=(cat)
|
50
|
+
raise TypeError, "Must be a Catalog object" unless cat.is_a?(Catalog)
|
57
51
|
|
58
|
-
|
59
|
-
# Sets an action to run on document opening.
|
60
|
-
# _action_:: An Action Object.
|
61
|
-
#
|
62
|
-
def onDocumentOpen(action)
|
63
|
-
self.Catalog.OpenAction = action
|
52
|
+
delete_object(@revisions.last.trailer[:Root]) if @revisions.last.trailer[:Root]
|
64
53
|
|
65
|
-
|
66
|
-
|
54
|
+
@revisions.last.trailer.Root = self << cat
|
55
|
+
end
|
67
56
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
self.Catalog.AA.WC = action
|
57
|
+
#
|
58
|
+
# Sets an action to run on document opening.
|
59
|
+
# _action_:: An Action Object.
|
60
|
+
#
|
61
|
+
def onDocumentOpen(action)
|
62
|
+
self.Catalog.OpenAction = action
|
75
63
|
|
76
|
-
|
77
|
-
|
64
|
+
self
|
65
|
+
end
|
78
66
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
67
|
+
#
|
68
|
+
# Sets an action to run on document closing.
|
69
|
+
# _action_:: A JavaScript Action Object.
|
70
|
+
#
|
71
|
+
def onDocumentClose(action)
|
72
|
+
self.Catalog.AA ||= CatalogAdditionalActions.new
|
73
|
+
self.Catalog.AA.WC = action
|
86
74
|
|
87
|
-
|
88
|
-
|
75
|
+
self
|
76
|
+
end
|
89
77
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
self.Catalog.Names ||= Names.new
|
98
|
-
|
99
|
-
value.set_indirect(true) unless value.is_a?(Reference)
|
100
|
-
|
101
|
-
namesroot = self.Catalog.Names[root]
|
102
|
-
if namesroot.nil?
|
103
|
-
names = NameTreeNode.new(:Names => []).set_indirect(true)
|
104
|
-
self.Catalog.Names[root] = names
|
105
|
-
names.Names << name << value
|
106
|
-
else
|
107
|
-
namesroot.solve[:Names] << name << value
|
108
|
-
end
|
109
|
-
end
|
78
|
+
#
|
79
|
+
# Sets an action to run on document printing.
|
80
|
+
# _action_:: A JavaScript Action Object.
|
81
|
+
#
|
82
|
+
def onDocumentPrint(action)
|
83
|
+
self.Catalog.AA ||= CatalogAdditionalActions.new
|
84
|
+
self.Catalog.AA.WP = action
|
110
85
|
|
111
|
-
|
112
|
-
|
113
|
-
# the specified _root_ name directory, or nil if the value does
|
114
|
-
# not exist.
|
115
|
-
#
|
116
|
-
def resolve_name(root, name)
|
117
|
-
namesroot = get_names_root(root)
|
118
|
-
return nil if namesroot.nil?
|
86
|
+
self
|
87
|
+
end
|
119
88
|
|
120
|
-
|
121
|
-
|
89
|
+
#
|
90
|
+
# Registers an object into a specific Names root dictionary.
|
91
|
+
# _root_:: The root dictionary (see Names::Root)
|
92
|
+
# _name_:: The value name.
|
93
|
+
# _value_:: The value to associate with this name.
|
94
|
+
#
|
95
|
+
def register(root, name, value)
|
96
|
+
self.Catalog.Names ||= Names.new
|
97
|
+
|
98
|
+
value.set_indirect(true) unless value.is_a?(Reference)
|
99
|
+
|
100
|
+
namesroot = self.Catalog.Names[root]
|
101
|
+
if namesroot.nil?
|
102
|
+
names = NameTreeNode.new(Names: []).set_indirect(true)
|
103
|
+
self.Catalog.Names[root] = names
|
104
|
+
names.Names << name << value
|
105
|
+
else
|
106
|
+
namesroot.solve[:Names] << name << value
|
107
|
+
end
|
108
|
+
end
|
122
109
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
110
|
+
#
|
111
|
+
# Retrieve the corresponding value associated with _name_ in
|
112
|
+
# the specified _root_ name directory, or nil if the value does
|
113
|
+
# not exist.
|
114
|
+
#
|
115
|
+
def resolve_name(root, name)
|
116
|
+
namesroot = get_names_root(root)
|
117
|
+
return nil if namesroot.nil?
|
129
118
|
|
130
|
-
|
131
|
-
|
132
|
-
#
|
133
|
-
def each_name(root, &block)
|
134
|
-
return enum_for(__method__, root) unless block_given?
|
119
|
+
resolve_name_from_node(namesroot, name)
|
120
|
+
end
|
135
121
|
|
136
|
-
|
137
|
-
|
122
|
+
#
|
123
|
+
# Returns a Hash of all names under the specified _root_ name directory.
|
124
|
+
#
|
125
|
+
def names(root)
|
126
|
+
each_name(root).to_h
|
127
|
+
end
|
138
128
|
|
139
|
-
|
140
|
-
|
141
|
-
|
129
|
+
#
|
130
|
+
# Returns an Enumerator of all names under the specified _root_ name directory.
|
131
|
+
#
|
132
|
+
def each_name(root, &block)
|
133
|
+
return enum_for(__method__, root) unless block_given?
|
142
134
|
|
143
|
-
|
135
|
+
names_root = get_names_root(root)
|
136
|
+
return if names_root.nil?
|
144
137
|
|
145
|
-
|
146
|
-
|
147
|
-
|
138
|
+
names_from_node(names_root, &block)
|
139
|
+
self
|
140
|
+
end
|
148
141
|
|
149
|
-
|
142
|
+
private
|
150
143
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
raise InvalidNameTreeError, "Odd number of elements" if names.length.odd?
|
144
|
+
def names_from_node(node, browsed_nodes: [], &block) # :nodoc:
|
145
|
+
return if browsed_nodes.any? { |browsed| browsed.equal?(node) }
|
146
|
+
raise InvalidNameTreeError, "node is not a dictionary" unless node.is_a?(Dictionary)
|
155
147
|
|
156
|
-
|
157
|
-
yield(names[i * 2].solve, names[i * 2 + 1].solve)
|
158
|
-
end
|
148
|
+
browsed_nodes.push(node)
|
159
149
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
end
|
165
|
-
end
|
150
|
+
if node.has_key?(:Names) # leaf node
|
151
|
+
names = node.Names
|
152
|
+
raise InvalidNameTreeError, "Names must be an Array" unless names.is_a?(Array)
|
153
|
+
raise InvalidNameTreeError, "Odd number of elements" if names.length.odd?
|
166
154
|
|
167
|
-
|
168
|
-
|
169
|
-
raise InvalidNameTreeError, "node is not a Dictionary" unless node.is_a?(Dictionary)
|
170
|
-
|
171
|
-
browsed_nodes.push(node)
|
172
|
-
|
173
|
-
if node.has_key?(:Names) # leaf node
|
174
|
-
limits = node.Limits
|
175
|
-
names = node.Names
|
176
|
-
|
177
|
-
raise InvalidNameTreeError, "Names must be an Array" unless names.is_a?(Array)
|
178
|
-
raise InvalidNameTreeError, "Odd number of elements" if names.length.odd?
|
179
|
-
|
180
|
-
if limits.is_a?(Array)
|
181
|
-
raise InvalidNameTreeError, "Invalid Limits array" unless limits.length == 2
|
182
|
-
|
183
|
-
min, max = limits[0].value, limits[1].value
|
184
|
-
if name.to_str >= min and name.to_str <= max
|
185
|
-
names = Hash[*names]
|
186
|
-
target = names[name]
|
187
|
-
return target && target.solve
|
188
|
-
end
|
189
|
-
else
|
190
|
-
names = Hash[*names]
|
191
|
-
target = names[name]
|
192
|
-
return target && target.solve
|
193
|
-
end
|
194
|
-
|
195
|
-
elsif node.has_key?(:Kids) # intermediate node
|
196
|
-
raise InvalidNameTreeError, "Kids must be an Array" unless node.Kids.is_a?(Array)
|
197
|
-
|
198
|
-
node.Kids.each do |kid|
|
199
|
-
kid = kid.solve
|
200
|
-
limits = kid.Limits
|
201
|
-
unless limits.is_a?(Array) and limits.length == 2
|
202
|
-
raise InvalidNameTreeError, "Invalid Limits array"
|
203
|
-
end
|
204
|
-
|
205
|
-
min, max = limits[0].value, limits[1].value
|
206
|
-
|
207
|
-
if name.to_str >= min and name.to_str <= max
|
208
|
-
return resolve_name_from_node(kid, name, browsed_nodes: browsed_nodes)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
155
|
+
(0...names.length / 2).each do |i|
|
156
|
+
yield(names[i * 2].solve, names[i * 2 + 1].solve)
|
212
157
|
end
|
213
158
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
namedirs[root].solve
|
159
|
+
elsif node.has_key?(:Kids) # intermediate node
|
160
|
+
node.Kids.each do |kid|
|
161
|
+
names_from_node(kid.solve, browsed_nodes: browsed_nodes, &block)
|
219
162
|
end
|
163
|
+
end
|
220
164
|
end
|
221
165
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
TWO_COLUMN_LEFT = :TwoColumnLeft
|
226
|
-
TWO_COLUMN_RIGHT = :TwoColumnRight
|
227
|
-
TWO_PAGE_LEFT = :TwoPageLeft
|
228
|
-
TWO_PAGE_RIGHT = :TwoPageRight
|
229
|
-
end
|
166
|
+
def resolve_name_from_node(node, name, browsed_nodes: []) # :nodoc:
|
167
|
+
return if browsed_nodes.any? { |browsed| browsed.equal?(node) }
|
168
|
+
raise InvalidNameTreeError, "node is not a Dictionary" unless node.is_a?(Dictionary)
|
230
169
|
|
231
|
-
|
232
|
-
NONE = :UseNone
|
233
|
-
OUTLINES = :UseOutlines
|
234
|
-
THUMBS = :UseThumbs
|
235
|
-
FULLSCREEN = :FullScreen
|
236
|
-
OPTIONAL_CONTENT = :UseOC
|
237
|
-
ATTACHMENTS = :UseAttachments
|
238
|
-
end
|
170
|
+
browsed_nodes.push(node)
|
239
171
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
class CatalogAdditionalActions < Dictionary
|
244
|
-
include StandardObject
|
245
|
-
|
246
|
-
field :WC, :Type => Action, :Version => "1.4"
|
247
|
-
field :WS, :Type => Action, :Version => "1.4"
|
248
|
-
field :DS, :Type => Action, :Version => "1.4"
|
249
|
-
field :WP, :Type => Action, :Version => "1.4"
|
250
|
-
field :DP, :Type => Action, :Version => "1.4"
|
251
|
-
end
|
172
|
+
if node.has_key?(:Names) # leaf node
|
173
|
+
limits = node.Limits
|
174
|
+
names = node.Names
|
252
175
|
|
253
|
-
|
254
|
-
|
255
|
-
#
|
256
|
-
class Names < Dictionary
|
257
|
-
include StandardObject
|
258
|
-
|
259
|
-
#
|
260
|
-
# Defines constants for Names tree root entries.
|
261
|
-
#
|
262
|
-
DESTINATIONS = :Dests
|
263
|
-
AP = :AP
|
264
|
-
JAVASCRIPT = :JavaScript
|
265
|
-
PAGES = :Pages
|
266
|
-
TEMPLATES = :Templates
|
267
|
-
IDS = :IDS
|
268
|
-
URLS = :URLS
|
269
|
-
EMBEDDED_FILES = :EmbeddedFiles
|
270
|
-
ALTERNATE_PRESENTATIONS = :AlternatePresentations
|
271
|
-
RENDITIONS = :Renditions
|
272
|
-
XFA_RESOURCES = :XFAResources
|
273
|
-
|
274
|
-
field DESTINATIONS, :Type => NameTreeNode.of([DestinationDictionary, Destination]), :Version => "1.2"
|
275
|
-
field AP, :Type => NameTreeNode.of(Annotation::AppearanceStream), :Version => "1.3"
|
276
|
-
field JAVASCRIPT, :Type => NameTreeNode.of(Action::JavaScript), :Version => "1.3"
|
277
|
-
field PAGES, :Type => NameTreeNode.of(Page), :Version => "1.3"
|
278
|
-
field TEMPLATES, :Type => NameTreeNode.of(Page), :Version => "1.3"
|
279
|
-
field IDS, :Type => NameTreeNode.of(WebCapture::ContentSet), :Version => "1.3"
|
280
|
-
field URLS, :Type => NameTreeNode.of(WebCapture::ContentSet), :Version => "1.3"
|
281
|
-
field EMBEDDED_FILES, :Type => NameTreeNode.of(FileSpec), :Version => "1.4"
|
282
|
-
field ALTERNATE_PRESENTATIONS, :Type => NameTreeNode, :Version => "1.4"
|
283
|
-
field RENDITIONS, :Type => NameTreeNode, :Version => "1.5"
|
284
|
-
field XFA_RESOURCES, :Type => NameTreeNode.of(XFAStream), :Version => "1.7", :ExtensionLevel => 3
|
285
|
-
end
|
176
|
+
raise InvalidNameTreeError, "Names must be an Array" unless names.is_a?(Array)
|
177
|
+
raise InvalidNameTreeError, "Odd number of elements" if names.length.odd?
|
286
178
|
|
287
|
-
|
288
|
-
|
289
|
-
#
|
290
|
-
class NameLeaf < Array.of(String, Object)
|
291
|
-
|
292
|
-
#
|
293
|
-
# Creates a new leaf in a Name tree.
|
294
|
-
# _hash_:: A hash of couples, associating a Name with an Reference.
|
295
|
-
#
|
296
|
-
def initialize(hash = {})
|
297
|
-
super(hash.flat_map {|name, obj| [name.dup, obj]})
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
#
|
302
|
-
# Class representing the ViewerPreferences Dictionary of a PDF.
|
303
|
-
# This dictionary modifies the way the UI looks when the file is opened in a viewer.
|
304
|
-
#
|
305
|
-
class ViewerPreferences < Dictionary
|
306
|
-
include StandardObject
|
179
|
+
if limits.is_a?(Array)
|
180
|
+
raise InvalidNameTreeError, "Invalid Limits array" unless limits.length == 2
|
307
181
|
|
308
|
-
|
309
|
-
|
310
|
-
|
182
|
+
min, max = limits[0].value, limits[1].value
|
183
|
+
if (name.to_str >= min) && (name.to_str <= max)
|
184
|
+
names = Hash[*names]
|
185
|
+
target = names[name]
|
186
|
+
target&.solve
|
187
|
+
end
|
188
|
+
else
|
189
|
+
names = Hash[*names]
|
190
|
+
target = names[name]
|
191
|
+
target&.solve
|
311
192
|
end
|
312
193
|
|
313
|
-
|
314
|
-
|
315
|
-
field :HideWindowUI, :Type => Boolean, :Default => false
|
316
|
-
field :FitWindow, :Type => Boolean, :Default => false
|
317
|
-
field :CenterWindow, :Type => Boolean, :Default => false
|
318
|
-
field :DisplayDocTitle, :Type => Boolean, :Default => false, :Version => "1.4"
|
319
|
-
field :NonFullScreenPageMode, :Type => Name, :Default => :UseNone
|
320
|
-
field :Direction, :Type => Name, :Default => :L2R
|
321
|
-
field :ViewArea, :Type => Name, :Default => :CropBox, :Version => "1.4"
|
322
|
-
field :ViewClip, :Type => Name, :Default => :CropBox, :Version => "1.4"
|
323
|
-
field :PrintArea, :Type => Name, :Default => :CropBox, :Version => "1.4"
|
324
|
-
field :PrintClip, :Type => Name, :Default => :CropBox, :Version => "1.4"
|
325
|
-
field :PrintScaling, :Type => Name, :Default => :AppDefault, :Version => "1.6"
|
326
|
-
field :Duplex, :Type => Name, :Default => :Simplex, :Version => "1.7"
|
327
|
-
field :PickTrayByPDFSize, :Type => Boolean, :Version => "1.7"
|
328
|
-
field :PrintPageRange, :Type => Array.of(Integer), :Version => "1.7"
|
329
|
-
field :NumCopies, :Type => Integer, :Version => "1.7"
|
330
|
-
field :Enforce, :Type => Array.of(Name), :Version => "1.7", :ExtensionLevel => 3
|
331
|
-
end
|
332
|
-
|
333
|
-
class Requirement < Dictionary
|
334
|
-
include StandardObject
|
194
|
+
elsif node.has_key?(:Kids) # intermediate node
|
195
|
+
raise InvalidNameTreeError, "Kids must be an Array" unless node.Kids.is_a?(Array)
|
335
196
|
|
336
|
-
|
337
|
-
|
197
|
+
node.Kids.each do |kid|
|
198
|
+
kid = kid.solve
|
199
|
+
limits = kid.Limits
|
200
|
+
unless limits.is_a?(Array) && (limits.length == 2)
|
201
|
+
raise InvalidNameTreeError, "Invalid Limits array"
|
202
|
+
end
|
338
203
|
|
339
|
-
|
340
|
-
JS = :JS
|
341
|
-
NOOP = :NoOp
|
342
|
-
end
|
204
|
+
min, max = limits[0].value, limits[1].value
|
343
205
|
|
344
|
-
|
345
|
-
|
346
|
-
|
206
|
+
if (name.to_str >= min) && (name.to_str <= max)
|
207
|
+
return resolve_name_from_node(kid, name, browsed_nodes: browsed_nodes)
|
208
|
+
end
|
347
209
|
end
|
348
|
-
|
349
|
-
field :Type, :Type => Name, :Default => :Requirement
|
350
|
-
field :S, :Type => Name, :Default => :EnableJavaScripts, :Version => "1.7", :Required => true
|
351
|
-
field :RH, :Type => Array.of(Handler)
|
210
|
+
end
|
352
211
|
end
|
353
212
|
|
354
|
-
#
|
355
|
-
|
356
|
-
|
357
|
-
class DeveloperExtension < Dictionary
|
358
|
-
include StandardObject
|
213
|
+
def get_names_root(root) # :nodoc:
|
214
|
+
namedirs = self.Catalog.Names
|
215
|
+
return nil if namedirs.nil? || namedirs[root].nil?
|
359
216
|
|
360
|
-
|
361
|
-
field :BaseVersion, :Type => Name, :Required => true
|
362
|
-
field :ExtensionLevel, :Type => Integer, :Required => true
|
217
|
+
namedirs[root].solve
|
363
218
|
end
|
219
|
+
end
|
220
|
+
|
221
|
+
module PageLayout # :nodoc:
|
222
|
+
SINGLE = :SinglePage
|
223
|
+
ONE_COLUMN = :OneColumn
|
224
|
+
TWO_COLUMN_LEFT = :TwoColumnLeft
|
225
|
+
TWO_COLUMN_RIGHT = :TwoColumnRight
|
226
|
+
TWO_PAGE_LEFT = :TwoPageLeft
|
227
|
+
TWO_PAGE_RIGHT = :TwoPageRight
|
228
|
+
end
|
229
|
+
|
230
|
+
module PageMode # :nodoc:
|
231
|
+
NONE = :UseNone
|
232
|
+
OUTLINES = :UseOutlines
|
233
|
+
THUMBS = :UseThumbs
|
234
|
+
FULLSCREEN = :FullScreen
|
235
|
+
OPTIONAL_CONTENT = :UseOC
|
236
|
+
ATTACHMENTS = :UseAttachments
|
237
|
+
end
|
238
|
+
|
239
|
+
#
|
240
|
+
# Class representing additional actions which can be associated with a Catalog.
|
241
|
+
#
|
242
|
+
class CatalogAdditionalActions < Dictionary
|
243
|
+
include StandardObject
|
244
|
+
|
245
|
+
field :WC, Type: Action, Version: "1.4"
|
246
|
+
field :WS, Type: Action, Version: "1.4"
|
247
|
+
field :DS, Type: Action, Version: "1.4"
|
248
|
+
field :WP, Type: Action, Version: "1.4"
|
249
|
+
field :DP, Type: Action, Version: "1.4"
|
250
|
+
end
|
251
|
+
|
252
|
+
#
|
253
|
+
# Class representing the Names Dictionary of a PDF file.
|
254
|
+
#
|
255
|
+
class Names < Dictionary
|
256
|
+
include StandardObject
|
364
257
|
|
365
258
|
#
|
366
|
-
#
|
259
|
+
# Defines constants for Names tree root entries.
|
367
260
|
#
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
261
|
+
DESTINATIONS = :Dests
|
262
|
+
AP = :AP
|
263
|
+
JAVASCRIPT = :JavaScript
|
264
|
+
PAGES = :Pages
|
265
|
+
TEMPLATES = :Templates
|
266
|
+
IDS = :IDS
|
267
|
+
URLS = :URLS
|
268
|
+
EMBEDDED_FILES = :EmbeddedFiles
|
269
|
+
ALTERNATE_PRESENTATIONS = :AlternatePresentations
|
270
|
+
RENDITIONS = :Renditions
|
271
|
+
XFA_RESOURCES = :XFAResources
|
272
|
+
|
273
|
+
field DESTINATIONS, Type: NameTreeNode.of([DestinationDictionary, Destination]), Version: "1.2"
|
274
|
+
field AP, Type: NameTreeNode.of(Annotation::AppearanceStream), Version: "1.3"
|
275
|
+
field JAVASCRIPT, Type: NameTreeNode.of(Action::JavaScript), Version: "1.3"
|
276
|
+
field PAGES, Type: NameTreeNode.of(Page), Version: "1.3"
|
277
|
+
field TEMPLATES, Type: NameTreeNode.of(Page), Version: "1.3"
|
278
|
+
field IDS, Type: NameTreeNode.of(WebCapture::ContentSet), Version: "1.3"
|
279
|
+
field URLS, Type: NameTreeNode.of(WebCapture::ContentSet), Version: "1.3"
|
280
|
+
field EMBEDDED_FILES, Type: NameTreeNode.of(FileSpec), Version: "1.4"
|
281
|
+
field ALTERNATE_PRESENTATIONS, Type: NameTreeNode, Version: "1.4"
|
282
|
+
field RENDITIONS, Type: NameTreeNode, Version: "1.5"
|
283
|
+
field XFA_RESOURCES, Type: NameTreeNode.of(XFAStream), Version: "1.7", ExtensionLevel: 3
|
284
|
+
end
|
285
|
+
|
286
|
+
#
|
287
|
+
# Class representing a leaf in a Name tree.
|
288
|
+
#
|
289
|
+
class NameLeaf < Array.of(String, Object)
|
375
290
|
#
|
376
|
-
#
|
291
|
+
# Creates a new leaf in a Name tree.
|
292
|
+
# _hash_:: A hash of couples, associating a Name with an Reference.
|
377
293
|
#
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
294
|
+
def initialize(hash = {})
|
295
|
+
super(hash.flat_map { |name, obj| [name.dup, obj] })
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
#
|
300
|
+
# Class representing the ViewerPreferences Dictionary of a PDF.
|
301
|
+
# This dictionary modifies the way the UI looks when the file is opened in a viewer.
|
302
|
+
#
|
303
|
+
class ViewerPreferences < Dictionary
|
304
|
+
include StandardObject
|
305
|
+
|
306
|
+
# Valid values for the Enforce field.
|
307
|
+
module Enforce
|
308
|
+
PRINT_SCALING = :PrintScaling
|
309
|
+
end
|
310
|
+
|
311
|
+
field :HideToolbar, Type: Boolean, Default: false
|
312
|
+
field :HideMenubar, Type: Boolean, Default: false
|
313
|
+
field :HideWindowUI, Type: Boolean, Default: false
|
314
|
+
field :FitWindow, Type: Boolean, Default: false
|
315
|
+
field :CenterWindow, Type: Boolean, Default: false
|
316
|
+
field :DisplayDocTitle, Type: Boolean, Default: false, Version: "1.4"
|
317
|
+
field :NonFullScreenPageMode, Type: Name, Default: :UseNone
|
318
|
+
field :Direction, Type: Name, Default: :L2R
|
319
|
+
field :ViewArea, Type: Name, Default: :CropBox, Version: "1.4"
|
320
|
+
field :ViewClip, Type: Name, Default: :CropBox, Version: "1.4"
|
321
|
+
field :PrintArea, Type: Name, Default: :CropBox, Version: "1.4"
|
322
|
+
field :PrintClip, Type: Name, Default: :CropBox, Version: "1.4"
|
323
|
+
field :PrintScaling, Type: Name, Default: :AppDefault, Version: "1.6"
|
324
|
+
field :Duplex, Type: Name, Default: :Simplex, Version: "1.7"
|
325
|
+
field :PickTrayByPDFSize, Type: Boolean, Version: "1.7"
|
326
|
+
field :PrintPageRange, Type: Array.of(Integer), Version: "1.7"
|
327
|
+
field :NumCopies, Type: Integer, Version: "1.7"
|
328
|
+
field :Enforce, Type: Array.of(Name), Version: "1.7", ExtensionLevel: 3
|
329
|
+
end
|
330
|
+
|
331
|
+
class Requirement < Dictionary
|
332
|
+
include StandardObject
|
333
|
+
|
334
|
+
class Handler < Dictionary
|
335
|
+
include StandardObject
|
336
|
+
|
337
|
+
module Type
|
338
|
+
JS = :JS
|
339
|
+
NOOP = :NoOp
|
340
|
+
end
|
341
|
+
|
342
|
+
field :Type, Type: Name, Default: :ReqHandler
|
343
|
+
field :S, Type: Name, Default: Type::NOOP, Required: true
|
344
|
+
field :Script, Type: String
|
416
345
|
end
|
417
346
|
|
347
|
+
field :Type, Type: Name, Default: :Requirement
|
348
|
+
field :S, Type: Name, Default: :EnableJavaScripts, Version: "1.7", Required: true
|
349
|
+
field :RH, Type: Array.of(Handler)
|
350
|
+
end
|
351
|
+
|
352
|
+
#
|
353
|
+
# Class representing a developer extension.
|
354
|
+
#
|
355
|
+
class DeveloperExtension < Dictionary
|
356
|
+
include StandardObject
|
357
|
+
|
358
|
+
field :Type, Type: Name, Default: :DeveloperExtensions
|
359
|
+
field :BaseVersion, Type: Name, Required: true
|
360
|
+
field :ExtensionLevel, Type: Integer, Required: true
|
361
|
+
end
|
362
|
+
|
363
|
+
#
|
364
|
+
# Class representing an extension Dictionary.
|
365
|
+
#
|
366
|
+
class Extensions < Dictionary
|
367
|
+
include StandardObject
|
368
|
+
|
369
|
+
field :Type, Type: Name, Default: :Extensions
|
370
|
+
field :ADBE, Type: DeveloperExtension
|
371
|
+
end
|
372
|
+
|
373
|
+
#
|
374
|
+
# Class representing the Catalog Dictionary of a PDF file.
|
375
|
+
#
|
376
|
+
class Catalog < Dictionary
|
377
|
+
include StandardObject
|
378
|
+
|
379
|
+
field :Type, Type: Name, Default: :Catalog, Required: true
|
380
|
+
field :Version, Type: Name, Version: "1.4"
|
381
|
+
field :Pages, Type: PageTreeNode, Required: true
|
382
|
+
field :PageLabels, Type: NumberTreeNode.of(PageLabel), Version: "1.3"
|
383
|
+
field :Names, Type: Names, Version: "1.2"
|
384
|
+
field :Dests, Type: Dictionary, Version: "1.1"
|
385
|
+
field :ViewerPreferences, Type: ViewerPreferences, Version: "1.2"
|
386
|
+
field :PageLayout, Type: Name, Default: PageLayout::SINGLE
|
387
|
+
field :PageMode, Type: Name, Default: PageMode::NONE
|
388
|
+
field :Outlines, Type: Outline
|
389
|
+
field :Threads, Type: Array, Version: "1.1"
|
390
|
+
field :OpenAction, Type: [Array, Dictionary], Version: "1.1"
|
391
|
+
field :AA, Type: CatalogAdditionalActions, Version: "1.4"
|
392
|
+
field :URI, Type: Dictionary, Version: "1.1"
|
393
|
+
field :AcroForm, Type: InteractiveForm, Version: "1.2"
|
394
|
+
field :Metadata, Type: MetadataStream, Version: "1.4"
|
395
|
+
field :StructTreeRoot, Type: Dictionary, Version: "1.3"
|
396
|
+
field :MarkInfo, Type: Dictionary, Version: "1.4"
|
397
|
+
field :Lang, Type: String, Version: "1.4"
|
398
|
+
field :SpiderInfo, Type: WebCapture::SpiderInfo, Version: "1.3"
|
399
|
+
field :OutputIntents, Type: Array.of(OutputIntent), Version: "1.4"
|
400
|
+
field :PieceInfo, Type: Dictionary, Version: "1.4"
|
401
|
+
field :OCProperties, Type: OptionalContent::Properties, Version: "1.5"
|
402
|
+
field :Perms, Type: Dictionary, Version: "1.5"
|
403
|
+
field :Legal, Type: Dictionary, Version: "1.5"
|
404
|
+
field :Requirements, Type: Array.of(Requirement), Version: "1.7"
|
405
|
+
field :Collection, Type: Collection, Version: "1.7"
|
406
|
+
field :NeedsRendering, Type: Boolean, Version: "1.7", Default: false
|
407
|
+
field :Extensions, Type: Extensions, Version: "1.7", ExtensionLevel: 3
|
408
|
+
|
409
|
+
def initialize(hash = {}, parser = nil)
|
410
|
+
set_indirect(true)
|
411
|
+
|
412
|
+
super
|
413
|
+
end
|
414
|
+
end
|
418
415
|
end
|