hexapdf 0.23.0 → 0.24.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 (243) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -0
  3. data/LICENSE +1 -1
  4. data/Rakefile +1 -1
  5. data/examples/016-frame_automatic_box_placement.rb +7 -2
  6. data/examples/017-frame_text_flow.rb +10 -18
  7. data/examples/020-column_box.rb +40 -0
  8. data/examples/021-list_box.rb +26 -0
  9. data/lib/hexapdf/cli/batch.rb +1 -1
  10. data/lib/hexapdf/cli/command.rb +1 -1
  11. data/lib/hexapdf/cli/files.rb +1 -1
  12. data/lib/hexapdf/cli/fonts.rb +1 -1
  13. data/lib/hexapdf/cli/form.rb +2 -2
  14. data/lib/hexapdf/cli/image2pdf.rb +1 -1
  15. data/lib/hexapdf/cli/images.rb +1 -1
  16. data/lib/hexapdf/cli/info.rb +2 -2
  17. data/lib/hexapdf/cli/inspect.rb +2 -2
  18. data/lib/hexapdf/cli/merge.rb +1 -1
  19. data/lib/hexapdf/cli/modify.rb +1 -1
  20. data/lib/hexapdf/cli/optimize.rb +1 -1
  21. data/lib/hexapdf/cli/split.rb +1 -1
  22. data/lib/hexapdf/cli/watermark.rb +1 -1
  23. data/lib/hexapdf/cli.rb +1 -1
  24. data/lib/hexapdf/composer.rb +45 -126
  25. data/lib/hexapdf/configuration.rb +17 -1
  26. data/lib/hexapdf/content/canvas.rb +1 -1
  27. data/lib/hexapdf/content/color_space.rb +1 -1
  28. data/lib/hexapdf/content/graphic_object/arc.rb +1 -1
  29. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
  30. data/lib/hexapdf/content/graphic_object/geom2d.rb +2 -1
  31. data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
  32. data/lib/hexapdf/content/graphic_object.rb +1 -1
  33. data/lib/hexapdf/content/graphics_state.rb +1 -1
  34. data/lib/hexapdf/content/operator.rb +1 -1
  35. data/lib/hexapdf/content/parser.rb +1 -1
  36. data/lib/hexapdf/content/processor.rb +1 -1
  37. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  38. data/lib/hexapdf/content.rb +1 -1
  39. data/lib/hexapdf/data_dir.rb +1 -1
  40. data/lib/hexapdf/dictionary.rb +1 -1
  41. data/lib/hexapdf/dictionary_fields.rb +1 -1
  42. data/lib/hexapdf/document/files.rb +1 -1
  43. data/lib/hexapdf/document/fonts.rb +1 -1
  44. data/lib/hexapdf/document/images.rb +1 -1
  45. data/lib/hexapdf/document/layout.rb +397 -0
  46. data/lib/hexapdf/document/pages.rb +17 -1
  47. data/lib/hexapdf/document/signatures.rb +5 -4
  48. data/lib/hexapdf/document.rb +8 -1
  49. data/lib/hexapdf/encryption/aes.rb +1 -1
  50. data/lib/hexapdf/encryption/arc4.rb +1 -1
  51. data/lib/hexapdf/encryption/fast_aes.rb +1 -1
  52. data/lib/hexapdf/encryption/fast_arc4.rb +30 -21
  53. data/lib/hexapdf/encryption/identity.rb +1 -1
  54. data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
  55. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  56. data/lib/hexapdf/encryption/security_handler.rb +1 -1
  57. data/lib/hexapdf/encryption/standard_security_handler.rb +1 -1
  58. data/lib/hexapdf/encryption.rb +1 -1
  59. data/lib/hexapdf/error.rb +1 -1
  60. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  61. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  62. data/lib/hexapdf/filter/crypt.rb +1 -1
  63. data/lib/hexapdf/filter/encryption.rb +1 -1
  64. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  65. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  66. data/lib/hexapdf/filter/pass_through.rb +1 -1
  67. data/lib/hexapdf/filter/predictor.rb +1 -1
  68. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  69. data/lib/hexapdf/filter.rb +1 -1
  70. data/lib/hexapdf/font/cmap/parser.rb +1 -1
  71. data/lib/hexapdf/font/cmap/writer.rb +1 -1
  72. data/lib/hexapdf/font/cmap.rb +1 -1
  73. data/lib/hexapdf/font/encoding/base.rb +1 -1
  74. data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
  75. data/lib/hexapdf/font/encoding/glyph_list.rb +2 -2
  76. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  77. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
  78. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  79. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  80. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +1 -1
  81. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  82. data/lib/hexapdf/font/encoding.rb +1 -1
  83. data/lib/hexapdf/font/invalid_glyph.rb +1 -1
  84. data/lib/hexapdf/font/true_type/builder.rb +1 -1
  85. data/lib/hexapdf/font/true_type/font.rb +1 -1
  86. data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
  87. data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
  88. data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
  89. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
  90. data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
  91. data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
  92. data/lib/hexapdf/font/true_type/table/head.rb +1 -1
  93. data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
  94. data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
  95. data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
  96. data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
  97. data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
  98. data/lib/hexapdf/font/true_type/table/name.rb +1 -1
  99. data/lib/hexapdf/font/true_type/table/os2.rb +1 -1
  100. data/lib/hexapdf/font/true_type/table/post.rb +1 -1
  101. data/lib/hexapdf/font/true_type/table.rb +1 -1
  102. data/lib/hexapdf/font/true_type.rb +1 -1
  103. data/lib/hexapdf/font/true_type_wrapper.rb +1 -1
  104. data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
  105. data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
  106. data/lib/hexapdf/font/type1/font.rb +1 -1
  107. data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
  108. data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
  109. data/lib/hexapdf/font/type1.rb +1 -1
  110. data/lib/hexapdf/font/type1_wrapper.rb +1 -1
  111. data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
  112. data/lib/hexapdf/font_loader/from_file.rb +1 -1
  113. data/lib/hexapdf/font_loader/standard14.rb +1 -1
  114. data/lib/hexapdf/font_loader.rb +1 -1
  115. data/lib/hexapdf/image_loader/jpeg.rb +1 -1
  116. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  117. data/lib/hexapdf/image_loader/png.rb +1 -1
  118. data/lib/hexapdf/image_loader.rb +1 -1
  119. data/lib/hexapdf/importer.rb +1 -1
  120. data/lib/hexapdf/layout/box.rb +121 -22
  121. data/lib/hexapdf/layout/box_fitter.rb +136 -0
  122. data/lib/hexapdf/layout/column_box.rb +247 -0
  123. data/lib/hexapdf/layout/frame.rb +155 -139
  124. data/lib/hexapdf/layout/image_box.rb +19 -4
  125. data/lib/hexapdf/layout/inline_box.rb +1 -1
  126. data/lib/hexapdf/layout/line.rb +1 -1
  127. data/lib/hexapdf/layout/list_box.rb +355 -0
  128. data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
  129. data/lib/hexapdf/layout/style.rb +5 -1
  130. data/lib/hexapdf/layout/text_box.rb +20 -9
  131. data/lib/hexapdf/layout/text_fragment.rb +3 -2
  132. data/lib/hexapdf/layout/text_layouter.rb +17 -2
  133. data/lib/hexapdf/layout/text_shaper.rb +1 -1
  134. data/lib/hexapdf/layout/width_from_polygon.rb +12 -7
  135. data/lib/hexapdf/layout.rb +4 -1
  136. data/lib/hexapdf/name_tree_node.rb +1 -1
  137. data/lib/hexapdf/number_tree_node.rb +1 -1
  138. data/lib/hexapdf/object.rb +1 -1
  139. data/lib/hexapdf/parser.rb +1 -8
  140. data/lib/hexapdf/pdf_array.rb +1 -1
  141. data/lib/hexapdf/rectangle.rb +1 -1
  142. data/lib/hexapdf/reference.rb +1 -1
  143. data/lib/hexapdf/revision.rb +1 -1
  144. data/lib/hexapdf/revisions.rb +1 -1
  145. data/lib/hexapdf/serializer.rb +1 -1
  146. data/lib/hexapdf/stream.rb +1 -1
  147. data/lib/hexapdf/task/dereference.rb +1 -1
  148. data/lib/hexapdf/task/optimize.rb +1 -1
  149. data/lib/hexapdf/task.rb +1 -1
  150. data/lib/hexapdf/tokenizer.rb +1 -1
  151. data/lib/hexapdf/type/acro_form/appearance_generator.rb +1 -1
  152. data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
  153. data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
  154. data/lib/hexapdf/type/acro_form/field.rb +1 -1
  155. data/lib/hexapdf/type/acro_form/form.rb +1 -1
  156. data/lib/hexapdf/type/acro_form/signature_field.rb +1 -1
  157. data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
  158. data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
  159. data/lib/hexapdf/type/acro_form.rb +1 -1
  160. data/lib/hexapdf/type/action.rb +1 -1
  161. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  162. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  163. data/lib/hexapdf/type/actions/launch.rb +1 -1
  164. data/lib/hexapdf/type/actions/uri.rb +1 -1
  165. data/lib/hexapdf/type/actions.rb +1 -1
  166. data/lib/hexapdf/type/annotation.rb +1 -1
  167. data/lib/hexapdf/type/annotations/link.rb +1 -1
  168. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  169. data/lib/hexapdf/type/annotations/text.rb +1 -1
  170. data/lib/hexapdf/type/annotations/widget.rb +1 -1
  171. data/lib/hexapdf/type/annotations.rb +1 -1
  172. data/lib/hexapdf/type/catalog.rb +1 -1
  173. data/lib/hexapdf/type/cid_font.rb +1 -1
  174. data/lib/hexapdf/type/embedded_file.rb +1 -1
  175. data/lib/hexapdf/type/file_specification.rb +1 -1
  176. data/lib/hexapdf/type/font.rb +1 -1
  177. data/lib/hexapdf/type/font_descriptor.rb +1 -1
  178. data/lib/hexapdf/type/font_simple.rb +1 -1
  179. data/lib/hexapdf/type/font_true_type.rb +1 -1
  180. data/lib/hexapdf/type/font_type0.rb +1 -1
  181. data/lib/hexapdf/type/font_type1.rb +1 -1
  182. data/lib/hexapdf/type/font_type3.rb +1 -1
  183. data/lib/hexapdf/type/form.rb +1 -1
  184. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  185. data/lib/hexapdf/type/icon_fit.rb +1 -1
  186. data/lib/hexapdf/type/image.rb +1 -1
  187. data/lib/hexapdf/type/info.rb +1 -1
  188. data/lib/hexapdf/type/names.rb +1 -1
  189. data/lib/hexapdf/type/object_stream.rb +1 -1
  190. data/lib/hexapdf/type/page.rb +1 -1
  191. data/lib/hexapdf/type/page_tree_node.rb +19 -2
  192. data/lib/hexapdf/type/resources.rb +1 -1
  193. data/lib/hexapdf/type/signature/adbe_pkcs7_detached.rb +1 -1
  194. data/lib/hexapdf/type/signature/adbe_x509_rsa_sha1.rb +1 -1
  195. data/lib/hexapdf/type/signature/handler.rb +1 -1
  196. data/lib/hexapdf/type/signature/verification_result.rb +1 -1
  197. data/lib/hexapdf/type/signature.rb +1 -1
  198. data/lib/hexapdf/type/trailer.rb +2 -2
  199. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  200. data/lib/hexapdf/type/xref_stream.rb +1 -1
  201. data/lib/hexapdf/type.rb +1 -1
  202. data/lib/hexapdf/utils/bit_field.rb +1 -1
  203. data/lib/hexapdf/utils/bit_stream.rb +1 -1
  204. data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
  205. data/lib/hexapdf/utils/lru_cache.rb +1 -1
  206. data/lib/hexapdf/utils/math_helpers.rb +1 -1
  207. data/lib/hexapdf/utils/object_hash.rb +1 -1
  208. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  209. data/lib/hexapdf/utils/sorted_tree_node.rb +1 -1
  210. data/lib/hexapdf/version.rb +2 -2
  211. data/lib/hexapdf/writer.rb +9 -7
  212. data/lib/hexapdf/xref_section.rb +1 -1
  213. data/lib/hexapdf.rb +1 -1
  214. data/test/hexapdf/content/graphic_object/test_geom2d.rb +1 -1
  215. data/test/hexapdf/document/test_destinations.rb +1 -1
  216. data/test/hexapdf/document/test_images.rb +1 -1
  217. data/test/hexapdf/document/test_layout.rb +264 -0
  218. data/test/hexapdf/document/test_pages.rb +9 -0
  219. data/test/hexapdf/document/test_signatures.rb +10 -3
  220. data/test/hexapdf/encryption/test_security_handler.rb +1 -1
  221. data/test/hexapdf/font/encoding/test_glyph_list.rb +4 -0
  222. data/test/hexapdf/layout/test_box.rb +53 -3
  223. data/test/hexapdf/layout/test_box_fitter.rb +62 -0
  224. data/test/hexapdf/layout/test_column_box.rb +159 -0
  225. data/test/hexapdf/layout/test_frame.rb +99 -38
  226. data/test/hexapdf/layout/test_image_box.rb +1 -1
  227. data/test/hexapdf/layout/test_list_box.rb +249 -0
  228. data/test/hexapdf/layout/test_text_box.rb +17 -2
  229. data/test/hexapdf/layout/test_text_fragment.rb +1 -1
  230. data/test/hexapdf/layout/test_text_layouter.rb +42 -17
  231. data/test/hexapdf/layout/test_width_from_polygon.rb +13 -0
  232. data/test/hexapdf/test_composer.rb +11 -0
  233. data/test/hexapdf/test_dictionary_fields.rb +9 -9
  234. data/test/hexapdf/test_document.rb +4 -4
  235. data/test/hexapdf/test_filter.rb +1 -1
  236. data/test/hexapdf/test_parser.rb +0 -2
  237. data/test/hexapdf/test_revisions.rb +2 -2
  238. data/test/hexapdf/test_serializer.rb +1 -5
  239. data/test/hexapdf/test_writer.rb +58 -3
  240. data/test/hexapdf/type/test_page_tree_node.rb +21 -1
  241. data/test/hexapdf/type/test_trailer.rb +3 -3
  242. data/test/test_helper.rb +5 -1
  243. metadata +28 -3
