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.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/examples/attachments/attachment.rb +7 -8
  4. data/examples/attachments/nested_document.rb +6 -5
  5. data/examples/encryption/encryption.rb +5 -4
  6. data/examples/events/events.rb +7 -6
  7. data/examples/flash/flash.rb +10 -9
  8. data/examples/forms/javascript.rb +14 -13
  9. data/examples/forms/xfa.rb +67 -66
  10. data/examples/javascript/hello_world.rb +6 -5
  11. data/examples/javascript/js_emulation.rb +26 -26
  12. data/examples/loop/goto.rb +12 -11
  13. data/examples/loop/named.rb +17 -16
  14. data/examples/signature/signature.rb +11 -11
  15. data/examples/uri/javascript.rb +25 -24
  16. data/examples/uri/open-uri.rb +5 -4
  17. data/examples/uri/submitform.rb +11 -10
  18. data/lib/origami/3d.rb +330 -334
  19. data/lib/origami/acroform.rb +267 -268
  20. data/lib/origami/actions.rb +266 -278
  21. data/lib/origami/annotations.rb +659 -670
  22. data/lib/origami/array.rb +192 -196
  23. data/lib/origami/boolean.rb +66 -70
  24. data/lib/origami/catalog.rb +360 -363
  25. data/lib/origami/collections.rb +132 -133
  26. data/lib/origami/compound.rb +125 -129
  27. data/lib/origami/destinations.rb +226 -237
  28. data/lib/origami/dictionary.rb +155 -154
  29. data/lib/origami/encryption.rb +967 -923
  30. data/lib/origami/extensions/fdf.rb +270 -275
  31. data/lib/origami/extensions/ppklite.rb +323 -328
  32. data/lib/origami/filespec.rb +170 -173
  33. data/lib/origami/filters/ascii.rb +162 -167
  34. data/lib/origami/filters/ccitt/tables.rb +248 -252
  35. data/lib/origami/filters/ccitt.rb +309 -312
  36. data/lib/origami/filters/crypt.rb +31 -34
  37. data/lib/origami/filters/dct.rb +47 -50
  38. data/lib/origami/filters/flate.rb +57 -60
  39. data/lib/origami/filters/jbig2.rb +50 -53
  40. data/lib/origami/filters/jpx.rb +40 -43
  41. data/lib/origami/filters/lzw.rb +151 -155
  42. data/lib/origami/filters/predictors.rb +250 -255
  43. data/lib/origami/filters/runlength.rb +111 -115
  44. data/lib/origami/filters.rb +319 -325
  45. data/lib/origami/font.rb +173 -177
  46. data/lib/origami/functions.rb +62 -66
  47. data/lib/origami/graphics/colors.rb +203 -208
  48. data/lib/origami/graphics/instruction.rb +79 -81
  49. data/lib/origami/graphics/path.rb +141 -144
  50. data/lib/origami/graphics/patterns.rb +156 -160
  51. data/lib/origami/graphics/render.rb +51 -47
  52. data/lib/origami/graphics/state.rb +144 -142
  53. data/lib/origami/graphics/text.rb +185 -188
  54. data/lib/origami/graphics/xobject.rb +818 -804
  55. data/lib/origami/graphics.rb +25 -26
  56. data/lib/origami/header.rb +63 -65
  57. data/lib/origami/javascript.rb +718 -651
  58. data/lib/origami/linearization.rb +284 -285
  59. data/lib/origami/metadata.rb +156 -135
  60. data/lib/origami/name.rb +98 -100
  61. data/lib/origami/null.rb +49 -51
  62. data/lib/origami/numeric.rb +133 -135
  63. data/lib/origami/obfuscation.rb +180 -182
  64. data/lib/origami/object.rb +634 -631
  65. data/lib/origami/optionalcontent.rb +147 -149
  66. data/lib/origami/outline.rb +46 -48
  67. data/lib/origami/outputintents.rb +76 -77
  68. data/lib/origami/page.rb +637 -596
  69. data/lib/origami/parser.rb +214 -221
  70. data/lib/origami/parsers/fdf.rb +44 -45
  71. data/lib/origami/parsers/pdf/lazy.rb +147 -154
  72. data/lib/origami/parsers/pdf/linear.rb +104 -109
  73. data/lib/origami/parsers/pdf.rb +109 -107
  74. data/lib/origami/parsers/ppklite.rb +44 -46
  75. data/lib/origami/pdf.rb +886 -896
  76. data/lib/origami/reference.rb +116 -120
  77. data/lib/origami/signature.rb +617 -625
  78. data/lib/origami/stream.rb +560 -558
  79. data/lib/origami/string.rb +366 -368
  80. data/lib/origami/template/patterns.rb +50 -52
  81. data/lib/origami/template/widgets.rb +111 -114
  82. data/lib/origami/trailer.rb +153 -157
  83. data/lib/origami/tree.rb +55 -57
  84. data/lib/origami/version.rb +19 -19
  85. data/lib/origami/webcapture.rb +87 -90
  86. data/lib/origami/xfa/config.rb +409 -414
  87. data/lib/origami/xfa/connectionset.rb +113 -117
  88. data/lib/origami/xfa/datasets.rb +38 -42
  89. data/lib/origami/xfa/localeset.rb +33 -37
  90. data/lib/origami/xfa/package.rb +49 -52
  91. data/lib/origami/xfa/pdf.rb +54 -59
  92. data/lib/origami/xfa/signature.rb +33 -37
  93. data/lib/origami/xfa/sourceset.rb +34 -38
  94. data/lib/origami/xfa/stylesheet.rb +35 -39
  95. data/lib/origami/xfa/template.rb +1630 -1634
  96. data/lib/origami/xfa/xdc.rb +33 -37
  97. data/lib/origami/xfa/xfa.rb +132 -123
  98. data/lib/origami/xfa/xfdf.rb +34 -38
  99. data/lib/origami/xfa/xmpmeta.rb +34 -38
  100. data/lib/origami/xfa.rb +50 -53
  101. data/lib/origami/xreftable.rb +462 -462
  102. data/lib/origami.rb +37 -38
  103. data/test/test_actions.rb +22 -20
  104. data/test/test_annotations.rb +54 -52
  105. data/test/test_forms.rb +23 -21
  106. data/test/test_native_types.rb +82 -78
  107. data/test/test_object_tree.rb +25 -24
  108. data/test/test_pages.rb +43 -41
  109. data/test/test_pdf.rb +2 -0
  110. data/test/test_pdf_attachment.rb +23 -21
  111. data/test/test_pdf_create.rb +16 -15
  112. data/test/test_pdf_encrypt.rb +69 -66
  113. data/test/test_pdf_parse.rb +131 -129
  114. data/test/test_pdf_parse_lazy.rb +53 -53
  115. data/test/test_pdf_sign.rb +67 -67
  116. data/test/test_streams.rb +145 -143
  117. data/test/test_xrefs.rb +46 -45
  118. metadata +64 -8
