hexapdf 0.32.2 → 0.34.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +104 -1
  3. data/README.md +9 -0
  4. data/examples/002-graphics.rb +15 -17
  5. data/examples/003-arcs.rb +9 -9
  6. data/examples/009-text_layouter_alignment.rb +1 -1
  7. data/examples/010-text_layouter_inline_boxes.rb +2 -2
  8. data/examples/011-text_layouter_line_wrapping.rb +1 -1
  9. data/examples/012-text_layouter_styling.rb +7 -7
  10. data/examples/013-text_layouter_shapes.rb +1 -1
  11. data/examples/014-text_in_polygon.rb +1 -1
  12. data/examples/015-boxes.rb +8 -7
  13. data/examples/016-frame_automatic_box_placement.rb +2 -2
  14. data/examples/017-frame_text_flow.rb +2 -1
  15. data/examples/018-composer.rb +1 -1
  16. data/examples/020-column_box.rb +2 -1
  17. data/examples/025-table_box.rb +46 -0
  18. data/examples/026-optional_content.rb +55 -0
  19. data/examples/027-composer_optional_content.rb +83 -0
  20. data/lib/hexapdf/cli/command.rb +12 -3
  21. data/lib/hexapdf/cli/fonts.rb +1 -1
  22. data/lib/hexapdf/cli/form.rb +5 -5
  23. data/lib/hexapdf/cli/inspect.rb +5 -7
  24. data/lib/hexapdf/composer.rb +106 -53
  25. data/lib/hexapdf/configuration.rb +65 -40
  26. data/lib/hexapdf/content/canvas.rb +445 -267
  27. data/lib/hexapdf/content/color_space.rb +72 -25
  28. data/lib/hexapdf/content/graphic_object/arc.rb +57 -24
  29. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -23
  30. data/lib/hexapdf/content/graphic_object/geom2d.rb +47 -6
  31. data/lib/hexapdf/content/graphic_object/solid_arc.rb +58 -36
  32. data/lib/hexapdf/content/graphic_object.rb +6 -7
  33. data/lib/hexapdf/content/graphics_state.rb +54 -45
  34. data/lib/hexapdf/content/operator.rb +54 -54
  35. data/lib/hexapdf/content/parser.rb +2 -2
  36. data/lib/hexapdf/content/processor.rb +15 -15
  37. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  38. data/lib/hexapdf/content.rb +5 -0
  39. data/lib/hexapdf/dictionary.rb +7 -5
  40. data/lib/hexapdf/dictionary_fields.rb +43 -16
  41. data/lib/hexapdf/digital_signature/cms_handler.rb +2 -2
  42. data/lib/hexapdf/digital_signature/handler.rb +1 -1
  43. data/lib/hexapdf/digital_signature/pkcs1_handler.rb +2 -3
  44. data/lib/hexapdf/digital_signature/signature.rb +6 -6
  45. data/lib/hexapdf/digital_signature/signatures.rb +13 -12
  46. data/lib/hexapdf/digital_signature/signing/default_handler.rb +14 -5
  47. data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -4
  48. data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +4 -4
  49. data/lib/hexapdf/digital_signature/signing.rb +4 -0
  50. data/lib/hexapdf/digital_signature/verification_result.rb +3 -4
  51. data/lib/hexapdf/digital_signature.rb +7 -2
  52. data/lib/hexapdf/document/destinations.rb +12 -11
  53. data/lib/hexapdf/document/files.rb +1 -1
  54. data/lib/hexapdf/document/fonts.rb +1 -1
  55. data/lib/hexapdf/document/layout.rb +170 -39
  56. data/lib/hexapdf/document/pages.rb +4 -3
  57. data/lib/hexapdf/document.rb +96 -55
  58. data/lib/hexapdf/encryption/aes.rb +5 -5
  59. data/lib/hexapdf/encryption/arc4.rb +1 -1
  60. data/lib/hexapdf/encryption/fast_aes.rb +2 -2
  61. data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
  62. data/lib/hexapdf/encryption/identity.rb +1 -1
  63. data/lib/hexapdf/encryption/ruby_aes.rb +11 -21
  64. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  65. data/lib/hexapdf/encryption/security_handler.rb +31 -24
  66. data/lib/hexapdf/encryption/standard_security_handler.rb +45 -36
  67. data/lib/hexapdf/encryption.rb +7 -2
  68. data/lib/hexapdf/error.rb +18 -0
  69. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  70. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  71. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  72. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  73. data/lib/hexapdf/filter/pass_through.rb +1 -1
  74. data/lib/hexapdf/filter/predictor.rb +1 -1
  75. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  76. data/lib/hexapdf/filter.rb +55 -6
  77. data/lib/hexapdf/font/cmap/parser.rb +2 -2
  78. data/lib/hexapdf/font/cmap.rb +1 -1
  79. data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
  80. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  81. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
  82. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  83. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  84. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +3 -3
  85. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  86. data/lib/hexapdf/font/invalid_glyph.rb +3 -0
  87. data/lib/hexapdf/font/true_type_wrapper.rb +17 -4
  88. data/lib/hexapdf/font/type1_wrapper.rb +19 -4
  89. data/lib/hexapdf/font_loader/from_configuration.rb +5 -2
  90. data/lib/hexapdf/font_loader/from_file.rb +5 -5
  91. data/lib/hexapdf/font_loader/standard14.rb +3 -3
  92. data/lib/hexapdf/font_loader.rb +3 -0
  93. data/lib/hexapdf/image_loader/jpeg.rb +2 -2
  94. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  95. data/lib/hexapdf/image_loader/png.rb +2 -2
  96. data/lib/hexapdf/image_loader.rb +1 -1
  97. data/lib/hexapdf/importer.rb +13 -0
  98. data/lib/hexapdf/layout/box.rb +32 -5
  99. data/lib/hexapdf/layout/box_fitter.rb +2 -2
  100. data/lib/hexapdf/layout/column_box.rb +20 -5
  101. data/lib/hexapdf/layout/frame.rb +53 -18
  102. data/lib/hexapdf/layout/image_box.rb +5 -0
  103. data/lib/hexapdf/layout/inline_box.rb +21 -9
  104. data/lib/hexapdf/layout/list_box.rb +50 -20
  105. data/lib/hexapdf/layout/page_style.rb +6 -5
  106. data/lib/hexapdf/layout/style.rb +64 -9
  107. data/lib/hexapdf/layout/table_box.rb +684 -0
  108. data/lib/hexapdf/layout/text_box.rb +12 -3
  109. data/lib/hexapdf/layout/text_fragment.rb +29 -3
  110. data/lib/hexapdf/layout/text_layouter.rb +32 -8
  111. data/lib/hexapdf/layout.rb +1 -0
  112. data/lib/hexapdf/name_tree_node.rb +1 -1
  113. data/lib/hexapdf/number_tree_node.rb +1 -1
  114. data/lib/hexapdf/object.rb +18 -7
  115. data/lib/hexapdf/parser.rb +7 -7
  116. data/lib/hexapdf/pdf_array.rb +1 -1
  117. data/lib/hexapdf/rectangle.rb +1 -1
  118. data/lib/hexapdf/reference.rb +1 -1
  119. data/lib/hexapdf/revision.rb +1 -1
  120. data/lib/hexapdf/revisions.rb +3 -3
  121. data/lib/hexapdf/serializer.rb +15 -15
  122. data/lib/hexapdf/stream.rb +5 -4
  123. data/lib/hexapdf/tokenizer.rb +14 -14
  124. data/lib/hexapdf/type/acro_form/appearance_generator.rb +22 -22
  125. data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
  126. data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
  127. data/lib/hexapdf/type/acro_form/field.rb +2 -2
  128. data/lib/hexapdf/type/acro_form/form.rb +1 -1
  129. data/lib/hexapdf/type/acro_form/signature_field.rb +4 -4
  130. data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
  131. data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
  132. data/lib/hexapdf/type/acro_form.rb +1 -1
  133. data/lib/hexapdf/type/action.rb +1 -1
  134. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  135. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  136. data/lib/hexapdf/type/actions/launch.rb +1 -1
  137. data/lib/hexapdf/type/actions/set_ocg_state.rb +86 -0
  138. data/lib/hexapdf/type/actions/uri.rb +1 -1
  139. data/lib/hexapdf/type/actions.rb +2 -1
  140. data/lib/hexapdf/type/annotation.rb +3 -3
  141. data/lib/hexapdf/type/annotations/link.rb +1 -1
  142. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  143. data/lib/hexapdf/type/annotations/text.rb +2 -3
  144. data/lib/hexapdf/type/annotations/widget.rb +2 -2
  145. data/lib/hexapdf/type/annotations.rb +1 -1
  146. data/lib/hexapdf/type/catalog.rb +11 -2
  147. data/lib/hexapdf/type/cid_font.rb +18 -4
  148. data/lib/hexapdf/type/embedded_file.rb +1 -1
  149. data/lib/hexapdf/type/file_specification.rb +2 -2
  150. data/lib/hexapdf/type/font_descriptor.rb +1 -1
  151. data/lib/hexapdf/type/font_simple.rb +2 -2
  152. data/lib/hexapdf/type/font_type0.rb +3 -3
  153. data/lib/hexapdf/type/font_type3.rb +1 -1
  154. data/lib/hexapdf/type/form.rb +76 -6
  155. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  156. data/lib/hexapdf/type/icon_fit.rb +1 -1
  157. data/lib/hexapdf/type/image.rb +1 -1
  158. data/lib/hexapdf/type/info.rb +1 -1
  159. data/lib/hexapdf/type/mark_information.rb +1 -1
  160. data/lib/hexapdf/type/names.rb +2 -2
  161. data/lib/hexapdf/type/object_stream.rb +2 -1
  162. data/lib/hexapdf/type/optional_content_configuration.rb +170 -0
  163. data/lib/hexapdf/type/optional_content_group.rb +370 -0
  164. data/lib/hexapdf/type/optional_content_membership.rb +63 -0
  165. data/lib/hexapdf/type/optional_content_properties.rb +158 -0
  166. data/lib/hexapdf/type/outline.rb +1 -1
  167. data/lib/hexapdf/type/outline_item.rb +1 -1
  168. data/lib/hexapdf/type/page.rb +46 -21
  169. data/lib/hexapdf/type/page_label.rb +5 -9
  170. data/lib/hexapdf/type/page_tree_node.rb +1 -1
  171. data/lib/hexapdf/type/resources.rb +1 -1
  172. data/lib/hexapdf/type/trailer.rb +2 -2
  173. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  174. data/lib/hexapdf/type/xref_stream.rb +2 -2
  175. data/lib/hexapdf/type.rb +4 -0
  176. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -2
  177. data/lib/hexapdf/version.rb +1 -1
  178. data/lib/hexapdf/writer.rb +4 -4
  179. data/lib/hexapdf/xref_section.rb +2 -2
  180. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +11 -1
  181. data/test/hexapdf/content/graphic_object/test_geom2d.rb +7 -0
  182. data/test/hexapdf/content/test_canvas.rb +49 -1
  183. data/test/hexapdf/digital_signature/test_signatures.rb +22 -0
  184. data/test/hexapdf/document/test_files.rb +2 -2
  185. data/test/hexapdf/document/test_layout.rb +105 -2
  186. data/test/hexapdf/document/test_pages.rb +6 -6
  187. data/test/hexapdf/encryption/test_security_handler.rb +12 -11
  188. data/test/hexapdf/encryption/test_standard_security_handler.rb +35 -23
  189. data/test/hexapdf/font/test_true_type_wrapper.rb +18 -1
  190. data/test/hexapdf/font/test_type1_wrapper.rb +15 -1
  191. data/test/hexapdf/layout/test_box.rb +14 -5
  192. data/test/hexapdf/layout/test_column_box.rb +65 -21
  193. data/test/hexapdf/layout/test_frame.rb +27 -15
  194. data/test/hexapdf/layout/test_image_box.rb +4 -0
  195. data/test/hexapdf/layout/test_inline_box.rb +17 -3
  196. data/test/hexapdf/layout/test_list_box.rb +84 -33
  197. data/test/hexapdf/layout/test_page_style.rb +3 -2
  198. data/test/hexapdf/layout/test_style.rb +60 -0
  199. data/test/hexapdf/layout/test_table_box.rb +728 -0
  200. data/test/hexapdf/layout/test_text_box.rb +26 -0
  201. data/test/hexapdf/layout/test_text_fragment.rb +33 -0
  202. data/test/hexapdf/layout/test_text_layouter.rb +36 -5
  203. data/test/hexapdf/test_composer.rb +10 -0
  204. data/test/hexapdf/test_dictionary.rb +10 -0
  205. data/test/hexapdf/test_dictionary_fields.rb +4 -1
  206. data/test/hexapdf/test_document.rb +5 -0
  207. data/test/hexapdf/test_filter.rb +8 -0
  208. data/test/hexapdf/test_importer.rb +9 -0
  209. data/test/hexapdf/test_object.rb +16 -5
  210. data/test/hexapdf/test_stream.rb +7 -0
  211. data/test/hexapdf/test_writer.rb +3 -3
  212. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -5
  213. data/test/hexapdf/type/acro_form/test_form.rb +4 -3
  214. data/test/hexapdf/type/actions/test_set_ocg_state.rb +40 -0
  215. data/test/hexapdf/type/test_catalog.rb +11 -0
  216. data/test/hexapdf/type/test_form.rb +119 -0
  217. data/test/hexapdf/type/test_optional_content_configuration.rb +112 -0
  218. data/test/hexapdf/type/test_optional_content_group.rb +158 -0
  219. data/test/hexapdf/type/test_optional_content_properties.rb +109 -0
  220. data/test/hexapdf/type/test_page.rb +20 -6
  221. metadata +28 -8