@@ -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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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
@@ -69,7 +69,7 @@ module HexaPDF
69
69
 
70
70
  # Returns the document's Catalog (see Type::Catalog), creating it if needed.
71
71
  def catalog
72
- self[:Root] ||= document.add({Type: :Catalog})
72
+ self[:Root] ||= document.add({Type: :Catalog}, type: :Catalog)
73
73
  end
74
74
 
75
75
  # Returns the document's information dictionary (see Type::Info), creating it if needed.
@@ -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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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/type.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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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
@@ -37,6 +37,6 @@
37
37
  module HexaPDF
38
38
 
39
39
  # The version of HexaPDF.
40
- VERSION = '0.23.0'
40
+ VERSION = '0.24.0'
41
41
 
42
42
  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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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
@@ -72,7 +72,8 @@ module HexaPDF
72
72
  @use_xref_streams = false
73
73
  end
74
74
 
75
- # Writes the document to the IO object and returns the last XRefSection written.
75
+ # Writes the document to the IO object and returns the file position of the start of the last
76
+ # cross-reference section and the last XRefSection written.
76
77
  def write
77
78
  move_modified_objects_into_current_revision
78
79
  write_file_header
@@ -83,11 +84,12 @@ module HexaPDF
83
84
  pos, xref_section = write_revision(rev, pos)