@@ -1,418 +1,415 @@
1
- =begin
2
-
3
- This file is part of Origami, PDF manipulation framework for Ruby
4
- Copyright (C) 2016 Guillaume Delugré.
5
-
6
- Origami is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU Lesser General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
10
-
11
- Origami is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU Lesser General Public License for more details.
15
-
16
- You should have received a copy of the GNU Lesser General Public License
17
- along with Origami. If not, see <http://www.gnu.org/licenses/>.
18
-
19
- =end
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
- class PDF
24
- #
25
- # Sets PDF extension level and version. Only supported values are "1.7" and 3.
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
- cat
45
- end
33
+ self
34
+ end
46
35
 
47
- #
48
- # Sets the current Catalog Dictionary.
49
- #
50
- def Catalog=(cat)
51
- raise TypeError, "Must be a Catalog object" unless cat.is_a?(Catalog)
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
- delete_object(@revisions.last.trailer[:Root]) if @revisions.last.trailer[:Root]
43
+ cat
44
+ end
54
45
 
55
- @revisions.last.trailer.Root = self << cat
56
- end
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
- self
66
- end
54
+ @revisions.last.trailer.Root = self << cat
55
+ end
67
56
 
68
- #
69
- # Sets an action to run on document closing.
70
- # _action_:: A JavaScript Action Object.
71
- #
72
- def onDocumentClose(action)
73
- self.Catalog.AA ||= CatalogAdditionalActions.new
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
- self
77
- end
64
+ self
65
+ end
78
66
 
79
- #
80
- # Sets an action to run on document printing.
81
- # _action_:: A JavaScript Action Object.
82
- #
83
- def onDocumentPrint(action)
84
- self.Catalog.AA ||= CatalogAdditionalActions.new
85
- self.Catalog.AA.WP = action
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
- self
88
- end
75
+ self
76
+ end
89
77
 
90
- #
91
- # Registers an object into a specific Names root dictionary.
92
- # _root_:: The root dictionary (see Names::Root)
93
- # _name_:: The value name.
94
- # _value_:: The value to associate with this name.
95
- #
96
- def register(root, name, value)
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
- # Retrieve the corresponding value associated with _name_ in
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
- resolve_name_from_node(namesroot, name)
121
- end
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
- # Returns a Hash of all names under the specified _root_ name directory.
125
- #
126
- def names(root)
127
- self.each_name(root).to_h
128
- end
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
- # Returns an Enumerator of all names under the specified _root_ name directory.
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
- names_root = get_names_root(root)
137
- return if names_root.nil?
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
- names_from_node(names_root, &block)
140
- self
141
- end
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
- private
135
+ names_root = get_names_root(root)
136
+ return if names_root.nil?
144
137
 
145
- def names_from_node(node, browsed_nodes: [], &block) #:nodoc:
146
- return if browsed_nodes.any?{|browsed| browsed.equal?(node)}
147
- raise InvalidNameTreeError, "node is not a dictionary" unless node.is_a?(Dictionary)
138
+ names_from_node(names_root, &block)
139
+ self
140
+ end
148
141
 
149
- browsed_nodes.push(node)
142
+ private
150
143
 