@@ -64,32 +64,43 @@ end
64
64
  #
65
65
  # Here are some pointers to more in depth information:
66
66
  #
67
- # * For information about the command line application, see the HexaPDF::CLI module.
67
+ # * HexaPDF::CLI has information about the accompanying command line application.
68
68
  # * HexaPDF::Document provides information about how to work with a PDF file.
69
+ # * HexaPDF::Composer is the main class for easily creating PDF documents from scratch.
69
70
  # * HexaPDF::Content::Canvas provides the canvas API for drawing/writing on a page or form XObject
71
+ # * HexaPDF::Type::AcroForm::Form is the entry point for working with interactive forms.
72
+ # * HexaPDF::Type::Outline has information on working with outlines/bookmarks.
73
+ # * HexaPDF::Encryption provides information on how encryption works.
74
+ # * HexaPDF::DigitalSignature is the entry point for working with digital signaturs.
70
75
  module HexaPDF
71
76
 
72
77
  autoload(:Composer, 'hexapdf/composer')
73
78
 
74
79
  # == HexaPDF::Document
75
80
  #
76
- # Represents one PDF document.
81
+ # Represents a PDF document.
77
82
  #
78
- # A PDF document consists of (indirect) objects, so the main job of this class is to provide
79
- # methods for working with these objects. However, since a PDF document may also be
83
+ # A PDF document essentially consists of (indirect) objects, so the main job of this class is to
84
+ # provide methods for working with these objects. However, since a PDF document may also be
80
85
  # incrementally updated and can therefore contain one or more revisions, there are also methods
