hexapdf 0.30.0 → 0.32.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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
@@ -104,8 +104,16 @@ module HexaPDF
104
104
  Executive: [0, 0, 522, 756].freeze,
105
105
  }.freeze
106
106
 
107
- # Returns the media box for the given paper size. See PAPER_SIZE for the defined paper sizes.
107
+ # Returns the media box for the given paper size or array.
108
+ #
109
+ # If an array is specified, it needs to contain exactly four numbers. The +orientation+
110
+ # argument is not used in this case.
111
+ #
112
+ # See PAPER_SIZE for the defined paper sizes.
108
113
  def self.media_box(paper_size, orientation: :portrait)
114
+ return paper_size if paper_size.kind_of?(Array) && paper_size.size == 4 &&
115
+ paper_size.all?(Numeric)
116
+
109
117
  unless PAPER_SIZE.key?(paper_size)
110
118
  raise HexaPDF::Error, "Invalid paper size specified: #{paper_size}"
111
119
  end
@@ -118,9 +126,6 @@ module HexaPDF
118
126
  # The inheritable fields.
119
127
  INHERITABLE_FIELDS = [:Resources, :MediaBox, :CropBox, :Rotate].freeze
120
128
 
121
- # The required inheritable fields.
122
- REQUIRED_INHERITABLE_FIELDS = [:Resources, :MediaBox].freeze
123
-
124
129
  define_type :Page
125
130
 
126
131
  define_field :Type, type: Symbol, required: true, default: type
@@ -571,6 +576,12 @@ module HexaPDF
571
576
  left, right = [llx, ulx, lrx, lrx + (ulx - llx)].minmax
572
577
  bottom, top = [lly, uly, lry, lry + (uly - lly)].minmax
573
578
 
579
+ # Handle degenerate case of the transformed bounding box being a line or point
580
+ if right - left == 0 || top - bottom == 0
581
+ to_delete << annotation
582
+ next
583
+ end
584
+
574
585
  # Step b) Fit calculated rectangle to annotation rectangle by translating/scaling
575
586
  a = HexaPDF::Content::TransformationMatrix.new
576
587
  a.translate(rect.left - left, rect.bottom - bottom)
@@ -609,10 +620,26 @@ module HexaPDF
609
620
  return unless parent_node
610
621
 
611
622
  super
612
- REQUIRED_INHERITABLE_FIELDS.each do |name|
613
- next if self[name]
614
- yield("Inheritable page field #{name} not set", name == :Resources)
615
- resources.validate(&block) if name == :Ressources
623
+
624
+ unless self[:Resources]
625
+ yield("Required inheritable page field Resources not set", true)
626
+ resources.validate(&block)
627
+ end
628
+
629
+ unless self[:MediaBox]
630
+ yield("Required inheritable page field MediaBox not set", true)
631
+ index = self.index
632
+ box_before = index == 0 ? nil : document.pages[index - 1][:MediaBox]
633
+ box_after = index == document.pages.count - 1 ? nil : document.pages[index + 1]&.[](:MediaBox)
634
+ self[:MediaBox] =
635
+ if box_before && (box_before&.value == box_after&.value || box_after.nil?)
636
+ box_before.dup
637
+ elsif box_after && box_before.nil?
638
+ box_after
639
+ else
640
+ self.class.media_box(document.config['page.default_media_box'],
641
+ orientation: document.config['page.default_media_orientation'])
642
+ end
616
643
  end
617
644
  end
618
645
 
@@ -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
@@ -72,12 +72,10 @@ module HexaPDF
72
72
 
73
73
  define_field :Type, type: Symbol, default: type, required: true, indirect: false,
74
74
  version: '1.5'
75
- # Size is not required because it will be auto-filled before the object is written
76
- define_field :Size, type: Integer, indirect: false
75
+ define_field :Size, type: Integer, indirect: false, required: true
77
76
  define_field :Index, type: PDFArray, indirect: false
78
77
  define_field :Prev, type: Integer, indirect: false
79
- # W is not required because it will be auto-filled on #update_with_xref_section_and_trailer
80
- define_field :W, type: PDFArray, indirect: false
78
+ define_field :W, type: PDFArray, indirect: false, required: true
81
79
 