151
- if node.has_key?(:Names) # leaf node
152
- names = node.Names
153
- raise InvalidNameTreeError, "Names must be an Array" unless names.is_a?(Array)
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
- for i in 0...names.length/2
157
- yield(names[i * 2].solve, names[i * 2 + 1].solve)
158
- end
148
+ browsed_nodes.push(node)
159
149
 
160
- elsif node.has_key?(:Kids) # intermediate node
161
- node.Kids.each do |kid|
162
- names_from_node(kid.solve, browsed_nodes: browsed_nodes, &block)
163
- end
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
- def resolve_name_from_node(node, name, browsed_nodes: []) #:nodoc:
168
- return if browsed_nodes.any?{|browsed| browsed.equal?(node)}
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
- def get_names_root(root) #:nodoc:
215
- namedirs = self.Catalog.Names
216
- return nil if namedirs.nil? or namedirs[root].nil?
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
- module PageLayout #:nodoc:
223
- SINGLE = :SinglePage
224
- ONE_COLUMN = :OneColumn
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
- module PageMode #:nodoc:
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
- # Class representing additional actions which can be associated with a Catalog.
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
- # Class representing the Names Dictionary of a PDF file.
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
- # Class representing a leaf in a Name tree.
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
- # Valid values for the Enforce field.
309
- module Enforce
310
- PRINT_SCALING = :PrintScaling
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
- field :HideToolbar, :Type => Boolean, :Default => false
314
- field :HideMenubar, :Type => Boolean, :Default => false
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
- class Handler < Dictionary
337
- include StandardObject
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
- module Type
340
- JS = :JS
341
- NOOP = :NoOp
342
- end
204
+ min, max = limits[0].value, limits[1].value
343
205
 
344
- field :Type, :Type => Name, :Default => :ReqHandler
345
- field :S, :Type => Name, :Default => Type::NOOP, :Required => true
346
- field :Script, :Type => String
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
- # Class representing a developer extension.
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
- field :Type, :Type => Name, :Default => :DeveloperExtensions
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
- # Class representing an extension Dictionary.
259
+ # Defines constants for Names tree root entries.
367
260
  #
368
- class Extensions < Dictionary
369
- include StandardObject
370
-
371
- field :Type, :Type => Name, :Default => :Extensions
372
- field :ADBE, :Type => DeveloperExtension
373
- end
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
- # Class representing the Catalog Dictionary of a PDF file.
291
+ # Creates a new leaf in a Name tree.
292
+ # _hash_:: A hash of couples, associating a Name with an Reference.
377
293
  #
378
- class Catalog < Dictionary
379
- include StandardObject
380
-
381
- field :Type, :Type => Name, :Default => :Catalog, :Required => true
382
- field :Version, :Type => Name, :Version => "1.4"
383
- field :Pages, :Type => PageTreeNode, :Required => true
384
- field :PageLabels, :Type => NumberTreeNode.of(PageLabel), :Version => "1.3"
385
- field :Names, :Type => Names, :Version => "1.2"
386
- field :Dests, :Type => Dictionary, :Version => "1.1"
387
- field :ViewerPreferences, :Type => ViewerPreferences, :Version => "1.2"
388
- field :PageLayout, :Type => Name, :Default => PageLayout::SINGLE
389
- field :PageMode, :Type => Name, :Default => PageMode::NONE
390
- field :Outlines, :Type => Outline
391
- field :Threads, :Type => Array, :Version => "1.1"
392
- field :OpenAction, :Type => [ Array, Dictionary ], :Version => "1.1"
393
- field :AA, :Type => CatalogAdditionalActions, :Version => "1.4"
394
- field :URI, :Type => Dictionary, :Version => "1.1"
395
- field :AcroForm, :Type => InteractiveForm, :Version => "1.2"
396
- field :Metadata, :Type => MetadataStream, :Version => "1.4"
397
- field :StructTreeRoot, :Type => Dictionary, :Version => "1.3"
398
- field :MarkInfo, :Type => Dictionary, :Version => "1.4"
399
- field :Lang, :Type => String, :Version => "1.4"
400
- field :SpiderInfo, :Type => WebCapture::SpiderInfo, :Version => "1.3"
401
- field :OutputIntents, :Type => Array.of(OutputIntent), :Version => "1.4"
402
- field :PieceInfo, :Type => Dictionary, :Version => "1.4"
403
- field :OCProperties, :Type => OptionalContent::Properties, :Version => "1.5"
404
- field :Perms, :Type => Dictionary, :Version => "1.5"
405
- field :Legal, :Type => Dictionary, :Version => "1.5"
406
- field :Requirements, :Type => Array.of(Requirement), :Version => "1.7"
407
- field :Collection, :Type => Collection, :Version => "1.7"
408
- field :NeedsRendering, :Type => Boolean, :Version => "1.7", :Default => false
409
- field :Extensions, :Type => Extensions, :Version => "1.7", :ExtensionLevel => 3
410
-
411
- def initialize(hash = {}, parser = nil)
412
- set_indirect(true)
413
-
414
- super(hash, parser)
415
- end
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