81
- # for working with these revisions.
86
+ # for working with these revisions (see Revisions for details).
82
87
  #
83
- # Note: This class provides everything to work on PDF documents on a low-level basis. This means
84
- # that there are no convenience methods for higher PDF functionality. Those can be found in the
85
- # objects linked from here, like #catalog.
88
+ # Additionally, there are many convenience methods for easily accessing the most important PDF
89
+ # functionality, like encrypting a document (#encrypt), working with digital signatures
90
+ # (#signatures), accessing the interactive form data (#acro_form), working with the pages
91
+ # (#pages), fonts (#fonts) and images (#images).
86
92
  #
87
- # == Known Messages
93
+ # Note: This class provides the basis for working with a PDF document. The higher PDF
94
+ # functionality is *not* implemented here but either in the appropriate PDF type classes or in
95
+ # special convenience classes. All this functionality can be accessed via the convenience methods
96
+ # described above.
97
+ #
98
+ # == Available Message Hooks
88
99
  #
89
100
  # The document object provides a basic message dispatch system via #register_listener and
90
101
  # #dispatch_message.
91
102
  #
92
- # Following are the messages that are used by HexaPDF itself:
103
+ # Following messages are used by HexaPDF itself:
93
104
  #
94
105
  # :complete_objects::
95
106
  # This message is called before the first step of writing a document. Listeners should