84
85
  end
85
86
 
86
- xref_section
87
+ [pos, xref_section]
87
88
  end
88
89
 
89
90
  # Writes the complete source document unmodified to the IO and then one revision containing all
90
- # changes. Returns the XRefSection of that one revision.
91
+ # changes. Returns the file position of the start of the cross-reference section and the
92
+ # XRefSection object of that one revision.
91
93
  #
92
94
  # For this method to work the document must have been created from an existing file.
93
95
  def write_incremental
@@ -104,15 +106,15 @@ module HexaPDF
104
106
  @io << "\n"
105
107
 
106
108
  @rev_size = @document.revisions.current.next_free_oid
107
- @use_xref_streams = parser.contains_xref_streams?
109
+ @use_xref_streams = @document.revisions.any? {|rev| rev.trailer[:Type] == :XRef }
108
110
 
109
111
  revision = Revision.new(@document.revisions.current.trailer)
112
+ @document.trailer.info[:Producer] = "HexaPDF version #{HexaPDF::VERSION}"
110
113
  @document.revisions.each do |rev|
111
114
  rev.each_modified_object {|obj| revision.send(:add_without_check, obj) }
112
115
  end
113
- _pos, xref_section = write_revision(revision, parser.startxref_offset)
114
116
 
115
- xref_section
117
+ write_revision(revision, parser.startxref_offset)
116
118
  end