82
80
  # Returns an XRefSection that represents the content of this cross-reference stream.
83
81
  #
@@ -219,6 +217,15 @@ module HexaPDF
219
217
  [[1, middle, 2], pack_string]
220
218
  end
221
219
 
220
+ def perform_validation #:nodoc
221
+ # Size is not required because it will be auto-filled before the object is written
222
+ # W is not required because it will be auto-filled on #update_with_xref_section_and_trailer
223
+ # Set both here to dummy values to make validation work for the required values
224
+ self[:Size] ||= 1
225
+ self[:W] ||= [1, 1, 1]
226
+ super
227
+ end
228
+
222
229
  end
223
230
 
224
231
  end
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-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
@@ -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
@@ -37,6 +37,6 @@
37
37
  module HexaPDF
38
38
 
39
39
  # The version of HexaPDF.
40
- VERSION = '0.30.0'
40
+ VERSION = '0.32.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-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
@@ -207,7 +207,7 @@ module HexaPDF
207
207
  end
208
208
 
209
209
  if (!object_streams.empty? || @use_xref_streams) && xref_stream.nil?
210
- xref_stream = @document.wrap({Type: :XRef}, oid: @document.revisions.next_oid)
210
+ xref_stream = @document.wrap({}, type: Type::XRefStream, oid: @document.revisions.next_oid)
211
211
  rev.add(xref_stream)
212
212
  end
213
213
 
@@ -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.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
@@ -34,29 +34,24 @@ describe HexaPDF::Document::Layout::ChildrenCollector do
34
34
  assert_equal(2, @collector.children[0].size)
35
35
  end
36
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
37
+ it "allows appending boxes created by the Layout class" do
44
38
  @collector.lorem_ipsum
45
- assert_equal(1, @collector.children.size)
39
+ @collector.lorem_ipsum_box
40
+ @collector.column
41
+ @collector.column_box
42
+ assert_equal(4, @collector.children.size)
46
43
  assert_kind_of(HexaPDF::Layout::TextBox, @collector.children[0])
44
+ assert_kind_of(HexaPDF::Layout::TextBox, @collector.children[1])
45
+ assert_kind_of(HexaPDF::Layout::ColumnBox, @collector.children[2])
46
+ assert_kind_of(HexaPDF::Layout::ColumnBox, @collector.children[3])
47
47
  end
48
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])
49
+ it "can be asked which methods it supports" do
50
+ assert(@collector.respond_to?(:lorem_ipsum))
53
51
  end
54
52
 
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))
53
+ it "only allows using box creation methods from the Layout class" do
54
+ assert_raises(NameError) { @collector.style }
60
55
  end
61
56
 
62
57
  it "raises an error on an unknown method name" do
@@ -88,6 +83,27 @@ describe HexaPDF::Document::Layout do
88
83
  end
89
84
  end
90
85
 
86
+ describe "inline_box" do
87
+ it "takes a box as argument" do
88
+ box = HexaPDF::Layout::Box.create(width: 10, height: 10)
89
+ ibox = @layout.inline_box(box)
90
+ assert_same(box, ibox.box)
91
+ end
92
+
93
+ it "correctly passes on the valign argument" do
94
+ box = HexaPDF::Layout::Box.create(width: 10, height: 10)
95
+ ibox = @layout.inline_box(box, valign: :top)
96
+ assert_equal(:top, ibox.valign)
97
+ end
98
+
99
+ it "can create a box using any box creation method of the Layout class" do
100
+ ibox = @layout.inline_box(:text, "Some text", valign: :bottom, width: 10, background_color: "red")
101
+ assert_equal(:bottom, ibox.valign)
102
+ assert_equal(10, ibox.width)
103
+ assert_equal("red", ibox.box.style.background_color)
104
+ end
105
+ end
106
+
91
107
  describe "box" do
92
108
  it "creates the request box" do