@@ -138,17 +149,22 @@ module HexaPDF
138
149
  end
139
150
  end
140
151
 
141
- # The configuration for the document.
152
+ # The configuration object for the document.
153
+ #
154
+ # See Configuration for details.
142
155
  attr_reader :config
143
156
 
144
157
  # The revisions of the document.
158
+ #
159
+ # See Revisions.
145
160
  attr_reader :revisions
146
161
 
147
162
  # Creates a new PDF document, either an empty one or one read from the provided +io+.
148
163
  #
149
164
  # When an IO object is provided and it contains an encrypted PDF file, it is automatically
150
165
  # decrypted behind the scenes. The +decryption_opts+ argument has to be set appropriately in
151
- # this case.
166
+ # this case. In case this is not wanted, the configuration option 'document.auto_decrypt' needs
167
+ # to be used.
152
168
  #
153
169
  # Options:
154
170
  #
@@ -183,8 +199,8 @@ module HexaPDF
183
199
  # doc.object(ref) -> obj or nil
184
200
  # doc.object(oid) -> obj or nil
185
201
  #
186
- # Returns the current version of the indirect object for the given exact reference or for the
187
- # given object number.
202
+ # Returns the current version of the indirect object for the given exact reference (see
203
+ # Reference) or for the given object number.
188
204
  #
189
205
  # For references to unknown objects, +nil+ is returned but free objects are represented by a
190
206
  # PDF Null object, not by +nil+!
@@ -199,7 +215,7 @@ module HexaPDF
199
215
  # doc.object?(oid) -> true or false
200
216
  #
201
217
  # Returns +true+ if the the document contains an indirect object for the given exact reference
202
- # or for the given object number.
218
+ # (see Reference) or for the given object number.
203
219
  #
204
220
  # Even though this method might return +true+ for some references, #object may return +nil+
205
221
  # because this method takes *all* revisions into account. Also see the discussion on #each for
@@ -212,7 +228,7 @@ module HexaPDF
212
228
 
213
229
  # Dereferences the given object.
214
230
  #
215
- # Return the object itself if it is not a reference, or the indirect object specified by the
231
+ # Returns the object itself if it is not a reference, or the indirect object specified by the
216
232
  # reference.
217
233
  def deref(obj)
218
234
  obj.kind_of?(Reference) ? object(obj) : obj
@@ -227,7 +243,7 @@ module HexaPDF
227
243
  # HexaPDF::Object. If it is not the latter, #wrap is called with the object and the
228
244
  # additional keyword arguments.
229
245
  #
230
- # See: Revisions#add_object
246
+ # See: #wrap, Revisions#add_object
231
247
  def add(obj, **wrap_opts)
232
248
  obj = wrap(obj, **wrap_opts) unless obj.kind_of?(HexaPDF::Object)
233
249
 
@@ -266,14 +282,14 @@ module HexaPDF
266
282
  HexaPDF::Importer.for(self).import(obj, source: source)
267
283
  end
268
284
 
269
- # Wraps the given object inside a HexaPDF::Object class which allows one to use
285
+ # Wraps the given object inside a HexaPDF::Object (sub)class which allows one to use
270
286
  # convenience functions to work with the object.
271
287
  #
272
288
  # The +obj+ argument can also be a HexaPDF::Object object so that it can be re-wrapped if
273
- # needed.
289
+ # necessary.
274
290
  #
275
291
  # The class of the returned object is always a subclass of HexaPDF::Object (or of
276
- # HexaPDF::Stream if a +stream+ is given). Which subclass is used, depends on the values of the
292
+ # HexaPDF::Stream if +stream+ is given). Which subclass is used, depends on the values of the
277
293
  # +type+ and +subtype+ options as well as on the 'object.type_map' and 'object.subtype_map'
278
294
  # global configuration options:
279
295
  #
@@ -291,13 +307,13 @@ module HexaPDF
291
307
  #