117
119
 
118
120
  private
@@ -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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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.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-2021 Thomas Leitner
7
+ # Copyright (C) 2014-2022 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
@@ -57,7 +57,7 @@ describe HexaPDF::Content::GraphicObject::Geom2D do
57
57
  @obj.draw(@canvas)
58
58
  assert_operators(@canvas.contents,
59
59
  [[:move_to, [5, 6]], [:line_to, [10, 11]], [:line_to, [7, 9]],
60
- [:stroke_path]])
60
+ [:close_subpath], [:stroke_path]])
61
61
  end
62
62
 
63
63
  it "draws a Geom2D::PolygonSet onto the canvas" do
@@ -215,7 +215,7 @@ describe HexaPDF::Document::Destinations do
215
215
 
216
216
  describe "create_fit_page" do
217
217
  it "creates the destination" do
218
- dest = @doc.destinations.create_fit_page( @page)
218
+ dest = @doc.destinations.create_fit_page(@page)
219
219
  assert_equal([@page, :Fit], dest)
220
220
  end
221
221
 
@@ -31,7 +31,7 @@ describe HexaPDF::Document::Images do
31
31
  it "adds an image using an IO" do
32
32
  File.open(__FILE__, 'rb') do |file|
33
33
  image = @doc.images.add(file)