93
109
  box = @layout.box(:column, columns: 3, gaps: 20, width: 15, height: 30, style: {font_size: 10},
@@ -232,6 +248,24 @@ describe HexaPDF::Document::Layout do
232
248
  items = box.instance_variable_get(:@items)
233
249
  assert_equal({named_dest: 'test'}, items[0].properties)
234
250
  end
251
+
252
+ it "allows adding an inline box" do
253
+ ibox = @layout.inline_box(:base, width: 10, height: 10)
254
+ box = @layout.formatted_text_box([ibox])
255
+ assert_equal(ibox, box.instance_variable_get(:@items).first)
256
+ end
257
+
258
+ it "allows creating an inline box through a hash with a :box key" do
259
+ block = lambda {|item| item.box(:base, width: 5, height: 15) }
260
+ box = @layout.formatted_text_box([{box: :list, width: 10, block: block}])
261
+ ibox = box.instance_variable_get(:@items).first
262
+ assert_equal(10, ibox.width)
263
+ assert_equal(15, ibox.height)
264
+ end
265
+
266
+ it "fails if the data array contains unsupported items" do
267
+ assert_raises(ArgumentError) { @layout.formatted_text_box([5]) }
268
+ end
235
269
  end
236
270
 
237
271
  describe "image_box" do
@@ -277,4 +311,33 @@ describe HexaPDF::Document::Layout do
277
311
  assert_equal(HexaPDF::Document::Layout::LOREM_IPSUM[0, 2].join(" ").size * 2 + 2, items[0].items.length)
278
312
  end
279
313
  end
314
+
315
+ describe "method_missing" do
316
+ it "resolves to internal methods with the _box suffix, e.g. text_box" do
317
+ box = @layout.text("Test", width: 10, height: 15, properties: {key: :value})
318
+ assert_kind_of(HexaPDF::Layout::TextBox, box)
319
+ assert_equal(10, box.width)
320
+ assert_equal(15, box.height)
321
+ assert_equal({key: :value}, box.properties)
322
+ end
323
+
324
+ it "resolves to the box method when a configured name is used" do
325
+ box = @layout.column
326
+ assert_kind_of(HexaPDF::Layout::ColumnBox, box)
327
+ box = @layout.column_box
328
+ assert_kind_of(HexaPDF::Layout::ColumnBox, box)
329
+ end
330
+
331
+ it "fails if nothing could be resolved" do
332
+ assert_raises(NameError) { @layout.unknown }
333
+ end
334
+ end
335
+
336
+ describe "respond_to_missing?" do
337
+ it "can be asked which methods it supports" do
338
+ assert(@layout.respond_to?(:text))
339
+ assert(@layout.respond_to?(:column))
340
+ refute(@layout.respond_to?(:unknown))
341
+ end
342
+ end
280
343
  end
@@ -84,4 +84,8 @@ module ARC4EncryptionTests
84
84
  small.process('some') << small.process(' big') << small.process(' data chunk'))
85
85
  end
86
86
 
87
+ def test_works_with_empty_strings
88
+ assert_equal('', @algorithm_class.new('key').process(''))
89
+ end
90
+
87
91
  end
@@ -48,6 +48,10 @@ describe HexaPDF::Encryption::AES do
48
48
  end
49
49
  end
50
50
 
51
+ it "handles invalid files with empty strings" do
52
+ assert_equal('', @algorithm_class.decrypt('key', ''))
53
+ end
54
+
51
55
  it "handles invalid files with missing 16 byte padding" do
52
56
  assert_equal('', @algorithm_class.decrypt('some key' * 2, 'iv' * 8))
53
57
  end
@@ -118,6 +122,10 @@ describe HexaPDF::Encryption::AES do
118
122
  assert_equal('a' * 13 << "\x00\x01\x03", result)
119
123
  end
120
124
 
125
+ it "handles invalid files with empty streams" do
126
+ assert_equal('', collector(@algorithm_class.decryption_fiber('key', Fiber.new { '' })))
127
+ end
128
+
121
129
  it "fails on decryption if not enough bytes are provided" do
122
130
  [4, 20, 40].each do |length|
123
131
  assert_raises(HexaPDF::EncryptionError) do