292
308
  # * If there is no valid class after the above steps, HexaPDF::Stream is used if a stream is
293
309
  # given, HexaPDF::Dictionary if the given object is a hash, HexaPDF::PDFArray if it is an
294
- # array or else HexaPDF::Object is used.
310
+ # array or else HexaPDF::Object.
295
311
  #
296
312
  # Options:
297
313
  #
298
314
  # :type:: (Symbol or Class) The type of a PDF object that should be used for wrapping. This
299
315
  # could be, for example, :Pages. If a class object is provided, it is used directly
300
- # instead of the type detection system.
316
+ # instead of determining the class through the type detection system.
301
317
  #
302
318
  # :subtype:: (Symbol) The subtype of a PDF object which further qualifies a type. For
303
319
  # example, image objects in PDF have a type of :XObject and a subtype of :Image.
@@ -341,7 +357,9 @@ module HexaPDF
341
357
  if subtype
342
358
  sub_klass = GlobalConfiguration.constantize('object.subtype_map', type, subtype) { klass }
343
359
  if type ||
344
- sub_klass&.each_field&.none? {|name, field| field.required? && !data.value.key?(name) }
360
+ sub_klass&.each_field&.none? do |name, field|
361
+ field.required? && !data.value.key?(name) && name != :Type
362
+ end
345
363
  klass = sub_klass
346
364
  end
347
365
  end
@@ -410,6 +428,11 @@ module HexaPDF
410
428
  # doc.register_listener(name) {|*args| block} -> block
411
429
  #
412
430
  # Registers the given listener for the message +name+.
431
+ #
432
+ # If +callable+ is provided, it needs to be an Object responding to #call. Otherwise the block
433
+ # has to be provided. The arguments that are provided to the #call method depend on the message.
434
+ #
435
+ # See: dispatch_message
413
436
  def register_listener(name, callable = nil, &block)
414
437
  callable ||= block
415
438
  (@listeners[name] ||= []) << callable
@@ -420,6 +443,8 @@ module HexaPDF
420
443
  #
421
444
  # See the main Document documentation for an overview of messages that are used by HexaPDF
422
445
  # itself.
446
+ #
447
+ # See: register_listener
423
448
  def dispatch_message(name, *args)
424
449
  @listeners[name]&.each {|obj| obj.call(*args) }
425
450
  end
@@ -427,10 +452,10 @@ module HexaPDF
427
452
  UNSET = ::Object.new # :nordoc:
428
453
 
429
454
  # Caches and returns the given +value+ or the value of the given block using the given
430
- # +pdf_data+ and +key+ arguments as composite cache key. If a cached value already exists and
431
- # +update+ is +false+, the cached value is just returned.
455
+ # +pdf_data+ and +key+ arguments as composite cache key.
432
456
  #
433
- # Set +update+ to +true+ to force an update of the cached value.
457
+ # If a cached value already exists and +update+ is +false+, the cached value is just returned.
458
+ # If +update+ is set to +true+, an update of the cached value is forced.
434
459
  #
435
460
  # This facility can be used to cache expensive operations in PDF objects that are easy to
436
461
  # compute again.
@@ -444,7 +469,7 @@ module HexaPDF
444
469
  # Returns +true+ if there is a value cached for the composite key consisting of the given
445
470
  # +pdf_data+ and +key+ objects.
446
471
  #
447
- # Also see: #cache
472
+ # See: #cache
448
473
  def cached?(pdf_data, key)
449
474
  @cache.key?(pdf_data) && @cache[pdf_data].key?(key)
450
475
  end
@@ -455,29 +480,32 @@ module HexaPDF
455
480
  # It is *not* recommended to clear the whole cache! Better clear the cache for individual PDF
456
481
  # objects!
457
482
  #
458
- # Also see: #cache
483
+ # See: #cache, #cached?
459
484
  def clear_cache(pdf_data = nil)
460
485
  pdf_data ? @cache[pdf_data].clear : @cache.clear
461
486
  end
462
487
 
463
- # Returns the Pages object that provides convenience methods for working with pages.
488
+ # Returns the Pages object that provides convenience methods for working with the pages of the
489
+ # PDF file.
464
490
  #
465
- # Also see: HexaPDF::Type::PageTreeNode
491
+ # See: Pages, Type::PageTreeNode
466
492
  def pages
467
493
  @pages ||= Pages.new(self)
468
494
  end
469
495
 
470
- # Returns the Images object that provides convenience methods for working with images.
496
+ # Returns the Images object that provides convenience methods for working with images (e.g.
497
+ # adding them to the PDF or listing them).
471
498
  def images
472
499
  @images ||= Images.new(self)
473
500
  end
474
501
 
475
- # Returns the Files object that provides convenience methods for working with files.
502
+ # Returns the Files object that provides convenience methods for working with embedded files.
476
503
  def files
477
504
  @files ||= Files.new(self)
478
505
  end
479
506
 
480
- # Returns the Fonts object that provides convenience methods for working with fonts.
507
+ # Returns the Fonts object that provides convenience methods for working with the fonts used in
508
+ # the PDF file.
481
509
  def fonts
482
510
  @fonts ||= Fonts.new(self)
483
511
  end
