hexapdf 0.30.0 → 0.32.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 (241) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +54 -1
  3. data/LICENSE +1 -1
  4. data/examples/020-column_box.rb +10 -11
  5. data/examples/021-list_box.rb +5 -5
  6. data/lib/hexapdf/cli/batch.rb +1 -1
  7. data/lib/hexapdf/cli/command.rb +17 -2
  8. data/lib/hexapdf/cli/files.rb +1 -1
  9. data/lib/hexapdf/cli/fonts.rb +1 -1
  10. data/lib/hexapdf/cli/form.rb +1 -1
  11. data/lib/hexapdf/cli/image2pdf.rb +1 -1
  12. data/lib/hexapdf/cli/images.rb +1 -1
  13. data/lib/hexapdf/cli/info.rb +10 -2
  14. data/lib/hexapdf/cli/inspect.rb +3 -3
  15. data/lib/hexapdf/cli/merge.rb +1 -1
  16. data/lib/hexapdf/cli/modify.rb +1 -1
  17. data/lib/hexapdf/cli/optimize.rb +1 -1
  18. data/lib/hexapdf/cli/split.rb +1 -1
  19. data/lib/hexapdf/cli/watermark.rb +1 -1
  20. data/lib/hexapdf/cli.rb +1 -1
  21. data/lib/hexapdf/composer.rb +97 -29
  22. data/lib/hexapdf/configuration.rb +18 -5
  23. data/lib/hexapdf/content/canvas.rb +1 -1
  24. data/lib/hexapdf/content/color_space.rb +1 -1
  25. data/lib/hexapdf/content/graphic_object/arc.rb +1 -1
  26. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
  27. data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
  28. data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
  29. data/lib/hexapdf/content/graphic_object.rb +1 -1
  30. data/lib/hexapdf/content/graphics_state.rb +1 -1
  31. data/lib/hexapdf/content/operator.rb +1 -1
  32. data/lib/hexapdf/content/parser.rb +1 -1
  33. data/lib/hexapdf/content/processor.rb +1 -1
  34. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  35. data/lib/hexapdf/content.rb +1 -1
  36. data/lib/hexapdf/data_dir.rb +1 -1
  37. data/lib/hexapdf/dictionary.rb +1 -1
  38. data/lib/hexapdf/dictionary_fields.rb +1 -1
  39. data/lib/hexapdf/digital_signature/cms_handler.rb +1 -1
  40. data/lib/hexapdf/digital_signature/handler.rb +1 -1
  41. data/lib/hexapdf/digital_signature/pkcs1_handler.rb +1 -1
  42. data/lib/hexapdf/digital_signature/signature.rb +1 -1
  43. data/lib/hexapdf/digital_signature/signatures.rb +1 -1
  44. data/lib/hexapdf/digital_signature/signing/default_handler.rb +1 -1
  45. data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +1 -1
  46. data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +1 -1
  47. data/lib/hexapdf/digital_signature/signing.rb +1 -1
  48. data/lib/hexapdf/digital_signature/verification_result.rb +1 -1
  49. data/lib/hexapdf/digital_signature.rb +1 -1
  50. data/lib/hexapdf/document/destinations.rb +1 -1
  51. data/lib/hexapdf/document/files.rb +1 -1
  52. data/lib/hexapdf/document/fonts.rb +1 -1
  53. data/lib/hexapdf/document/images.rb +1 -1
  54. data/lib/hexapdf/document/layout.rb +122 -39
  55. data/lib/hexapdf/document/pages.rb +2 -6
  56. data/lib/hexapdf/document.rb +9 -2
  57. data/lib/hexapdf/encryption/aes.rb +3 -1
  58. data/lib/hexapdf/encryption/arc4.rb +1 -1
  59. data/lib/hexapdf/encryption/fast_aes.rb +1 -1
  60. data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
  61. data/lib/hexapdf/encryption/identity.rb +1 -1
  62. data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
  63. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  64. data/lib/hexapdf/encryption/security_handler.rb +4 -1
  65. data/lib/hexapdf/encryption/standard_security_handler.rb +1 -1
  66. data/lib/hexapdf/encryption.rb +1 -1
  67. data/lib/hexapdf/error.rb +12 -2
  68. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  69. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  70. data/lib/hexapdf/filter/crypt.rb +1 -1
  71. data/lib/hexapdf/filter/encryption.rb +1 -1
  72. data/lib/hexapdf/filter/flate_decode.rb +21 -9
  73. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  74. data/lib/hexapdf/filter/pass_through.rb +1 -1
  75. data/lib/hexapdf/filter/predictor.rb +1 -1
  76. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  77. data/lib/hexapdf/filter.rb +1 -1
  78. data/lib/hexapdf/font/cmap/parser.rb +1 -1
  79. data/lib/hexapdf/font/cmap/writer.rb +1 -1
  80. data/lib/hexapdf/font/cmap.rb +1 -1
  81. data/lib/hexapdf/font/encoding/base.rb +1 -1
  82. data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
  83. data/lib/hexapdf/font/encoding/glyph_list.rb +1 -1
  84. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  85. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
  86. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  87. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  88. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +1 -1
  89. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  90. data/lib/hexapdf/font/encoding.rb +1 -1
  91. data/lib/hexapdf/font/invalid_glyph.rb +1 -1
  92. data/lib/hexapdf/font/true_type/builder.rb +1 -1
  93. data/lib/hexapdf/font/true_type/font.rb +1 -1
  94. data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
  95. data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
  96. data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
  97. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
  98. data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
  99. data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
  100. data/lib/hexapdf/font/true_type/table/head.rb +1 -1
  101. data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
  102. data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
  103. data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
  104. data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
  105. data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
  106. data/lib/hexapdf/font/true_type/table/name.rb +1 -1
  107. data/lib/hexapdf/font/true_type/table/os2.rb +1 -1
  108. data/lib/hexapdf/font/true_type/table/post.rb +1 -1
  109. data/lib/hexapdf/font/true_type/table.rb +1 -1
  110. data/lib/hexapdf/font/true_type.rb +1 -1
  111. data/lib/hexapdf/font/true_type_wrapper.rb +1 -1
  112. data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
  113. data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
  114. data/lib/hexapdf/font/type1/font.rb +1 -1
  115. data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
  116. data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
  117. data/lib/hexapdf/font/type1.rb +1 -1
  118. data/lib/hexapdf/font/type1_wrapper.rb +1 -1
  119. data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
  120. data/lib/hexapdf/font_loader/from_file.rb +1 -1
  121. data/lib/hexapdf/font_loader/standard14.rb +1 -1
  122. data/lib/hexapdf/font_loader.rb +1 -1
  123. data/lib/hexapdf/image_loader/jpeg.rb +1 -1
  124. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  125. data/lib/hexapdf/image_loader/png.rb +1 -1
  126. data/lib/hexapdf/image_loader.rb +1 -1
  127. data/lib/hexapdf/importer.rb +1 -1
  128. data/lib/hexapdf/layout/box.rb +1 -1
  129. data/lib/hexapdf/layout/box_fitter.rb +1 -1
  130. data/lib/hexapdf/layout/column_box.rb +1 -1
  131. data/lib/hexapdf/layout/frame.rb +1 -1
  132. data/lib/hexapdf/layout/image_box.rb +1 -1
  133. data/lib/hexapdf/layout/inline_box.rb +17 -3
  134. data/lib/hexapdf/layout/line.rb +1 -1
  135. data/lib/hexapdf/layout/list_box.rb +1 -1
  136. data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
  137. data/lib/hexapdf/layout/page_style.rb +144 -0
  138. data/lib/hexapdf/layout/style.rb +1 -1
  139. data/lib/hexapdf/layout/text_box.rb +1 -1
  140. data/lib/hexapdf/layout/text_fragment.rb +1 -1
  141. data/lib/hexapdf/layout/text_layouter.rb +4 -7
  142. data/lib/hexapdf/layout/text_shaper.rb +1 -1
  143. data/lib/hexapdf/layout/width_from_polygon.rb +1 -1
  144. data/lib/hexapdf/layout.rb +2 -1
  145. data/lib/hexapdf/name_tree_node.rb +1 -1
  146. data/lib/hexapdf/number_tree_node.rb +1 -1
  147. data/lib/hexapdf/object.rb +1 -1
  148. data/lib/hexapdf/parser.rb +1 -1
  149. data/lib/hexapdf/pdf_array.rb +1 -1
  150. data/lib/hexapdf/rectangle.rb +1 -1
  151. data/lib/hexapdf/reference.rb +1 -1
  152. data/lib/hexapdf/revision.rb +1 -1
  153. data/lib/hexapdf/revisions.rb +1 -1
  154. data/lib/hexapdf/serializer.rb +1 -1
  155. data/lib/hexapdf/stream.rb +1 -1
  156. data/lib/hexapdf/task/dereference.rb +1 -1
  157. data/lib/hexapdf/task/optimize.rb +9 -7
  158. data/lib/hexapdf/task.rb +1 -1
  159. data/lib/hexapdf/test_utils.rb +1 -1
  160. data/lib/hexapdf/tokenizer.rb +2 -1
  161. data/lib/hexapdf/type/acro_form/appearance_generator.rb +1 -1
  162. data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
  163. data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
  164. data/lib/hexapdf/type/acro_form/field.rb +1 -1
  165. data/lib/hexapdf/type/acro_form/form.rb +1 -1
  166. data/lib/hexapdf/type/acro_form/signature_field.rb +1 -1
  167. data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
  168. data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
  169. data/lib/hexapdf/type/acro_form.rb +1 -1
  170. data/lib/hexapdf/type/action.rb +1 -1
  171. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  172. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  173. data/lib/hexapdf/type/actions/launch.rb +1 -1
  174. data/lib/hexapdf/type/actions/uri.rb +1 -1
  175. data/lib/hexapdf/type/actions.rb +1 -1
  176. data/lib/hexapdf/type/annotation.rb +1 -1
  177. data/lib/hexapdf/type/annotations/link.rb +1 -1
  178. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  179. data/lib/hexapdf/type/annotations/text.rb +1 -1
  180. data/lib/hexapdf/type/annotations/widget.rb +1 -1
  181. data/lib/hexapdf/type/annotations.rb +1 -1
  182. data/lib/hexapdf/type/catalog.rb +1 -1
  183. data/lib/hexapdf/type/cid_font.rb +1 -1
  184. data/lib/hexapdf/type/embedded_file.rb +1 -1
  185. data/lib/hexapdf/type/file_specification.rb +1 -1
  186. data/lib/hexapdf/type/font.rb +1 -1
  187. data/lib/hexapdf/type/font_descriptor.rb +1 -1
  188. data/lib/hexapdf/type/font_simple.rb +1 -1
  189. data/lib/hexapdf/type/font_true_type.rb +1 -1
  190. data/lib/hexapdf/type/font_type0.rb +1 -1
  191. data/lib/hexapdf/type/font_type1.rb +1 -1
  192. data/lib/hexapdf/type/font_type3.rb +1 -1
  193. data/lib/hexapdf/type/form.rb +1 -1
  194. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  195. data/lib/hexapdf/type/icon_fit.rb +1 -1
  196. data/lib/hexapdf/type/image.rb +1 -1
  197. data/lib/hexapdf/type/info.rb +1 -1
  198. data/lib/hexapdf/type/mark_information.rb +1 -1
  199. data/lib/hexapdf/type/names.rb +1 -1
  200. data/lib/hexapdf/type/object_stream.rb +8 -3
  201. data/lib/hexapdf/type/outline.rb +2 -2
  202. data/lib/hexapdf/type/outline_item.rb +11 -2
  203. data/lib/hexapdf/type/page.rb +36 -9
  204. data/lib/hexapdf/type/page_label.rb +1 -1
  205. data/lib/hexapdf/type/page_tree_node.rb +1 -1
  206. data/lib/hexapdf/type/resources.rb +1 -1
  207. data/lib/hexapdf/type/trailer.rb +1 -1
  208. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  209. data/lib/hexapdf/type/xref_stream.rb +12 -5
  210. data/lib/hexapdf/type.rb +1 -1
  211. data/lib/hexapdf/utils/bit_field.rb +1 -1
  212. data/lib/hexapdf/utils/bit_stream.rb +1 -1
  213. data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
  214. data/lib/hexapdf/utils/lru_cache.rb +1 -1
  215. data/lib/hexapdf/utils/math_helpers.rb +1 -1
  216. data/lib/hexapdf/utils/object_hash.rb +1 -1
  217. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  218. data/lib/hexapdf/utils/sorted_tree_node.rb +1 -1
  219. data/lib/hexapdf/version.rb +2 -2
  220. data/lib/hexapdf/writer.rb +2 -2
  221. data/lib/hexapdf/xref_section.rb +1 -1
  222. data/lib/hexapdf.rb +1 -1
  223. data/test/hexapdf/document/test_layout.rb +80 -17
  224. data/test/hexapdf/encryption/common.rb +4 -0
  225. data/test/hexapdf/encryption/test_aes.rb +8 -0
  226. data/test/hexapdf/encryption/test_security_handler.rb +6 -0
  227. data/test/hexapdf/filter/test_flate_decode.rb +19 -5
  228. data/test/hexapdf/layout/test_inline_box.rb +35 -15
  229. data/test/hexapdf/layout/test_page_style.rb +70 -0
  230. data/test/hexapdf/layout/test_text_box.rb +5 -2
  231. data/test/hexapdf/layout/test_text_layouter.rb +6 -11
  232. data/test/hexapdf/task/test_optimize.rb +11 -9
  233. data/test/hexapdf/test_composer.rb +49 -11
  234. data/test/hexapdf/test_tokenizer.rb +5 -0
  235. data/test/hexapdf/test_writer.rb +5 -5
  236. data/test/hexapdf/type/test_object_stream.rb +16 -7
  237. data/test/hexapdf/type/test_outline.rb +3 -1
  238. data/test/hexapdf/type/test_outline_item.rb +21 -1
  239. data/test/hexapdf/type/test_page.rb +58 -11
  240. data/test/hexapdf/type/test_xref_stream.rb +6 -1
  241. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 139f1864e4decd05c57468dc3b326a9cc4e749f1d35d4b5dadb3e0549215afd6