34
- assert_equal(File.read(__FILE__), image.stream)
34
+ assert_equal(File.binread(__FILE__), image.stream)
35
35
  assert_equal(File.absolute_path(__FILE__), image.source_path)
36
36
  end
37
37
  end
@@ -0,0 +1,264 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+
6
+ describe HexaPDF::Document::Layout::ChildrenCollector do
7
+ before do
8
+ @doc = HexaPDF::Document.new
9
+ @collector = HexaPDF::Document::Layout::ChildrenCollector.new(@doc.layout)
10
+ end
11
+
12
+ it "provides a convenient ::collect method which just returns the collected children" do
13
+ children = HexaPDF::Document::Layout::ChildrenCollector.collect(@doc.layout) do |collector|
14
+ collector.lorem_ipsum_box
15
+ collector.lorem_ipsum_box
16
+ end
17
+ assert_equal(2, children.size)
18
+ assert_kind_of(HexaPDF::Layout::TextBox, children[0])
19
+ assert_kind_of(HexaPDF::Layout::TextBox, children[1])
20
+ end
21
+
22
+ it "allows appending existing boxes" do
23
+ box = @doc.layout.lorem_ipsum_box
24
+ @collector << box
25
+ assert_equal([box], @collector.children)
26
+ end
27
+
28
+ it "allows appending an array of boxes created through another children collector" do
29
+ @collector.multiple do |collector|
30
+ collector.lorem_ipsum_box
31
+ collector.lorem_ipsum_box
32
+ end
33
+ assert_equal(1, @collector.children.size)
34
+ assert_equal(2, @collector.children[0].size)
35
+ end
36
+
37
+ it "allows appending boxes through method names of the Layout class" do
38
+ @collector.lorem_ipsum_box
39
+ assert_equal(1, @collector.children.size)
40
+ assert_kind_of(HexaPDF::Layout::TextBox, @collector.children[0])
41
+ end
42
+
43
+ it "allows appending boxes through method names without the _box suffix of the Layout class" do
44
+ @collector.lorem_ipsum
45
+ assert_equal(1, @collector.children.size)
46
+ assert_kind_of(HexaPDF::Layout::TextBox, @collector.children[0])
47
+ end
48
+
49
+ it "allows appending boxes through their registered names" do
50
+ @collector.column
51
+ assert_equal(1, @collector.children.size)
52
+ assert_kind_of(HexaPDF::Layout::ColumnBox, @collector.children[0])
53
+ end
54
+
55
+ it "can be asked which methods it supports" do
56
+ assert(@collector.respond_to?(:text_box))
57
+ assert(@collector.respond_to?(:text))
58
+ assert(@collector.respond_to?(:column))
59
+ refute(@collector.respond_to?(:unknown))
60
+ end
61
+
62
+ it "raises an error on an unknown method name" do
63
+ assert_raises(NameError) { @collector.unknown_box }
64
+ end
65
+ end
66
+
67
+ describe HexaPDF::Document::Layout do
68
+ before do
69
+ @doc = HexaPDF::Document.new
70
+ @layout = @doc.layout
71
+ end
72
+
73
+ describe "style" do
74
+ it "creates a new style if it does not exist based on the base argument" do
75
+ @layout.style(:base, font_size: 20)
76
+ assert_equal(20, @layout.style(:newstyle, subscript: true).font_size)
77
+ refute(@layout.style(:base).subscript)
78
+ assert_equal(10, @layout.style(:another_new, base: nil).font_size)
79
+ assert(@layout.style(:yet_another_new, base: :newstyle).subscript)
80
+ end
81
+
82
+ it "returns the named style" do
83
+ assert_kind_of(HexaPDF::Layout::Style, @layout.style(:base))
84
+ end
85
+
86
+ it "updates the style with the given properties" do
87
+ assert_equal(20, @layout.style(:base, font_size: 20).font_size)
88
+ end
89
+ end
90
+
91
+ describe "box" do
92
+ it "creates the request box" do
93
+ box = @layout.box(:column, columns: 3, gaps: 20, width: 15, height: 30, style: {font_size: 10})
94
+ assert_equal(15, box.width)
95
+ assert_equal(30, box.height)
96
+ assert_equal([-1, -1, -1], box.columns)
97
+ assert_equal([20], box.gaps)
98
+ assert_equal(10, box.style.font_size)
99
+ end
100
+
101
+ it "allows specifying the box's children via a provided block" do
102
+ box = @layout.box(:column) do |column|
103
+ column.lorem_ipsum
104
+ column.lorem_ipsum
105
+ end
106
+ assert_equal(2, box.children.size)
107
+ end
108
+
109
+ it "fails if the name is not registered" do
110
+ assert_raises(HexaPDF::Error) { @layout.box(:unknown) }
111
+ end
112
+ end
113
+
114
+ describe "text_box" do
115
+ it "creates a text box" do
116
+ box = @layout.text_box("Test", width: 10, height: 15)
117
+ assert_equal(10, box.width)
118
+ assert_equal(15, box.height)
119
+ assert_same(@doc.fonts.add("Times"), box.style.font)
120
+ items = box.instance_variable_get(:@items)
121
+ assert_equal(1, items.length)
122
+ assert_same(box.style, items.first.style)
123
+ end
124
+
125
+ it "allows setting of a custom style" do
126
+ style = HexaPDF::Layout::Style.new(font_size: 20, font: ['Times', {variant: :bold}])
127
+ box = @layout.text_box("Test", style: style)
128
+ assert_same(box.style, style)
129
+ assert_same(@doc.fonts.add("Times", variant: :bold), box.style.font)
130
+ assert_equal(20, box.style.font_size)
131
+
132
+ box = @layout.text_box("Test", style: {font_size: 20})
133
+ assert_equal(20, box.style.font_size)
134
+
135
+ @layout.style(:named, font_size: 20)
136
+ box = @layout.text_box("Test", style: :named)
137
+ assert_equal(20, box.style.font_size)
138
+ end
139
+
140
+ it "updates the used style with the provided options" do
141
+ box = @layout.text_box("Test", style: {subscript: true}, font_size: 20)
142
+ assert_equal(20, box.style.font_size)
143
+ end
144
+
145
+ it "allows using a box style different from the text style" do
146
+ style = HexaPDF::Layout::Style.new(font_size: 20)
147
+ box = @layout.text_box("Test", box_style: style)
148
+ refute_same(box.instance_variable_get(:@items).first.style, style)
149
+ assert_same(box.style, style)
150
+
151
+ @layout.style(:named, font_size: 20)
152
+ box = @layout.text_box("Test", box_style: :named)
153
+ assert_equal(20, box.style.font_size)
154
+ end
155
+ end
156
+
157
+ describe "formatted_text" do
158
+ it "creates a text box with the given text" do
159
+ box = @layout.formatted_text_box(["Test"], width: 10, height: 15)
160
+ assert_equal(10, box.width)
161
+ assert_equal(15, box.height)
162
+ assert_equal(1, box.instance_variable_get(:@items).length)
163
+ end
164
+
165
+ it "allows using a hash with :text key instead of a simple string" do
166
+ box = @layout.formatted_text_box([{text: "Test"}])
167
+ items = box.instance_variable_get(:@items)
168
+ assert_equal(4, items[0].items.length)
169
+ end
170
+
171
+ it "uses an empty string if the :text key for a hash is not specified" do
172
+ box = @layout.formatted_text_box([{font_size: "Test"}])
173
+ items = box.instance_variable_get(:@items)
174
+ assert_equal(0, items[0].items.length)
175
+ end
176
+
177
+ it "allows setting a custom base style for all parts" do
178
+ box = @layout.formatted_text_box(["Test", "other"], font_size: 20)
179
+ items = box.instance_variable_get(:@items)
180
+ assert_equal(20, box.style.font_size)
181
+ assert_equal(20, items[0].style.font_size)
182
+ assert_equal(20, items[1].style.font_size)
183
+ end
184
+
185
+ it "allows using custom style properties for a single part" do
186
+ box = @layout.formatted_text_box([{text: "Test", font_size: 20}, "test"], align: :center)
187
+ items = box.instance_variable_get(:@items)
188
+ assert_equal(10, box.style.font_size)
189
+
190
+ assert_equal(20, items[0].style.font_size)
191
+ assert_equal(:center, items[0].style.align)
192
+
193
+ assert_equal(10, items[1].style.font_size)
194
+ assert_equal(:center, items[1].style.align)
195
+ end
196
+
197
+ it "allows using a custom style as basis for a single part" do
198
+ box = @layout.formatted_text_box([{text: "Test", style: {font_size: 20}, subscript: true},
199
+ "test"], align: :center)
200
+ items = box.instance_variable_get(:@items)
201
+ assert_equal(10, box.style.font_size)
202
+
203
+ assert_equal(20, items[0].style.font_size)
204
+ assert_equal(:left, items[0].style.align)
205
+ assert(items[0].style.subscript)
206
+
207
+ assert_equal(10, items[1].style.font_size)
208
+ assert_equal(:center, items[1].style.align)
209
+ refute(items[1].style.subscript)
210
+ end
211
+
212
+ it "allows specifying a link to an URL via the :link key" do
213
+ box = @layout.formatted_text_box([{text: "Test", link: "URI"}, {link: "URI"}, "test"])
214
+ items = box.instance_variable_get(:@items)
215
+ assert_equal(3, items.length)
216
+ assert_equal(4, items[0].items.length, "text should be Test")
217
+ assert_equal(3, items[1].items.length, "text should be URI")
218
+ assert_equal([:link, {uri: 'URI'}], items[0].style.overlays.instance_variable_get(:@layers)[0])
219
+ refute(items[2].style.overlays?)
220
+ end
221
+ end
222
+
223
+ describe "image_box" do
224
+ it "creates an image box" do
225
+ image_path = File.join(TEST_DATA_DIR, 'images', 'gray.jpg')
226
+
227
+ box = @layout.image_box(image_path, width: 10, height: 15, style: {font_size: 20}, subscript: true)
228
+ assert_equal(10, box.width)
229
+ assert_equal(15, box.height)
230
+ assert_equal(20, box.style.font_size)
231
+ assert(box.style.subscript)
232
+ assert_same(@doc.images.add(image_path), box.image)
233
+ end
234
+
235
+ it "allows using a form XObject" do
236
+ form = @doc.add({Type: :XObject, Subtype: :Form, BBox: [0, 0, 10, 10]})
237
+ box = @layout.image_box(form, width: 10)
238
+ assert_equal(10, box.width)
239
+ assert_same(form, box.image)
240
+ end
241
+ end
242
+
243
+ describe "lorem_ipsum_box" do
244
+ it "creates a standard lorem ipsum box" do
245
+ box = @layout.lorem_ipsum_box(width: 10, height: 15, font_size: 15)
246
+ assert_equal(10, box.width)
247
+ assert_equal(15, box.height)
248
+ items = box.instance_variable_get(:@items)
249
+ assert_equal(HexaPDF::Document::Layout::LOREM_IPSUM.join(" ").size, items[0].items.length)
250
+ end
251
+
252
+ it "can use just some sentences from the lorem ipsum text" do
253
+ box = @layout.lorem_ipsum_box(sentences: 1)
254
+ items = box.instance_variable_get(:@items)
255
+ assert_equal(HexaPDF::Document::Layout::LOREM_IPSUM[0].size, items[0].items.length)
256
+ end
257
+
258
+ it "can use multiple of the selected sentences" do
259
+ box = @layout.lorem_ipsum_box(sentences: 2, count: 2)
260
+ items = box.instance_variable_get(:@items)
261
+ assert_equal(HexaPDF::Document::Layout::LOREM_IPSUM[0, 2].join(" ").size * 2 + 2, items[0].items.length)
262
+ end
263
+ end
264
+ end
@@ -72,6 +72,15 @@ describe HexaPDF::Document::Pages do
72
72
  end