@@ -496,24 +524,33 @@ module HexaPDF
496
524
 
497
525
  # Returns the main AcroForm object for dealing with interactive forms.
498
526
  #
499
- # See HexaPDF::Type::Catalog#acro_form for details on the arguments.
527
+ # The meaning of the +create+ argument is detailed at Type::Catalog#acro_form.
528
+ #
529
+ # See: Type::AcroForm::Form
500
530
  def acro_form(create: false)
501
531
  catalog.acro_form(create: create)
502
532
  end
503
533
 
504
- # Returns the main document outline object.
534
+ # Returns the entry object to the document outline (a.k.a. bookmarks).
505
535
  #
506
- # See HexaPDF::Type::Outline for details.
536
+ # See: Type::Outline
507
537
  def outline
508
538
  catalog.outline
509
539
  end
510
540
 
541
+ # Returns the main object for working with optional content (a.k.a. layers).
542
+ #
543
+ # See: Type::Catalog#optional_content
544
+ def optional_content
545
+ catalog.optional_content
546
+ end
547
+
511
548
  # Executes the given task and returns its result.
512
549
  #
513
550
  # Tasks provide an extensible way for performing operations on a PDF document without
514
551
  # cluttering the Document interface.
515
552
  #
516
- # See Task for more information.
553
+ # See: Task
517
554
  def task(name, **opts, &block)
518
555
  task = config.constantize('task.map', name) do
519
556
  raise HexaPDF::Error, "No task named '#{name}' is available"
@@ -522,11 +559,15 @@ module HexaPDF
522
559
  end
523
560
 
524
561
  # Returns the trailer dictionary for the document.
562
+ #
563
+ # See: Type::Trailer
525
564
  def trailer
526
565
  @revisions.current.trailer
527
566
  end
528
567
 
529
568
  # Returns the document's catalog, the root of the object tree.
569
+ #
570
+ # See: Type::Catalog
530
571
  def catalog
531
572
  trailer.catalog
532
573
  end
@@ -537,14 +578,16 @@ module HexaPDF
537
578
  # version has been set manually and the catalog's /Version key refers to a later version, the
538
579
  # later version is used.
539
580
  #
540
- # See: PDF1.7 s7.2.2
581
+ # See: PDF2.0 s7.2.2
541
582
  def version
542
583
  catalog_version = (catalog[:Version] || '1.0').to_s
543
584
  (@version < catalog_version ? catalog_version : @version)
544
585
  end
545
586
 
546
- # Sets the version of the PDF document. The argument must be a string in the format 'M.N'
547
- # where M is the major version and N the minor version (e.g. '1.4' or '2.0').
587
+ # Sets the version of the PDF document.
588
+ #
589
+ # The argument +value+ must be a string in the format 'M.N' where M is the major version and N
590
+ # the minor version (e.g. '1.4' or '2.0').
548
591
  def version=(value)
549
592
  raise ArgumentError, "PDF version must follow format M.N" unless value.to_s.match?(/\A\d\.\d\z/)
550
593
  @version = value.to_s
@@ -557,9 +600,9 @@ module HexaPDF
557
600
 
558
601
  # Encrypts the document.
559
602
  #
560
- # This is done by setting up a security handler for this purpose and populating the trailer's
561
- # Encrypt dictionary accordingly. The actual encryption, however, is only done when writing the
562
- # document.
603
+ # Encryption is done by setting up a security handler for this purpose and populating the
604
+ # trailer's Encrypt dictionary accordingly. The actual encryption, however, is only done when
605
+ # writing the document.
563
606
  #
564
607
  # The security handler used for encrypting is selected via the +name+ argument. All other
565
608
  # arguments are passed on the security handler.
@@ -567,9 +610,8 @@ module HexaPDF
567
610
  # If the document should not be encrypted, the +name+ argument has to be set to +nil+. This
568
611
  # removes the security handler and deletes the trailer's Encrypt dictionary.
569
612
  #
570
- # See: HexaPDF::Encryption::SecurityHandler#set_up_encryption and
571
- # HexaPDF::Encryption::StandardSecurityHandler::EncryptionOptions for possible encryption
572
- # options.
613
+ # See: Encryption::SecurityHandler#set_up_encryption and
614
+ # Encryption::StandardSecurityHandler::EncryptionOptions for possible encryption options.
573
615
  def encrypt(name: :Standard, **options)
574
616
  if name.nil?
575
617
  trailer.delete(:Encrypt)
@@ -605,17 +647,16 @@ module HexaPDF
605
647
  # Signs the document and writes it to the given file or IO object.
606
648
  #
607
649
  # For details on the arguments +file_or_io+, +signature+ and +write_options+ see
608
- # HexaPDF::DigitalSignature::Signatures#add.
650
+ # DigitalSignature::Signatures#add.
609
651
  #
610
652
  # The signing handler to be used is determined by the +handler+ argument together with the rest
611
- # of the keyword arguments (see HexaPDF::DigitalSignature::Signatures#signing_handler for
612
- # details).
653
+ # of the keyword arguments (see DigitalSignature::Signatures#signing_handler for details).
613
654
  #