@@ -325,6 +325,12 @@ describe HexaPDF::Encryption::SecurityHandler do
325
325
  assert_equal("test", @handler.decrypt(@obj)[:Contents])
326
326
  end
327
327
 
328
+ it "enhances a thrown EncryptionError by setting the PDF object" do
329
+ @handler.set_up_encryption(key_length: 256)
330
+ error = assert_raises(HexaPDF::EncryptionError) { @handler.decrypt(@obj) }
331
+ assert_match(/Object \(1,0\):/, error.message)
332
+ end
333
+
328
334
  it "fails if V < 5 and the object number changes" do
329
335
  @obj.oid = 55
330
336
  @handler.decrypt(@obj)
@@ -26,12 +26,26 @@ describe HexaPDF::Filter::FlateDecode do
26
26
  assert_equal(@decoded, collector(@obj.decoder(feeder(@encoded_predictor), @predictor_opts)))
27
27
  end
28
28
 
29
- it "fails on invalid input" do
30
- assert_raises(HexaPDF::FilterError) do
31
- collector(@obj.decoder(feeder(@encoded[0..-2], @encoded.length - 3)))
29
+ describe "invalid input is handled as good as possible" do
30
+ def strict_mode
31
+ HexaPDF::GlobalConfiguration['filter.flate.on_error'] = proc { true }
32
+ yield
33
+ ensure
34
+ HexaPDF::GlobalConfiguration['filter.flate.on_error'] = proc { false }
32
35
  end
33
- assert_raises(HexaPDF::FilterError) do
34
- collector(@obj.decoder(feeder("some data")))
36
+
37
+ it "handles completely invalid data" do
38
+ assert_equal('', collector(@obj.decoder(feeder("some data"))))
39
+ assert_raises(HexaPDF::FilterError) do
40
+ strict_mode { collector(@obj.decoder(feeder("some data"))) }
41
+ end
42
+ end
43
+
44
+ it "handles missing data" do
45
+ assert_equal('abcdefg', collector(@obj.decoder(feeder(@encoded[0..-2]))))
46
+ assert_raises(HexaPDF::FilterError) do
47
+ strict_mode { collector(@obj.decoder(feeder(@encoded[0..-2]))) }
48
+ end
35
49
  end
36
50
  end
37
51
  end
@@ -2,31 +2,51 @@
2
2
 
3
3
  require 'test_helper'
4
4
  require 'hexapdf/layout/inline_box'
5
+ require 'hexapdf/document'
5
6
 
6
7
  describe HexaPDF::Layout::InlineBox do
8
+ def inline_box(box, valign: :baseline)
9
+ HexaPDF::Layout::InlineBox.new(box, valign: valign)
10
+ end
11
+
7
12
  before do
8
13
  @box = HexaPDF::Layout::InlineBox.create(width: 10, height: 15, margin: [15, 10])
9
14
  end
10
15
 
11
- it "needs a box to wrap and an optional alignment on initialization" do
12
- ibox = HexaPDF::Layout::InlineBox.new(@box)
13
- assert_equal(@box, ibox.box)
14
- assert_equal(:baseline, ibox.valign)
16
+ describe "initialize" do
17
+ it "needs a box to wrap and an optional alignment on initialization" do
18
+ box = HexaPDF::Layout::Box.create(width: 10, height: 15)
19
+ ibox = inline_box(box)
20
+ assert_equal(box, ibox.box)
21
+ assert_equal(:baseline, ibox.valign)
15
22
 
16
- ibox = HexaPDF::Layout::InlineBox.new(@box, valign: :top)
17
- assert_equal(:top, ibox.valign)
18
- end
23
+ ibox = inline_box(box, valign: :top)
24
+ assert_equal(:top, ibox.valign)
25
+ end
19
26
 
20
- it "draws the wrapped box at the correct position" do
21
- canvas = Object.new
22
- block = lambda do |c, x, y|
23
- assert_equal(canvas, c)
24
- assert_equal(10, x)
25
- assert_equal(15, y)
27
+ it "automatically fits the provided box into a frame" do
28
+ ibox = inline_box(HexaPDF::Document.new.layout.text("test is going good", width: 20))
29
+ assert_equal(20, ibox.width)
30
+ assert_equal(45, ibox.height)
26
31
  end