4
- data.tar.gz: e7a0d34979abe6738a084dec2334f449ebc1db3eb479dd5f2374a81eeabd83d7
3
+ metadata.gz: 3c74f0e152b612b628321f312413a0eb88e52a41a809f7b37e993acb9e0436b2
4
+ data.tar.gz: 9dfe8cfaaa10527695b70d9019636ed9cc6059367125a45a3dacde7bc1d8c3bb
5
5
  SHA512:
6
- metadata.gz: 339c38737585eafdf447f7516a52ba7ce40b7e2e476336a2404e97a97645d5043b2956835d874296841b8b68d5935c53d97244ac90a2fd621d0471ce85ae8809
7
- data.tar.gz: 4a4c843a32859c639fdf724ca1c6492fa3d387a1c8a92335a2341e82de42a5b9bc30663a3226c1cc0f2ca116dd638071e24b595b323e64fa1e0342d8681199bd
6
+ metadata.gz: f9ee0dbe507a6d31cbf024d2f34e69c15e491bc05a64a0f4039f38bcf6d52192245d6c7d2ac4cb65ae1eb110f8af735afcf13366e15975d96bcc17dda8e2a618
7
+ data.tar.gz: 846ce0611e5f125011aa0535d2de69c15c356f6164f9b09f0a314f9968e34e4addda5396c03d82cd70dffc96eaa0408e1a6dd7a6fc55ce59646be5c3f8b4f9a6
data/CHANGELOG.md CHANGED
@@ -1,4 +1,57 @@
1
- ## 0.30.0 - 2023-01-13
1
+ ## 0.32.0 - 2023-03-08
2
+
3
+ ### Added
4
+
5
+ * [HexaPDF::Document::Layout#method_missing] for more convenient box creation
6
+ * [HexaPDF::Document::Composer#method_missing] for more convenient box drawing
7
+ * [HexaPDF::Document::Layout#inline_box] for easy creation of inline boxes
8
+ * [HexaPDF::Type::OutlineItem#open?] for getting the open state of an outline
9
+ item
10
+
11
+ ### Changed
12
+
13
+ * [HexaPDF::Document::Layout#formatted_text_box] to allow using and/or creating
14
+ inline boxes
15
+
16
+ ### Fixed
17
+
18
+ * Decryption of invalid files having empty strings or streams when using the AES
19
+ algorithm
20
+ * [HexaPDF::Type::Page#flatten_annotations] to work for annotations having
21
+ appearances with degenerate bounding boxes
22
+ * `HexaPDF::Tokenizer#parse_literal_string` to make sure enough bytes are in the
23
+ buffer for correctly reading escape sequences
24
+ * [HexaPDF::Layout::InlineBox] to correctly work for all kinds of wrapped boxes
25
+
26
+
27
+ ## 0.31.0 - 2023-02-22
28
+
29
+ ### Added
30
+
31
+ * [HexaPDF::Layout::PageStyle] for collecting all styling information for pages
32
+ * [HexaPDF::Composer#page_style] for configuring different page styles
33
+
34
+ ### Changed
35
+
36
+ * **Breaking change**: [HexaPDF::Composer] uses page styles underneath
37
+ * **Breaking change**: Configuration options `filter.flate_compression` and
38
+ `filter.flate_memory` are changed to `filter.flate.compression` and
39
+ `filter.flate.memory`
40
+ * **Breaking change**: [HexaPDF::Document#wrap] handles cross-reference and
41
+ object stream specially to avoid problems with invalid PDFs
42
+ * [HexaPDF::Composer::new] to allow skipping the initial page creation
43
+ * CLI command `hexapdf info --check` to process streams to reveal stream errors
44
+ * CLI commands to output the name of created PDF files in verbose mode
45
+
46
+ ### Fixed
47
+
48
+ * Validation of document outline items in case the first or last item got
49
+ deleted
50
+ * `HexaPDF::Type::Page#perform_validation` to set a /MediaBox for invalid pages
51
+ that don't have one
52
+
53
+
54
+ ## 0.30.0 - 2023-02-13
2
55
 
3
56
  ### Added
4
57
 
data/LICENSE CHANGED
@@ -1,5 +1,5 @@
1
1
  HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
2
- Copyright (C) 2014-2022 Thomas Leitner
2
+ Copyright (C) 2014-2023 Thomas Leitner
3
3
 
4
4
  HexaPDF is free software: you can redistribute it and/or modify it
5
5
  under the terms of the GNU Affero General Public License version 3 as
@@ -19,21 +19,20 @@ page_box = page.box
19
19
  frame = HexaPDF::Layout::Frame.new(page_box.left + 20, page_box.bottom + 20,
20
20
  page_box.width - 40, page_box.height - 40)
21
21
 
22
- boxes = []
23
- 5.times do
24
- boxes << doc.layout.image_box(File.join(__dir__, 'machupicchu.jpg'), width: 100,
25
- style: {margin: [10, 30], position: :float})
26
- boxes << HexaPDF::Layout::Box.create(width: 50, height: 50, margin: 20,
27
- position: :float, position_hint: :right,
28
- border: {width: 1, color: [[255, 0, 0]]})
29
- boxes << doc.layout.lorem_ipsum_box(count: 2, position: :flow, align: :justify)
30
- end
31
-
32
22
  polygon = Geom2D::Polygon([200, 350], [400, 350], [400, 450], [200, 450])
33
23
  frame.remove_area(polygon)
34
24
  page.canvas.draw(:geom2d, object: polygon)
35
25
 
36
- columns = doc.layout.box(:column, children: boxes, columns: 2, style: {position: :flow})
26
+ columns = doc.layout.column(columns: 2, style: {position: :flow}) do |column|
27
+ 5.times do
28
+ column.image(File.join(__dir__, 'machupicchu.jpg'), width: 100,
29
+ style: {margin: [10, 30], position: :float})
30
+ column.box(:base, width: 50, height: 50,
31
+ style: {margin: 20, position: :float, position_hint: :right,
32
+ border: {width: 1, color: [[255, 0, 0]]}})
33
+ column.lorem_ipsum(count: 2, position: :flow, align: :justify)
34
+ end
35
+ end
37
36
  result = frame.fit(columns)
38
37
  frame.draw(page.canvas, result)
39
38
 
@@ -13,14 +13,14 @@
13
13
  require 'hexapdf'
14
14
 
15
15
  HexaPDF::Composer.create("list_box.pdf") do |composer|
16
- composer.box(:list, content_indentation: 40, item_spacing: 20) do |list|
17
- list.lorem_ipsum_box
16
+ composer.list(content_indentation: 40, item_spacing: 20) do |list|
17
+ list.lorem_ipsum
18
18
  list.image(File.join(__dir__, 'machupicchu.jpg'), height: 100)
19
- list.box(:list, item_type: :decimal) do |sub_list|
19
+ list.list(item_type: :decimal) do |sub_list|
20
20
  1.upto(10) {|i| sub_list.text("Item #{i}") }
21
21
  end
22
- list.box(:column) do |column|
23
- column.lorem_ipsum_box(count: 3)
22
+ list.column do |column|
23
+ column.lorem_ipsum(count: 3)
24
24
  end
25
25
  end
26
26
  end
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -101,6 +101,17 @@ module HexaPDF
101
101
  def pdf_options(password)
102
102
  hash = {decryption_opts: {password: password}, config: {}}
103
103
  HexaPDF::GlobalConfiguration['filter.predictor.strict'] = command_parser.strict
104
+ HexaPDF::GlobalConfiguration['filter.flate.on_error'] =
105
+ if command_parser.strict
106
+ proc { true }
107
+ else
108
+ proc do |_, error|
109
+ if command_parser.verbosity_info?
110
+ $stderr.puts "Ignoring error in flate encoded stream: #{error}"
111
+ end
112
+ false
113
+ end
114
+ end
104
115
  hash[:config]['parser.try_xref_reconstruction'] = !command_parser.strict
105
116
  hash[:config]['parser.on_correctable_error'] =
106
117
  if command_parser.strict
@@ -120,6 +131,7 @@ module HexaPDF
120
131
  # Writes the document to the given file or does nothing if +out_file+ is +nil+.
121
132
  def write_document(doc, out_file, incremental: false)
122
133
  if out_file
134
+ doc.trailer.update_id
123
135
  doc.validate(auto_correct: true) do |msg, correctable, object|
124
136
  if command_parser.strict && !correctable
125
137
  raise "Validation error for object (#{object.oid},#{object.gen}): #{msg}"
@@ -128,6 +140,9 @@ module HexaPDF
128
140
  "for object (#{object.oid},#{object.gen}): #{msg}"
129
141
  end
130
142
  end
143
+ if command_parser.verbosity_info?
144
+ puts "Creating output document #{out_file}"
145
+ end
131
146
  doc.write(out_file, validate: false, incremental: incremental)
132
147
  end
133
148
  end
@@ -331,7 +346,7 @@ module HexaPDF
331
346
  rotation = ROTATE_MAP[$4]
332
347
  start_nr.step(to: end_nr, by: step) {|n| arr << [n, rotation] }
333
348
  else
334
- raise OptionParser::InvalidArgument, "invalid page range format: #{str}"
349
+ raise OptionParser::InvalidArgument, "invalid page range format: #{str.inspect}"
335
350
  end
336
351
  end
337
352
  end
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -106,6 +106,13 @@ module HexaPDF
106
106
  doc.each(only_loaded: false) do |obj|
107
107
  indirect_object = obj
108
108
  obj.validate(auto_correct: true, &validation_block)
109
+ if obj.data.stream
110
+ begin
111
+ obj.stream
112
+ rescue StandardError
113
+ puts "ERROR: Stream of object (#{obj.oid},#{obj.gen}) invalid: #{$!.message}"
114
+ end
115
+ end
109
116
  end
110
117
  end
111
118
 
@@ -177,7 +184,8 @@ module HexaPDF
177
184
  def pdf_options(password)
178
185
  if @check_file
179
186
  options = {decryption_opts: {password: password}, config: {}}
180
- HexaPDF::GlobalConfiguration['filter.predictor.strict'] = false
187
+ HexaPDF::GlobalConfiguration['filter.predictor.strict'] = true
188
+ HexaPDF::GlobalConfiguration['filter.flate.on_error'] = proc { true }
181
189
  options[:config]['parser.try_xref_reconstruction'] = true
182
190
  options[:config]['parser.on_correctable_error'] = lambda do |_, msg, pos|
183
191
  puts "WARNING: Parse error at position #{pos}: #{msg}"
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -166,8 +166,8 @@ module HexaPDF
166
166
  when 'p', 'pages'
167
167
  begin
168
168
  pages = parse_pages_specification(data.shift || '1-e', @doc.pages.count)
169
- rescue StandardError
170
- $stderr.puts("Error: Invalid page range argument")
169
+ rescue StandardError => e
170
+ $stderr.puts("Error: #{e}")
171
171
  next
172
172
  end
173
173
  page_list = @doc.pages.to_a
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
data/lib/hexapdf/cli.rb CHANGED
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -106,6 +106,14 @@ module HexaPDF
106
106
 
107
107
  # Creates a new Composer object and optionally yields it to the given block.
108
108
  #
109
+ # skip_page_creation::
110
+ # If this argument is +true+ (the default), the arguments +page_size+, +page_orientation+
111
+ # and +margin+ are used to create a page style with the name :default and an initial page is
112
+ # created as well.
113
+ #
114
+ # Otherwise, i.e. when this argument is +false+, no initial page or default page style is
115
+ # created. This has to be done manually using the #page_style and #new_page methods.
116
+ #
109
117
  # page_size::
110
118
  # Can be any valid predefined page size (see Type::Page::PAPER_SIZE) or an array [llx, lly,
111
119
  # urx, ury] specifying a custom page size.
@@ -120,36 +128,53 @@ module HexaPDF
120
128
  # Example:
121
129
  #
122
130
  # composer = HexaPDF::Composer.new # uses the default values
131
+ #
123
132
  # HexaPDF::Composer.new(page_size: :Letter, margin: 72) do |composer|
124
133
  # #...
125
134
  # end
126
- def initialize(page_size: :A4, page_orientation: :portrait, margin: 36) #:yields: composer
135
+ #
136
+ # HexaPDF::Composer.new(skip_page_creation: true) do |composer|
137
+ # page_template = lambda {|canvas, style| style.create_frame(canvas.context, 36) }
138
+ # page_style(:default, template: page_template)
139
+ # new_page
140
+ # # ...
141
+ # end
142
+ def initialize(skip_page_creation: false, page_size: :A4, page_orientation: :portrait,
143
+ margin: 36) #:yields: composer
127
144
  @document = HexaPDF::Document.new
128
- @page_size = page_size
129
- @page_orientation = page_orientation
130
- @margin = Layout::Style::Quad.new(margin)
131
-
132
- new_page
145
+ @page_styles = {}
146
+ @page_style = :default
147
+ unless skip_page_creation
148
+ page_style(:default, page_size: page_size, orientation: page_orientation) do |canvas, style|
149
+ style.frame = style.create_frame(canvas.context, margin)
150
+ end
151
+ new_page
152
+ end
133
153
  yield(self) if block_given?
134
154
  end
135
155
 
136
156
  # Creates a new page, making it the current one.
137
157
  #
138
- # If any of +page_size+, +page_orientation+ or +margin+ are set, they will be used instead of
139
- # the default values and will become the default values.
158
+ # The page style to use for the new page can be set via the +style+ argument. If not provided,
159
+ # the currently set page style is used.
160
+ #
161
+ # The used page style determines the page style that should be used for the following new pages.
162
+ # If this information is not provided, the used page style is used again.
140
163
  #
141
164
  # Examples:
142
165
  #
143
- # composer.new_page # uses the default values
144
- # composer.new_page(page_size: :A5, margin: [72, 36])
145
- def new_page(page_size: nil, page_orientation: nil, margin: nil)
146
- @page_size = page_size if page_size
147
- @page_orientation = page_orientation if page_orientation
148
- @margin = Layout::Style::Quad.new(margin) if margin
149
-
150
- @page = @document.pages.add(@page_size, orientation: @page_orientation)
166
+ # composer.page_style(:cover, page_size: :A4).next_style = :content
167
+ # composer.page_style(:content, page_size: :A4)
168
+ # composer.new_page(:cover) # uses the :cover style, set next style to :content
169
+ # composer.new_page # uses the :content style, next style again :content
170
+ def new_page(style = @page_style)
171
+ page_style = @page_styles.fetch(style) do |key|
172
+ raise ArgumentError, "Page style #{key} has not been defined"
173
+ end
174
+ @page = @document.pages.add(page_style.create_page(@document))
151
175
  @canvas = @page.canvas
152
- create_frame
176
+ @frame = page_style.frame
177
+ @page_style = page_style.next_style || style
153
178
  end
154
179
 
155
180
  # The x-position of the cursor inside the current frame.
@@ -190,6 +215,40 @@ module HexaPDF
190
215
  @document.layout.style(name, base: base, **properties)
191
216
  end
192
217
 
218
+ # :call-seq:
219
+ # composer.page_style(name) -> page_style
220
+ # composer.page_style(name, **attributes, &template_block) -> page_style
221
+ #
222
+ # Creates and/or returns the page style +name+.
223
+ #
224
+ # If no attributes are given, the page style +name+ is returned. In case it does not exist,
225
+ # +nil+ is returned.
226
+ #
227
+ # If one or more page style attributes are given, a new HexaPDF::Layout::PageStyle object with
228
+ # those attribute values is created, stored under +name+ and returned. If a block is provided,
229
+ # it is used to define the page template.
230
+ #
231
+ # Example:
232
+ #
233
+ # composer.page_style(:default)
234
+ # composer.page_style(:cover, page_size: :A4) do |canvas, style|
235
+ # page_box = canvas.context.box
236
+ # canvas.fill_color("fd0") do
237
+ # canvas.rectangle(0, 0, page_box.width, page_box.height).
238
+ # fill
239
+ # end
240
+ # style.frame = style.create_frame(canvas.context, 36)
241
+ # end
242
+ #
243
+ # See: HexaPDF::Layout::PageStyle
244
+ def page_style(name, **attributes, &block)
245
+ if attributes.empty?
246
+ @page_styles[name]
247
+ else
248
+ @page_styles[name] = HexaPDF::Layout::PageStyle.new(**attributes, &block)
249
+ end
250
+ end
251
+
193
252
  # Draws the given text at the current position into the current frame.
194
253
  #
195
254
  # The text will be positioned at the current position if possible. Otherwise the next best
@@ -270,6 +329,26 @@ module HexaPDF
270
329
  draw_box(@document.layout.box(name, width: width, height: height, style: style, **box_options, &block))
271
330
  end
272
331
 
332
+ # Draws any custom box that can be created using HexaPDF::Document::Layout.
333
+ #
334
+ # Examples:
335
+ #
336
+ # #>pdf-composer
337
+ # composer.lorem_ipsum
338
+ # composer.column {|column| column.lorem_ipsum }
339
+ def method_missing(name, *args, **kwargs, &block)
340
+ if @document.layout.box_creation_method?(name)
341
+ draw_box(@document.layout.send(name, *args, **kwargs, &block))
342
+ else
343
+ super
344
+ end
345
+ end
346
+
347
+ # :nodoc:
348
+ def respond_to_missing?(name, _private)
349
+ @document.layout.box_creation_method?(name) || super
350
+ end
351
+
273
352
  # Draws the given HexaPDF::Layout::Box.
274
353
  #
275
354
  # The box is drawn into the current frame if possible. If it doesn't fit, the box is split. If
@@ -325,17 +404,6 @@ module HexaPDF
325
404
  stamp
326
405
  end
327
406
 
328
- private
329
-
330
- # Creates the frame into which boxes are layed out when a new page is created.
331
- def create_frame
332
- media_box = @page.box
333
- @frame = Layout::Frame.new(media_box.left + @margin.left,
334
- media_box.bottom + @margin.bottom,
335
- media_box.width - @margin.left - @margin.right,
336
- media_box.height - @margin.bottom - @margin.top)
337
- end
338
-
339
407
  end
340
408
 
341
409
  end
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -350,6 +350,9 @@ module HexaPDF
350
350
  # The media box that is used for new pages that don't define a media box. Default value is
351
351
  # A4. See HexaPDF::Type::Page::PAPER_SIZE for a list of predefined paper sizes.
352
352
  #
353
+ # This configuration option (together with 'page.default_media_orientation') is also used when
354
+ # validating pages and a page without a media box is found.
355
+ #
353
356
  # The value can either be a rectangle defining the paper size or a Symbol referencing one of
354
357
  # the predefined paper sizes.
355
358
  #
@@ -511,11 +514,20 @@ module HexaPDF
511
514
  #
512
515
  # See PDF1.7 s8.6
513
516
  #
514
- # filter.flate_compression::
517
+ # filter.flate.compression::
515
518
  # Specifies the compression level that should be used with the FlateDecode filter. The level
516
519
  # can range from 0 (no compression), 1 (best speed) to 9 (best compression, default).
517
520
  #
518
- # filter.flate_memory::
521
+ # filter.flate.on_error::
522
+ # Callback hook when a potentially recoverable Zlib error occurs in the FlateDecode filter.
523
+ #
524
+ # The value needs to be an object that responds to \#call(stream, error) where stream is the
525
+ # Zlib stream object and error is the thrown error. The method needs to return +true+ if an
526
+ # error should be raised.
527
+ #
528
+ # The default implementation prevents errors from being raised.
529
+ #
530
+ # filter.flate.memory::
519
531
  # Specifies the memory level that should be used with the FlateDecode filter. The level can
520
532
  # range from 1 (minimum memory usage; slow, reduces compression) to 9 (maximum memory usage).
521
533
  #
@@ -543,8 +555,9 @@ module HexaPDF
543
555
  # This mapping is used to provide automatic wrapping of objects in the HexaPDF::Document#wrap
544
556
  # method.
545
557
  GlobalConfiguration =
546
- Configuration.new('filter.flate_compression' => 9,
547
- 'filter.flate_memory' => 6,
558
+ Configuration.new('filter.flate.compression' => 9,
559
+ 'filter.flate.on_error' => proc { false },
560
+ 'filter.flate.memory' => 6,
548
561
  'filter.predictor.strict' => false,
549
562
  'color_space.map' => {
550
563
  DeviceRGB: 'HexaPDF::Content::ColorSpace::DeviceRGB',
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2022 Thomas Leitner
7
+ # Copyright (C) 2014-2023 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as