614
- # If not changed, the default signing handler is
615
- # HexaPDF::DigitalSignature::Signing::DefaultHandler.
655
+ # If not changed, the default signing handler is DigitalSignature::Signing::DefaultHandler.
616
656
  #
617
- # *Note*: Once signing is done the document cannot be changed anymore since it was written. If a
618
- # document needs to be signed multiple times, it needs to be loaded again after writing.
657
+ # *Note*: Once signing is done the document cannot be changed anymore since it was written
658
+ # during the signing process. If a document needs to be signed multiple times, it needs to be
659
+ # loaded again afterwards.
619
660
  def sign(file_or_io, handler: :default, signature: nil, write_options: {}, **handler_options)
620
661
  handler = signatures.signing_handler(name: handler, **handler_options)
621
662
  signatures.add(file_or_io, handler, signature: signature, write_options: write_options)
@@ -626,7 +667,7 @@ module HexaPDF
626
667
  #
627
668
  # If a block is given, it is called on validation problems.
628
669
  #
629
- # See HexaPDF::Object#validate for more information.
670
+ # See Object#validate for more information.
630
671
  def validate(auto_correct: true, only_loaded: false, &block) #:yield: msg, correctable, object
631
672
  result = trailer.validate(auto_correct: auto_correct, &block)
632
673
  each(only_loaded: only_loaded) do |obj|
@@ -651,7 +692,7 @@ module HexaPDF
651
692
  # This is needed, for example, when modifying a signed PDF and the original signature should
652
693
  # stay valid.
653
694
  #
654
- # See: PDF1.7 s7.5.6
695
+ # See: PDF2.0 s7.5.6
655
696
  #
656
697
  # validate::
657
698
  # Validates the document and raises an error if an uncorrectable problem is found.
@@ -43,7 +43,7 @@ module HexaPDF
43
43
  # Common interface for AES algorithms
44
44
  #
45
45
  # This module defines the common interface that is used by the security handlers to encrypt or
46
- # decrypt data with AES. It has to be *prepended* by any AES algorithm class.
46
+ # decrypt data with AES. It has to be *prepended* by any specific AES algorithm class.
47
47
  #
48
48
  # See the ClassMethods module for available class level methods of AES algorithms.
49
49
  #
@@ -79,7 +79,7 @@ module HexaPDF
79
79
  # The data is padded using the PKCS#5 padding scheme and the initialization vector is
80
80
  # prepended to the encrypted data,
81
81
  #
82
- # See: PDF1.7 s7.6.2.
82
+ # See: PDF2.0 s7.6.3
83
83
  def encrypt(key, data)
84
84
  iv = random_bytes(BLOCK_SIZE)
85
85
  iv << new(key, iv, :encrypt).process(pad(data))
@@ -112,7 +112,7 @@ module HexaPDF
112
112
  # It is assumed that the initialization vector is included in the first BLOCK_SIZE bytes
113
113
  # of the data. After the decryption the PKCS#5 padding is removed.
114
114
  #
115
- # See: PDF1.7 s7.6.2.
115
+ # See: PDF2.0 s7.6.3
116
116
  def decrypt(key, data)
117
117
  return data if data.empty? # Handle invalid files with empty strings
118
118
  if data.length % BLOCK_SIZE != 0 || data.length < BLOCK_SIZE
@@ -167,7 +167,7 @@ module HexaPDF
167
167
  # Pads the data to a muliple of BLOCK_SIZE using the PKCS#5 padding scheme and returns the
168
168
  # result.
169
169
  #
170
- # See: PDF1.7 s7.6.2
170
+ # See: PDF2.0 s7.6.3
171
171
  def pad(data)
172
172
  padding_length = BLOCK_SIZE - data.size % BLOCK_SIZE
173
173
  data + padding_length.chr * padding_length
@@ -179,7 +179,7 @@ module HexaPDF
179
179
  # In case the padding is not correct as per the specification, it is assumed that there is
180
180
  # no padding and the input is returned as is.
181
181
  #
182
- # See: PDF1.7 s7.6.2
182
+ # See: PDF2.0 s7.6.3
183
183
  def unpad(data)
184
184
  padding_length = data.getbyte(-1)
185
185
  if padding_length > BLOCK_SIZE || padding_length == 0 ||
@@ -65,7 +65,7 @@ module HexaPDF
65
65
 
66
66
  # Encrypts the given +data+ with the +key+.
67
67
  #
68
- # See: PDF1.7 s7.6.2.
68
+ # See: PDF2.0 s7.6.3
69
69
  def encrypt(key, data)
70
70
  new(key).process(data)
71
71
  end
@@ -48,7 +48,7 @@ module HexaPDF
48
48
  #
49
49
  # This implementation is using AES in Cipher Block Chaining (CBC) mode.
50
50
  #
51
- # See: PDF1.7 s7.6.2
51
+ # See: PDF2.0 s7.6.3
52
52
  class FastAES
53
53
 
54
54
  prepend AES
@@ -68,7 +68,7 @@ module HexaPDF
68
68
  @cipher.send(mode)
69
69
  @cipher.key = key
70
70
  @cipher.iv = iv
71
- @cipher.padding = 0
71
+ @cipher.padding = 0 # Padding handled by HexaPDF, also no @cipher.final call needed
72
72
  end