73
73
  end
74
74
 
75
+ describe "move" do
76
+ it "moves the page to the given index" do
77
+ first = @doc.pages.add
78
+ second = @doc.pages.add
79
+ @doc.pages.move(first, -1)
80
+ assert_equal([second, first], @doc.pages.each.to_a)
81
+ end
82
+ end
83
+
75
84
  describe "delete" do
76
85
  it "deletes a given page" do
77
86
  page1 = @doc.pages.add
@@ -138,7 +138,7 @@ describe HexaPDF::Document::Signatures do
138
138
  describe "add" do
139
139
  before do
140
140
  @doc = HexaPDF::Document.new(io: StringIO.new(MINIMAL_PDF))
141
- @io = StringIO.new
141
+ @io = StringIO.new(''.b)
142
142
  end
143
143
 
144
144
  it "uses the provided signature dictionary" do
@@ -164,7 +164,7 @@ describe HexaPDF::Document::Signatures do
164
164
  sig = @doc.signatures.first
165
165
  assert_equal(:'Adobe.PPKLite', sig[:Filter])
166
166
  assert_equal(:'adbe.pkcs7.detached', sig[:SubFilter])
167
- assert_equal([0, 968, 3590, 2425], sig[:ByteRange].value)
167
+ assert_equal([0, 968, 3590, 2517], sig[:ByteRange].value)
168
168
  assert_equal(:sig, sig[:key])