27
- @box.box.stub(:draw, block) do
28
- @box.draw(canvas, 0, 0)
32
+
33
+ it "fails if the wrapped box could not be fit" do
34
+ box = HexaPDF::Document.new.layout.text("test is not going good", width: 1)
35
+ assert_raises(HexaPDF::Error) { inline_box(box) }
29
36
  end
37
+
38
+ it "fails if the height is not set explicitly and during fitting" do
39
+ assert_raises(HexaPDF::Error) do
40
+ inline_box(HexaPDF::Layout::Box.create(width: 10))
41
+ end
42
+ end
43
+ end
44
+
45
+ it "draws the wrapped box at the correct position" do
46
+ doc = HexaPDF::Document.new
47
+ canvas = doc.pages.add.canvas
48
+ inline_box(doc.layout.text("", width: 20, margin: [15, 10])).draw(canvas, 100, 200)
49
+ assert_equal("q\n1 0 0 1 110 -99785 cm\nQ\n", canvas.contents)
30
50
  end
31
51
 
32
52
  it "returns true if the inline box is empty with no drawing operations" do
@@ -0,0 +1,70 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/layout/page_style'
5
+ require 'hexapdf/document'
6
+
7
+ describe HexaPDF::Layout::PageStyle do
8
+ it "allows assigning the page size, orientation and template on initialization" do
9
+ block = lambda {}
10
+ style = HexaPDF::Layout::PageStyle.new(page_size: :A3, orientation: :landscape, &block)
11
+ assert_equal(:A3, style.page_size)
12
+ assert_equal(:landscape, style.orientation)
13
+ assert_same(block, style.template)
14
+ end
15
+
16
+ it "uses defaults for all values" do
17
+ style = HexaPDF::Layout::PageStyle.new
18
+ assert_equal(:A4, style.page_size)
19
+ assert_equal(:portrait, style.orientation)
20
+ assert_nil(style.template)
21
+ assert_nil(style.frame)
22
+ assert_nil(style.next_style)
23
+ end
24
+
25
+ describe "create_page" do
26
+ before do
27
+ @doc = HexaPDF::Document.new
28
+ end
29
+
30
+ it "creates a new page object" do
31
+ style = HexaPDF::Layout::PageStyle.new do |canvas, istyle|
32
+ canvas.rectangle(0, 0, 10, 10).stroke
33
+ istyle.frame = :frame
34
+ istyle.next_style = :other
35
+ end
36
+ page = style.create_page(@doc)
37
+ assert_equal([0, 0, 595, 842], page.box(:media))
38
+ assert_equal("0 0 10 10 re\nS\n", page.contents)
39
+ assert_equal(:frame, style.frame)
40
+ assert_equal(:other, style.next_style)
41
+ assert_equal(0, @doc.pages.count)
42
+ end
43
+
44
+ it "works when no template is set" do
45
+ style = HexaPDF::Layout::PageStyle.new
46
+ page = style.create_page(@doc)
47
+ assert_equal("", page.contents)
48
+ end
49
+
50
+ it "creates a default frame if none is set beforehand or during template execution" do
51
+ style = HexaPDF::Layout::PageStyle.new
52
+ style.create_page(@doc)
53
+ assert_kind_of(HexaPDF::Layout::Frame, style.frame)
54
+ assert_equal(36, style.frame.left)
55
+ assert_equal(36, style.frame.bottom)
56
+ assert_equal(523, style.frame.width)
57
+ assert_equal(770, style.frame.height)
58
+ end
59
+ end
60
+
61
+ it "creates new frame objects given a page and a margin specification" do
62
+ doc = HexaPDF::Document.new
63
+ style = HexaPDF::Layout::PageStyle.new
64
+ frame = style.create_frame(style.create_page(doc), [15, 10])
65
+ assert_equal(10, frame.left)
66
+ assert_equal(15, frame.bottom)
67
+ assert_equal(575, frame.width)
68
+ assert_equal(812, frame.height)
69
+ end
70
+ end