73
73
 
74
74
  # Encrypts or decrypts the given data whose length must be a multiple of 16.
@@ -45,7 +45,7 @@ module HexaPDF
45
45
 
46
46
  # Implementation of the general encryption algorithm ARC4 using OpenSSL as backend.
47
47
  #
48
- # See: PDF1.7 s7.6.2
48
+ # See: PDF2.0 s7.6.3
49
49
  class FastARC4
50
50
 
51
51
  prepend ARC4
@@ -42,7 +42,7 @@ module HexaPDF
42
42
  # This "algorithm" does nothing, i.e. it returns the given data as is without encrypting or
43
43
  # decrypting it.
44
44
  #
45
- # See: PDF1.7 s7.6.5
45
+ # See: PDF2.0 s7.6.6
46
46
  module Identity
47
47
 
48
48
  class << self
@@ -51,7 +51,7 @@ module HexaPDF
51
51
  #
52
52
  # This implementation is using AES in Cipher Block Chaining (CBC) mode.
53
53
  #
54
- # See: PDF1.7 s7.6.2
54
+ # See: PDF2.0 s7.6.3
55
55
  class RubyAES
56
56
 
57
57
  prepend AES
@@ -92,9 +92,8 @@ module HexaPDF
92
92
 
93
93
  private
94
94
 
95
- # :nodoc:
96
95
  # Rijndael S-box
97
- SBOX = [
96
+ SBOX = [ # :nodoc:
98
97
  0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
99
98
  0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
100
99
  0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
@@ -113,9 +112,8 @@ module HexaPDF
113
112
  0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
114
113
  ].freeze
115
114
 
116
- # :nodoc:
117
115
  # Inverse of the Rijndael S-box
118
- INV_SBOX = [
116
+ INV_SBOX = [ # :nodoc:
119
117
  0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
120
118
  0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
121
119
  0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
@@ -134,12 +132,10 @@ module HexaPDF
134
132
  0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
135
133
  ].freeze
136
134
 
137
- # :nodoc:
138
- RCON = [0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c].freeze
135
+ RCON = [0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c].freeze # :nodoc:
139
136
 
140
- # :nodoc:
141
137
  # Precomputed Galois multiplication table for multiplication with 2 in GF(2^8)
142
- G2MULT = [
138
+ G2MULT = [ # :nodoc:
143
139
  0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
144
140
  0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
145
141
  0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
@@ -158,9 +154,8 @@ module HexaPDF
158
154
  0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
159
155
  ].freeze
160
156
 
161
- # :nodoc:
162
157
  # Precomputed Galois multiplication table for multiplication with 3 in GF(2^8)
163
- G3MULT = [
158
+ G3MULT = [ # :nodoc:
164
159
  0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
165
160
  0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
166
161
  0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
@@ -179,9 +174,8 @@ module HexaPDF
179
174
  0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
180
175
  ].freeze
181
176
 
182
- # :nodoc:
183
177
  # Precomputed Galois multiplication table for multiplication with 9 in GF(2^8)
184
- G9MULT = [
178
+ G9MULT = [ # :nodoc:
185
179
  0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
186
180
  0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
187
181
  0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
@@ -200,9 +194,8 @@ module HexaPDF
200
194
  0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
201
195
  ].freeze
202
196
 
203
- # :nodoc:
204
197
  # Precomputed Galois multiplication table for multiplication with 11 in GF(2^8)
205
- G11MULT = [
198
+ G11MULT = [ # :nodoc:
206
199
  0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
207
200
  0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
208
201
  0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
@@ -221,9 +214,8 @@ module HexaPDF
221
214
  0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
222
215
  ].freeze
223
216
 
224
- # :nodoc:
225
217
  # Precomputed Galois multiplication table for multiplication with 13 in GF(2^8)
226
- G13MULT = [
218
+ G13MULT = [ # :nodoc:
227
219
  0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
228
220
  0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
229
221
  0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
@@ -242,9 +234,8 @@ module HexaPDF
242
234
  0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
243
235
  ].freeze
244
236
 
245
- # :nodoc:
246
237
  # Precomputed Galois multiplication table for multiplication with 14 in GF(2^8)
247
- G14MULT = [
238
+ G14MULT = [ # :nodoc:
248
239
  0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
249
240
  0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
250
241
  0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
@@ -263,9 +254,8 @@ module HexaPDF
263
254
  0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
264
255
  ].freeze
265
256
 
266
- # :nodoc:
267
257
  # Number of rounds needed in various parts of the algorithm, depends on the key size
268
- NUMBER_OF_ROUNDS = {16 => 10, 24 => 12, 32 => 14}.freeze
258
+ NUMBER_OF_ROUNDS = {16 => 10, 24 => 12, 32 => 14}.freeze # :nodoc:
269
259
 
270
260
  # KeyExpansion step
271
261
  #
@@ -46,7 +46,7 @@ module HexaPDF
46
46
  #
47
47
  # For reference: This implementation is about 250 times slower than the FastARC4 version.
48
48
  #
49
- # See: PDF1.7 s7.6.2
49
+ # See: PDF2.0 s7.6.3
50
50
  class RubyARC4
51
51
 
52
52
  prepend ARC4