169
169
  assert_equal(:sig_field, @doc.acro_form.each_field.first[:key])
170
170
  assert(sig.key?(:Contents))
@@ -205,7 +205,14 @@ describe HexaPDF::Document::Signatures do
205
205
  it "handles different xref section types correctly when determing the offsets" do
206
206
  @doc.delete(7)
207
207
  sig = @doc.signatures.add(@io, @handler, write_options: {update_fields: false})
208
- assert_equal([0, 968, 3590, 2412], sig[:ByteRange].value)
208
+ assert_equal([0, 968, 3590, 2491], sig[:ByteRange].value)
209
+ end
210
+
211
+ it "works if the signature object is the last object of the xref section" do
212
+ field = @doc.acro_form(create: true).create_signature_field('Signature2')
213
+ field.create_widget(@doc.pages[0], Rect: [0, 0, 0, 0])
214
+ sig = @doc.signatures.add(@io, @handler, signature: field, write_options: {update_fields: false})
215
+ assert_equal([0, 3063, 5685, 400], sig[:ByteRange].value)
209
216
  end
210
217
 
211
218
  it "allows writing to a file in addition to writing to an IO" do
@@ -378,7 +378,7 @@ describe HexaPDF::Encryption::SecurityHandler do
378
378
 
379
379
  it "works correctly with different decryption and encryption handlers" do
380
380
  test_file = File.join(TEST_DATA_DIR, 'standard-security-handler', 'nopwd-arc4-40bit-V1.pdf')
381
- doc = HexaPDF::Document.new(io: StringIO.new(File.read(test_file)))
381
+ doc = HexaPDF::Document.new(io: StringIO.new(File.binread(test_file)))
382
382
  doc.encrypt(algorithm: :aes, password: 'test')
383
383
  out = StringIO.new(''.b)
384
384
  doc.write(out, update_fields: false)
@@ -21,6 +21,10 @@ describe HexaPDF::Font::Encoding::GlyphList do
21
21
  assert_equal("\u05da\u05b8", @list.name_to_unicode(:finalkafqamats))
22
22
  end
23
23
 
24
+ it "parses the whole file" do
25
+ assert_equal("ズ", @list.name_to_unicode(:zukatakana))
26
+ end
27
+
24
28
  it "maps special uniXXXX names to unicode values" do
25
29
  assert_equal("A", @list.name_to_unicode(:uni0041))
26
30
  assert_equal("\u1234", @list.name_to_unicode(:uni1234))