hexapdf 0.6.0 → 0.7.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 (257) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +33 -0
  3. data/CONTRIBUTERS +1 -1
  4. data/LICENSE +1 -1
  5. data/Rakefile +1 -1
  6. data/VERSION +1 -1
  7. data/bin/hexapdf +1 -1
  8. data/examples/text_layouter_styling.rb +1 -2
  9. data/lib/hexapdf.rb +2 -2
  10. data/lib/hexapdf/cli.rb +3 -3
  11. data/lib/hexapdf/cli/batch.rb +5 -5
  12. data/lib/hexapdf/cli/command.rb +15 -17
  13. data/lib/hexapdf/cli/files.rb +3 -3
  14. data/lib/hexapdf/cli/images.rb +3 -4
  15. data/lib/hexapdf/cli/info.rb +5 -5
  16. data/lib/hexapdf/cli/inspect.rb +6 -6
  17. data/lib/hexapdf/cli/merge.rb +6 -6
  18. data/lib/hexapdf/cli/modify.rb +4 -4
  19. data/lib/hexapdf/cli/optimize.rb +3 -3
  20. data/lib/hexapdf/configuration.rb +4 -5
  21. data/lib/hexapdf/content.rb +2 -2
  22. data/lib/hexapdf/content/canvas.rb +35 -36
  23. data/lib/hexapdf/content/color_space.rb +9 -14
  24. data/lib/hexapdf/content/graphic_object.rb +2 -2
  25. data/lib/hexapdf/content/graphic_object/arc.rb +3 -3
  26. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +2 -2
  27. data/lib/hexapdf/content/graphic_object/solid_arc.rb +4 -8
  28. data/lib/hexapdf/content/graphics_state.rb +4 -13
  29. data/lib/hexapdf/content/operator.rb +33 -35
  30. data/lib/hexapdf/content/parser.rb +28 -18
  31. data/lib/hexapdf/content/processor.rb +4 -5
  32. data/lib/hexapdf/content/transformation_matrix.rb +2 -2
  33. data/lib/hexapdf/data_dir.rb +2 -2
  34. data/lib/hexapdf/dictionary.rb +8 -9
  35. data/lib/hexapdf/dictionary_fields.rb +7 -10
  36. data/lib/hexapdf/document.rb +18 -18
  37. data/lib/hexapdf/document/files.rb +12 -10
  38. data/lib/hexapdf/document/fonts.rb +2 -2
  39. data/lib/hexapdf/document/images.rb +3 -3
  40. data/lib/hexapdf/document/pages.rb +4 -4
  41. data/lib/hexapdf/encryption.rb +2 -2
  42. data/lib/hexapdf/encryption/aes.rb +2 -2
  43. data/lib/hexapdf/encryption/arc4.rb +4 -4
  44. data/lib/hexapdf/encryption/fast_aes.rb +2 -2
  45. data/lib/hexapdf/encryption/fast_arc4.rb +4 -4
  46. data/lib/hexapdf/encryption/identity.rb +5 -4
  47. data/lib/hexapdf/encryption/ruby_aes.rb +147 -139
  48. data/lib/hexapdf/encryption/ruby_arc4.rb +4 -4
  49. data/lib/hexapdf/encryption/security_handler.rb +11 -12
  50. data/lib/hexapdf/encryption/standard_security_handler.rb +6 -9
  51. data/lib/hexapdf/error.rb +7 -9
  52. data/lib/hexapdf/filter.rb +2 -3
  53. data/lib/hexapdf/filter/ascii85_decode.rb +3 -3
  54. data/lib/hexapdf/filter/ascii_hex_decode.rb +2 -2
  55. data/lib/hexapdf/filter/dct_decode.rb +2 -2
  56. data/lib/hexapdf/filter/encryption.rb +2 -2
  57. data/lib/hexapdf/filter/flate_decode.rb +16 -33
  58. data/lib/hexapdf/filter/jpx_decode.rb +2 -2
  59. data/lib/hexapdf/filter/lzw_decode.rb +4 -4
  60. data/lib/hexapdf/filter/predictor.rb +2 -6
  61. data/lib/hexapdf/filter/run_length_decode.rb +2 -2
  62. data/lib/hexapdf/font/cmap.rb +2 -3
  63. data/lib/hexapdf/font/cmap/parser.rb +11 -11
  64. data/lib/hexapdf/font/cmap/writer.rb +25 -25
  65. data/lib/hexapdf/font/encoding.rb +2 -2
  66. data/lib/hexapdf/font/encoding/base.rb +2 -2
  67. data/lib/hexapdf/font/encoding/difference_encoding.rb +2 -2
  68. data/lib/hexapdf/font/encoding/glyph_list.rb +6 -6
  69. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +2 -2
  70. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
  71. data/lib/hexapdf/font/encoding/standard_encoding.rb +2 -2
  72. data/lib/hexapdf/font/encoding/symbol_encoding.rb +2 -2
  73. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +2 -2
  74. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +2 -2
  75. data/lib/hexapdf/font/invalid_glyph.rb +7 -7
  76. data/lib/hexapdf/font/true_type.rb +2 -2
  77. data/lib/hexapdf/font/true_type/builder.rb +13 -7
  78. data/lib/hexapdf/font/true_type/font.rb +2 -3
  79. data/lib/hexapdf/font/true_type/optimizer.rb +2 -2
  80. data/lib/hexapdf/font/true_type/subsetter.rb +4 -4
  81. data/lib/hexapdf/font/true_type/table.rb +3 -5
  82. data/lib/hexapdf/font/true_type/table/cmap.rb +2 -2
  83. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +9 -16
  84. data/lib/hexapdf/font/true_type/table/directory.rb +4 -4
  85. data/lib/hexapdf/font/true_type/table/glyf.rb +2 -2
  86. data/lib/hexapdf/font/true_type/table/head.rb +3 -2
  87. data/lib/hexapdf/font/true_type/table/hhea.rb +2 -2
  88. data/lib/hexapdf/font/true_type/table/hmtx.rb +2 -2
  89. data/lib/hexapdf/font/true_type/table/kern.rb +3 -3
  90. data/lib/hexapdf/font/true_type/table/loca.rb +3 -3
  91. data/lib/hexapdf/font/true_type/table/maxp.rb +2 -2
  92. data/lib/hexapdf/font/true_type/table/name.rb +3 -5
  93. data/lib/hexapdf/font/true_type/table/os2.rb +4 -3
  94. data/lib/hexapdf/font/true_type/table/post.rb +3 -7
  95. data/lib/hexapdf/font/true_type_wrapper.rb +20 -22
  96. data/lib/hexapdf/font/type1.rb +2 -2
  97. data/lib/hexapdf/font/type1/afm_parser.rb +7 -7
  98. data/lib/hexapdf/font/type1/character_metrics.rb +2 -2
  99. data/lib/hexapdf/font/type1/font.rb +3 -3
  100. data/lib/hexapdf/font/type1/font_metrics.rb +2 -4
  101. data/lib/hexapdf/font/type1/pfb_parser.rb +2 -2
  102. data/lib/hexapdf/font/type1_wrapper.rb +8 -9
  103. data/lib/hexapdf/font_loader.rb +2 -2
  104. data/lib/hexapdf/font_loader/from_configuration.rb +2 -2
  105. data/lib/hexapdf/font_loader/from_file.rb +2 -2
  106. data/lib/hexapdf/font_loader/standard14.rb +2 -2
  107. data/lib/hexapdf/image_loader.rb +2 -2
  108. data/lib/hexapdf/image_loader/jpeg.rb +6 -4
  109. data/lib/hexapdf/image_loader/pdf.rb +2 -2
  110. data/lib/hexapdf/image_loader/png.rb +6 -6
  111. data/lib/hexapdf/importer.rb +6 -4
  112. data/lib/hexapdf/layout.rb +2 -2
  113. data/lib/hexapdf/layout/box.rb +4 -4
  114. data/lib/hexapdf/layout/inline_box.rb +2 -2
  115. data/lib/hexapdf/layout/line.rb +6 -6
  116. data/lib/hexapdf/layout/numeric_refinements.rb +2 -2
  117. data/lib/hexapdf/layout/style.rb +17 -8
  118. data/lib/hexapdf/layout/text_fragment.rb +86 -48
  119. data/lib/hexapdf/layout/text_layouter.rb +40 -21
  120. data/lib/hexapdf/layout/text_shaper.rb +2 -2
  121. data/lib/hexapdf/name_tree_node.rb +2 -2
  122. data/lib/hexapdf/number_tree_node.rb +2 -2
  123. data/lib/hexapdf/object.rb +6 -8
  124. data/lib/hexapdf/parser.rb +10 -10
  125. data/lib/hexapdf/rectangle.rb +4 -4
  126. data/lib/hexapdf/reference.rb +2 -2
  127. data/lib/hexapdf/revision.rb +4 -4
  128. data/lib/hexapdf/revisions.rb +5 -5
  129. data/lib/hexapdf/serializer.rb +27 -24
  130. data/lib/hexapdf/stream.rb +4 -4
  131. data/lib/hexapdf/task.rb +2 -2
  132. data/lib/hexapdf/task/dereference.rb +4 -4
  133. data/lib/hexapdf/task/optimize.rb +5 -4
  134. data/lib/hexapdf/tokenizer.rb +12 -14
  135. data/lib/hexapdf/type.rb +2 -2
  136. data/lib/hexapdf/type/action.rb +3 -3
  137. data/lib/hexapdf/type/actions.rb +2 -2
  138. data/lib/hexapdf/type/actions/go_to.rb +2 -2
  139. data/lib/hexapdf/type/actions/go_to_r.rb +2 -2
  140. data/lib/hexapdf/type/actions/launch.rb +2 -2
  141. data/lib/hexapdf/type/actions/uri.rb +3 -3
  142. data/lib/hexapdf/type/annotation.rb +3 -3
  143. data/lib/hexapdf/type/annotations.rb +2 -2
  144. data/lib/hexapdf/type/annotations/link.rb +2 -2
  145. data/lib/hexapdf/type/annotations/markup_annotation.rb +2 -2
  146. data/lib/hexapdf/type/annotations/text.rb +2 -2
  147. data/lib/hexapdf/type/catalog.rb +4 -4
  148. data/lib/hexapdf/type/cid_font.rb +4 -5
  149. data/lib/hexapdf/type/embedded_file.rb +3 -3
  150. data/lib/hexapdf/type/file_specification.rb +6 -7
  151. data/lib/hexapdf/type/font.rb +4 -4
  152. data/lib/hexapdf/type/font_descriptor.rb +3 -4
  153. data/lib/hexapdf/type/font_simple.rb +12 -16
  154. data/lib/hexapdf/type/font_true_type.rb +2 -2
  155. data/lib/hexapdf/type/font_type0.rb +5 -5
  156. data/lib/hexapdf/type/font_type1.rb +4 -4
  157. data/lib/hexapdf/type/form.rb +3 -3
  158. data/lib/hexapdf/type/graphics_state_parameter.rb +3 -3
  159. data/lib/hexapdf/type/image.rb +13 -14
  160. data/lib/hexapdf/type/info.rb +2 -2
  161. data/lib/hexapdf/type/names.rb +2 -2
  162. data/lib/hexapdf/type/object_stream.rb +5 -5
  163. data/lib/hexapdf/type/page.rb +9 -10
  164. data/lib/hexapdf/type/page_tree_node.rb +5 -6
  165. data/lib/hexapdf/type/resources.rb +11 -11
  166. data/lib/hexapdf/type/trailer.rb +3 -3
  167. data/lib/hexapdf/type/viewer_preferences.rb +2 -2
  168. data/lib/hexapdf/type/xref_stream.rb +8 -4
  169. data/lib/hexapdf/utils/bit_field.rb +4 -4
  170. data/lib/hexapdf/utils/bit_stream.rb +4 -4
  171. data/lib/hexapdf/utils/graphics_helpers.rb +2 -2
  172. data/lib/hexapdf/utils/lru_cache.rb +2 -2
  173. data/lib/hexapdf/utils/math_helpers.rb +2 -2
  174. data/lib/hexapdf/utils/object_hash.rb +3 -3
  175. data/lib/hexapdf/utils/pdf_doc_encoding.rb +3 -3
  176. data/lib/hexapdf/utils/sorted_tree_node.rb +12 -11
  177. data/lib/hexapdf/version.rb +3 -3
  178. data/lib/hexapdf/writer.rb +8 -8
  179. data/lib/hexapdf/xref_section.rb +3 -3
  180. data/test/hexapdf/common_tokenizer_tests.rb +6 -7
  181. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +0 -1
  182. data/test/hexapdf/content/test_canvas.rb +28 -36
  183. data/test/hexapdf/content/test_color_space.rb +4 -0
  184. data/test/hexapdf/content/test_graphics_state.rb +2 -0
  185. data/test/hexapdf/content/test_operator.rb +6 -7
  186. data/test/hexapdf/content/test_parser.rb +2 -2
  187. data/test/hexapdf/content/test_processor.rb +1 -1
  188. data/test/hexapdf/document/test_files.rb +1 -0
  189. data/test/hexapdf/document/test_images.rb +1 -1
  190. data/test/hexapdf/encryption/common.rb +3 -3
  191. data/test/hexapdf/encryption/test_aes.rb +10 -4
  192. data/test/hexapdf/encryption/test_identity.rb +1 -1
  193. data/test/hexapdf/encryption/test_security_handler.rb +13 -17
  194. data/test/hexapdf/encryption/test_standard_security_handler.rb +12 -12
  195. data/test/hexapdf/filter/test_ascii85_decode.rb +2 -3
  196. data/test/hexapdf/filter/test_ascii_hex_decode.rb +6 -1
  197. data/test/hexapdf/filter/test_flate_decode.rb +2 -2
  198. data/test/hexapdf/filter/test_lzw_decode.rb +10 -10
  199. data/test/hexapdf/filter/test_predictor.rb +10 -2
  200. data/test/hexapdf/filter/test_run_length_decode.rb +1 -1
  201. data/test/hexapdf/font/cmap/test_parser.rb +40 -40
  202. data/test/hexapdf/font/cmap/test_writer.rb +29 -29
  203. data/test/hexapdf/font/test_true_type_wrapper.rb +3 -2
  204. data/test/hexapdf/font/true_type/common.rb +2 -0
  205. data/test/hexapdf/font/true_type/table/test_cmap.rb +1 -1
  206. data/test/hexapdf/font/true_type/table/test_cmap_subtable.rb +5 -4
  207. data/test/hexapdf/font/true_type/table/test_glyf.rb +2 -2
  208. data/test/hexapdf/font/true_type/table/test_head.rb +2 -2
  209. data/test/hexapdf/font/true_type/table/test_name.rb +9 -6
  210. data/test/hexapdf/font/true_type/test_builder.rb +8 -3
  211. data/test/hexapdf/font/true_type/test_optimizer.rb +1 -2
  212. data/test/hexapdf/font/type1/test_afm_parser.rb +2 -2
  213. data/test/hexapdf/image_loader/test_jpeg.rb +1 -1
  214. data/test/hexapdf/image_loader/test_pdf.rb +1 -1
  215. data/test/hexapdf/image_loader/test_png.rb +3 -3
  216. data/test/hexapdf/layout/test_inline_box.rb +10 -1
  217. data/test/hexapdf/layout/test_line.rb +4 -4
  218. data/test/hexapdf/layout/test_style.rb +19 -7
  219. data/test/hexapdf/layout/test_text_fragment.rb +73 -27
  220. data/test/hexapdf/layout/test_text_layouter.rb +84 -68
  221. data/test/hexapdf/layout/test_text_shaper.rb +4 -6
  222. data/test/hexapdf/task/test_dereference.rb +2 -2
  223. data/test/hexapdf/task/test_optimize.rb +16 -7
  224. data/test/hexapdf/test_configuration.rb +1 -1
  225. data/test/hexapdf/test_data_dir.rb +2 -2
  226. data/test/hexapdf/test_dictionary.rb +6 -3
  227. data/test/hexapdf/test_dictionary_fields.rb +15 -14
  228. data/test/hexapdf/test_document.rb +47 -48
  229. data/test/hexapdf/test_filter.rb +30 -26
  230. data/test/hexapdf/test_importer.rb +14 -0
  231. data/test/hexapdf/test_object.rb +16 -4
  232. data/test/hexapdf/test_parser.rb +36 -36
  233. data/test/hexapdf/test_reference.rb +7 -5
  234. data/test/hexapdf/test_revision.rb +1 -1
  235. data/test/hexapdf/test_revisions.rb +90 -90
  236. data/test/hexapdf/test_serializer.rb +3 -2
  237. data/test/hexapdf/test_stream.rb +2 -4
  238. data/test/hexapdf/test_tokenizer.rb +2 -2
  239. data/test/hexapdf/test_writer.rb +80 -80
  240. data/test/hexapdf/test_xref_section.rb +1 -1
  241. data/test/hexapdf/type/annotations/test_link.rb +1 -1
  242. data/test/hexapdf/type/annotations/test_text.rb +3 -3
  243. data/test/hexapdf/type/test_font_descriptor.rb +1 -1
  244. data/test/hexapdf/type/test_font_simple.rb +2 -2
  245. data/test/hexapdf/type/test_font_type0.rb +0 -1
  246. data/test/hexapdf/type/test_image.rb +0 -3
  247. data/test/hexapdf/type/test_object_stream.rb +2 -1
  248. data/test/hexapdf/type/test_page.rb +5 -1
  249. data/test/hexapdf/type/test_page_tree_node.rb +4 -4
  250. data/test/hexapdf/type/test_trailer.rb +1 -1
  251. data/test/hexapdf/type/test_xref_stream.rb +4 -0
  252. data/test/hexapdf/utils/test_bit_field.rb +2 -0
  253. data/test/hexapdf/utils/test_bit_stream.rb +1 -1
  254. data/test/hexapdf/utils/test_lru_cache.rb +1 -1
  255. data/test/hexapdf/utils/test_sorted_tree_node.rb +10 -4
  256. data/test/test_helper.rb +3 -6
  257. metadata +3 -3
@@ -21,8 +21,8 @@ describe HexaPDF::Task::Dereference do
21
21
 
22
22
  checker = lambda do |val, done = {}|
23
23
  case val
24
- when Array then val.all? {|v| checker.call(v, done)}
25
- when Hash then val.all? {|_, v| checker.call(v, done)}
24
+ when Array then val.all? {|v| checker.call(v, done) }
25
+ when Hash then val.all? {|_, v| checker.call(v, done) }
26
26
  when HexaPDF::Reference
27
27
  false
28
28
  when HexaPDF::Object
@@ -6,7 +6,9 @@ require 'hexapdf/task/optimize'
6
6
 
7
7
  describe HexaPDF::Task::Optimize do
8
8
  class TestType < HexaPDF::Dictionary
9
+
9
10
  define_field :Optional, type: Symbol, default: :Optional
11
+
10
12
  end
11
13
 
12
14
  before do
@@ -21,20 +23,20 @@ describe HexaPDF::Task::Optimize do
21
23
  end
22
24
 
23
25
  def assert_objstms_generated
24
- assert(@doc.revisions.all? {|rev| rev.any? {|obj| obj.type == :ObjStm}})
25
- assert(@doc.revisions.all? {|rev| rev.any? {|obj| obj.type == :XRef}})
26
+ assert(@doc.revisions.all? {|rev| rev.any? {|obj| obj.type == :ObjStm } })
27
+ assert(@doc.revisions.all? {|rev| rev.any? {|obj| obj.type == :XRef } })
26
28
  end
27
29
 
28
30
  def assert_xrefstms_generated
29
- assert(@doc.revisions.all? {|rev| rev.any? {|obj| obj.type == :XRef}})
31
+ assert(@doc.revisions.all? {|rev| rev.find_all {|obj| obj.type == :XRef }.size == 1 })
30
32
  end
31
33
 
32
34
  def assert_no_objstms
33
- assert(@doc.each(current: false).all? {|obj| obj.type != :ObjStm})
35
+ assert(@doc.each(current: false).all? {|obj| obj.type != :ObjStm })
34
36
  end
35
37
 
36
38
  def assert_no_xrefstms
37
- assert(@doc.each(current: false).all? {|obj| obj.type != :XRef})
39
+ assert(@doc.each(current: false).all? {|obj| obj.type != :XRef })
38
40
  end
39
41
 
40
42
  def assert_default_deleted
@@ -90,12 +92,13 @@ describe HexaPDF::Task::Optimize do
90
92
  assert_objstms_generated
91
93
  assert_default_deleted
92
94
  assert_nil(@doc.object(objstm).value)
93
- assert(3, @doc.revisions.current.find_all {|obj| obj.type == :ObjStm}.size)
94
- assert([xref], @doc.revisions.current.find_all {|obj| obj.type == :XRef})
95
+ assert(3, @doc.revisions.current.find_all {|obj| obj.type == :ObjStm }.size)
96
+ assert([xref], @doc.revisions.current.find_all {|obj| obj.type == :XRef })
95
97
  end
96
98
 
97
99
  it "deletes object and xref streams" do
98
100
  @doc.add(Type: :ObjStm)
101
+ @doc.add(Type: :XRef)
99
102
  @doc.task(:optimize, object_streams: :delete, xref_streams: :delete)
100
103
  assert_no_objstms
101
104
  assert_no_xrefstms
@@ -118,6 +121,12 @@ describe HexaPDF::Task::Optimize do
118
121
  assert_default_deleted
119
122
  end
120
123
 
124
+ it "reuses an xref stream in generatation mode" do
125
+ @doc.add(Type: :XRef)
126
+ @doc.task(:optimize, xref_streams: :generate)
127
+ assert_xrefstms_generated
128
+ end
129
+
121
130
  it "deletes xref streams" do
122
131
  @doc.add(Type: :XRef)
123
132
  @doc.task(:optimize, xref_streams: :delete)
@@ -87,7 +87,7 @@ describe HexaPDF::Configuration do
87
87
  end
88
88
 
89
89
  it "returns the result of the given block when no constant is found" do
90
- assert_equal(:test, @config.constantize('unk') {|name| assert_equal('unk', name); :test})
90
+ assert_equal(:test, @config.constantize('unk') {|name| assert_equal('unk', name); :test })
91
91
  end
92
92
  end
93
93
  end
@@ -19,13 +19,13 @@ describe 'HexaPDF.data_dir' do
19
19
  end
20
20
 
21
21
  it "returns the global data directory if the local one isn't found" do
22
- File.stub(:directory?, lambda {|path| path == @local ? false : true}) do
22
+ File.stub(:directory?, lambda {|path| path != @local }) do
23
23
  assert_equal(@global, HexaPDF.data_dir)
24
24
  end
25
25
  end
26
26
 
27
27
  it "fails if no data directory is found" do
28
- File.stub(:directory?, lambda {|_path| false}) do
28
+ File.stub(:directory?, lambda {|_path| false }) do
29
29
  assert_raises { HexaPDF.data_dir }
30
30
  end
31
31
  end
@@ -62,7 +62,7 @@ describe HexaPDF::Dictionary do
62
62
  it "can iterate over all fields" do
63
63
  @inherited_class = Class.new(@test_class)
64
64
  @inherited_class.define_field(:Inherited, type: [Array, Symbol])
65
- assert_equal([:Boolean, :Array, :TestClass, :Inherited], @inherited_class.each_field.map {|k, _| k})
65
+ assert_equal([:Boolean, :Array, :TestClass, :Inherited], @inherited_class.each_field.map {|k, _| k })
66
66
  end
67
67
 
68
68
  it "allows field access without subclassing" do
@@ -149,7 +149,7 @@ describe HexaPDF::Dictionary do
149
149
  assert_equal(7, @dict.value[:NewValue])
150
150
  end
151
151
 
152
- it "stores the value inside the current value HexaPDF::Object but only if the given one is not such an object" do
152
+ it "stores the value in an existing HexaPDF::Object but only if it is not such an object" do
153
153
  @dict[:Object] = [4, 5]
154
154
  assert_equal([4, 5], @dict.value[:Object].value)
155
155
 
@@ -256,7 +256,10 @@ describe HexaPDF::Dictionary do
256
256
  end
257
257
 
258
258
  it "validates direct PDF objects nested in hashes" do
259
- @obj[:TestClass] = {Inherited: :symbol, Nested: {Nested: {TestClass: @test_class.new(nil, document: self)}}}
259
+ @obj[:TestClass] = {
260
+ Inherited: :symbol,
261
+ Nested: {Nested: {TestClass: @test_class.new(nil, document: self)}},
262
+ }
260
263
  refute(@obj.validate)
261
264
  @obj[:TestClass][:Nested][:Nested][:TestClass][:Inherited] = :symbol
262
265
  assert(@obj.validate)
@@ -123,20 +123,21 @@ describe HexaPDF::DictionaryFields do
123
123
  refute(@field.convert?('test'.b))
124
124
  assert(@field.convert?(date))
125
125
 
126
- [["D:1998", [1998, 01, 01, 00, 00, 00, "-00:00"]],
127
- ["D:199812", [1998, 12, 01, 00, 00, 00, "-00:00"]],
128
- ["D:19981223", [1998, 12, 23, 00, 00, 00, "-00:00"]],
129
- ["D:1998122319", [1998, 12, 23, 19, 00, 00, "+00:00"]],
130
- ["D:199812231952", [1998, 12, 23, 19, 52, 00, "+00:00"]],
131
- ["D:19981223195210", [1998, 12, 23, 19, 52, 10, "+00:00"]],
132
- ["D:19981223195210-08'00'", [1998, 12, 23, 19, 52, 10, "-08:00"]],
133
- ["D:1998122319-08'00'", [1998, 12, 23, 19, 00, 00, "-08:00"]],
134
- ["D:19981223-08'00'", [1998, 12, 23, 00, 00, 00, "-08:00"]],
135
- ["D:199812-08'00'", [1998, 12, 01, 00, 00, 00, "-08:00"]],
136
- ["D:1998-08'00'", [1998, 01, 01, 00, 00, 00, "-08:00"]],
137
- ["D:19981223195210-08", [1998, 12, 23, 19, 52, 10, "-08:00"]], # non-standard bc missing '
138
- ["D:19981223195210-08'00", [1998, 12, 23, 19, 52, 10, "-08:00"]], # non-standard bc missing '
139
- ].each do |str, data|
126
+ [
127
+ ["D:1998", [1998, 01, 01, 00, 00, 00, "-00:00"]],
128
+ ["D:199812", [1998, 12, 01, 00, 00, 00, "-00:00"]],
129
+ ["D:19981223", [1998, 12, 23, 00, 00, 00, "-00:00"]],
130
+ ["D:1998122319", [1998, 12, 23, 19, 00, 00, "+00:00"]],
131
+ ["D:199812231952", [1998, 12, 23, 19, 52, 00, "+00:00"]],
132
+ ["D:19981223195210", [1998, 12, 23, 19, 52, 10, "+00:00"]],
133
+ ["D:19981223195210-08'00'", [1998, 12, 23, 19, 52, 10, "-08:00"]],
134
+ ["D:1998122319-08'00'", [1998, 12, 23, 19, 00, 00, "-08:00"]],
135
+ ["D:19981223-08'00'", [1998, 12, 23, 00, 00, 00, "-08:00"]],
136
+ ["D:199812-08'00'", [1998, 12, 01, 00, 00, 00, "-08:00"]],
137
+ ["D:1998-08'00'", [1998, 01, 01, 00, 00, 00, "-08:00"]],
138
+ ["D:19981223195210-08", [1998, 12, 23, 19, 52, 10, "-08:00"]], # non-standard, missing '
139
+ ["D:19981223195210-08'00", [1998, 12, 23, 19, 52, 10, "-08:00"]], # non-standard, missing '
140
+ ].each do |str, data|
140
141
  obj = @field.convert(str, self)
141
142
  assert_equal(Time.new(*data), obj, "date str used: #{str}")
142
143
  end
@@ -7,46 +7,46 @@ require 'stringio'
7
7
 
8
8
  describe HexaPDF::Document do
9
9
  before do
10
- @io = StringIO.new(<<EOF)
11
- %PDF-1.7
12
- 1 0 obj
13
- 10
14
- endobj
15
-
16
- 2 0 obj
17
- 20
18
- endobj
19
-
20
- 3 0 obj
21
- 30
22
- endobj
23
-
24
- xref
25
- 0 4
26
- 0000000000 65535 f
27
- 0000000009 00000 n
28
- 0000000028 00000 n
29
- 0000000047 00000 n
30
- trailer
31
- << /Size 4 >>
32
- startxref
33
- 66
34
- %%EOF
35
-
36
- 2 0 obj
37
- 200
38
- endobj
39
-
40
- xref
41
- 2 2
42
- 0000000197 00000 n
43
- 0000000000 00001 f
44
- trailer
45
- << /Size 4 /Prev 66 >>
46
- startxref
47
- 217
48
- %%EOF
49
- EOF
10
+ @io = StringIO.new(<<~EOF)
11
+ %PDF-1.7
12
+ 1 0 obj
13
+ 10
14
+ endobj
15
+
16
+ 2 0 obj
17
+ 20
18
+ endobj
19
+
20
+ 3 0 obj
21
+ 30
22
+ endobj
23
+
24
+ xref
25
+ 0 4
26
+ 0000000000 65535 f
27
+ 0000000009 00000 n
28
+ 0000000028 00000 n
29
+ 0000000047 00000 n
30
+ trailer
31
+ << /Size 4 >>
32
+ startxref
33
+ 66
34
+ %%EOF
35
+
36
+ 2 0 obj
37
+ 200
38
+ endobj
39
+
40
+ xref
41
+ 2 2
42
+ 0000000197 00000 n
43
+ 0000000000 00001 f
44
+ trailer
45
+ << /Size 4 /Prev 66 >>
46
+ startxref
47
+ 217
48
+ %%EOF
49
+ EOF
50
50
  @io_doc = HexaPDF::Document.new(io: @io)
51
51
  @doc = HexaPDF::Document.new
52
52
  end
@@ -195,7 +195,7 @@ EOF
195
195
  assert_raises(HexaPDF::Error) { @doc.add(obj) }
196
196
  end
197
197
 
198
- it "fails if the object number of the object to be added is already associated with another object" do
198
+ it "fails if the object number is already associated with another object" do
199
199
  obj = @doc.add(5)
200
200
  assert_raises(HexaPDF::Error) { @doc.add(@doc.wrap(5, oid: obj.oid, gen: 1)) }
201
201
  end
@@ -395,7 +395,7 @@ EOF
395
395
 
396
396
  it "yields the revision as second argument if the block accepts exactly two arguments" do
397
397
  objs = [[10, 20, 30], [200, nil]]
398
- data = @io_doc.revisions.map.with_index {|rev, i| objs[i].map {|o| [o, rev]}}.reverse.flatten
398
+ data = @io_doc.revisions.map.with_index {|rev, i| objs[i].map {|o| [o, rev] } }.reverse.flatten
399
399
  @io_doc.each(current: false) do |obj, rev|
400
400
  assert(data.shift == obj.value)
401
401
  assert_equal(data.shift, rev)
@@ -450,7 +450,6 @@ EOF
450
450
  end
451
451
  end
452
452
 
453
-
454
453
  describe "write" do
455
454
  it "writes the document to a file" do
456
455
  begin
@@ -498,14 +497,14 @@ EOF
498
497
  io = StringIO.new(''.b)
499
498
  @io_doc.write(io)
500
499
  doc = HexaPDF::Document.new(io: io)
501
- assert_equal(0, doc.each.count {|o| o.type == :ObjStm})
500
+ assert_equal(0, doc.each.count {|o| o.type == :ObjStm })
502
501
  end
503
502
 
504
503
  it "allows optimizing the file by using object streams" do
505
504
  io = StringIO.new(''.b)
506
505
  @io_doc.write(io, optimize: true)
507
506
  doc = HexaPDF::Document.new(io: io)
508
- assert_equal(2, doc.each.count {|o| o.type == :ObjStm})
507
+ assert_equal(2, doc.each.count {|o| o.type == :ObjStm })
509
508
  end
510
509
  end
511
510
 
@@ -547,7 +546,7 @@ EOF
547
546
  assert_equal(doc, @doc)
548
547
  block.call('inside')
549
548
  end
550
- assert_equal(:done, @doc.task(:test) {|msg| assert_equal('inside', msg); :done})
549
+ assert_equal(:done, @doc.task(:test) {|msg| assert_equal('inside', msg); :done })
551
550
  end
552
551
 
553
552
  it "fails if the given task is not available" do
@@ -558,9 +557,9 @@ EOF
558
557
  describe "listener interface" do
559
558
  it "allows registering and dispatching messages" do
560
559
  args = []
561
- callable = lambda {|*a| args << [:callable, a]}
560
+ callable = lambda {|*a| args << [:callable, a] }
562
561
  @doc.register_listener(:something, callable)
563
- @doc.register_listener(:something) {|*a| args << [:block, a]}
562
+ @doc.register_listener(:something) {|*a| args << [:block, a] }
564
563
  @doc.dispatch_message(:something, :arg)
565
564
  assert_equal([[:callable, [:arg]], [:block, [:arg]]], args)
566
565
  end
@@ -29,32 +29,34 @@ describe HexaPDF::Filter do
29
29
  @io = StringIO.new(@str.dup)
30
30
  end
31
31
 
32
+ def from_io(**opts)
33
+ collector(@obj.source_from_io(@io, **opts))
34
+ end
35
+
32
36
  it "converts an IO into a source via #source_from_io" do
33
- assert_equal(@str, collector(@obj.source_from_io(@io)))
37
+ assert_equal(@str, from_io)
34
38
 
35
- assert_equal(@str, collector(@obj.source_from_io(@io, pos: -10)))
36
- assert_equal(@str[10..-1], collector(@obj.source_from_io(@io, pos: 10)))
37
- assert_equal("", collector(@obj.source_from_io(@io, pos: 200)))
39
+ assert_equal(@str, from_io(pos: -10))
40
+ assert_equal(@str[10..-1], from_io(pos: 10))
41
+ assert_equal("", from_io(pos: 200))
38
42
 
39
- assert_equal("", collector(@obj.source_from_io(@io, length: 0)))
40
- assert_equal(@str[0...100], collector(@obj.source_from_io(@io, length: 100)))
41
- assert_equal(@str, collector(@obj.source_from_io(@io, length: -15)))
43
+ assert_equal("", from_io(length: 0))
44
+ assert_equal(@str[0...100], from_io(length: 100))
45
+ assert_equal(@str, from_io(length: -15))
42
46
  assert_equal(100, @obj.source_from_io(@io, length: 100).length)
43
47
 
44
- assert_equal(@str, collector(@obj.source_from_io(@io, chunk_size: -15)))
45
- assert_equal(@str, collector(@obj.source_from_io(@io, chunk_size: 0)))
46
- assert_equal(@str, collector(@obj.source_from_io(@io, chunk_size: 100)))
47
- assert_equal(@str, collector(@obj.source_from_io(@io, chunk_size: 200)))
48
+ assert_equal(@str, from_io(chunk_size: -15))
49
+ assert_equal(@str, from_io(chunk_size: 0))
50
+ assert_equal(@str, from_io(chunk_size: 100))
51
+ assert_equal(@str, from_io(chunk_size: 200))
48
52
 
49
- assert_equal(@str[0...20], collector(@obj.source_from_io(@io, length: 20, chunk_size: 100)))
50
- assert_equal(@str[20...40], collector(@obj.source_from_io(@io, pos: 20, length: 20, chunk_size: 100)))
51
- assert_equal(@str[20...40], collector(@obj.source_from_io(@io, pos: 20, length: 20, chunk_size: 5)))
53
+ assert_equal(@str[0...20], from_io(length: 20, chunk_size: 100))
54
+ assert_equal(@str[20...40], from_io(pos: 20, length: 20, chunk_size: 100))
55
+ assert_equal(@str[20...40], from_io(pos: 20, length: 20, chunk_size: 5))
52
56
  end
53
57
 
54
58
  it "fails if not all requested bytes could be read" do
55
- assert_raises(HexaPDF::FilterError) do
56
- collector(@obj.source_from_io(@io, length: 200))
57
- end
59
+ assert_raises(HexaPDF::FilterError) { from_io(length: 200) }
58
60
  end
59
61
  end
60
62
 
@@ -69,21 +71,23 @@ describe HexaPDF::Filter do
69
71
  @file.unlink
70
72
  end
71
73
 
74
+ def from_file(**opts)
75
+ @obj.source_from_file(@file.path, **opts)
76
+ end
77
+
72
78
  it "converts the file into a source fiber" do
73
- assert_equal(@str, collector(@obj.source_from_file(@file.path)))
74
- assert_equal(@file.size, @obj.source_from_file(@file.path).length)
79
+ assert_equal(@str, collector(from_file))
80
+ assert_equal(@file.size, from_file.length)
75
81
 
76
- assert_equal(@str[100..-1], collector(@obj.source_from_file(@file.path, pos: 100)))
77
- assert_equal(@str[100..-1].length, @obj.source_from_file(@file.path, pos: 100).length)
82
+ assert_equal(@str[100..-1], collector(from_file(pos: 100)))
83
+ assert_equal(@str[100..-1].length, from_file(pos: 100).length)
78
84
 
79
- assert_equal(@str[50...100], collector(@obj.source_from_file(@file.path, pos: 50, length: 50)))
80
- assert_equal(50, @obj.source_from_file(@file.path, length: 50).length)
85
+ assert_equal(@str[50..99], collector(from_file(pos: 50, length: 50)))
86
+ assert_equal(50, from_file(length: 50).length)
81
87
  end
82
88
 
83
89
  it "fails if more bytes are requested than stored in the file" do
84
- assert_raises(HexaPDF::FilterError) do
85
- collector(@obj.source_from_file(@file.path, length: 200))
86
- end
90
+ assert_raises(HexaPDF::FilterError) { collector(from_file(length: 200)) }
87
91
  end
88
92
  end
89
93
 
@@ -4,6 +4,14 @@ require 'test_helper'
4
4
  require 'hexapdf/importer'
5
5
  require 'hexapdf/document'
6
6
 
7
+ describe HexaPDF::Importer::NullableWeakRef do
8
+ it "returns nil instead of an error when the referred-to object is GCed" do
9
+ obj = HexaPDF::Importer::NullableWeakRef.new(Object.new)
10
+ GC.start
11
+ assert_equal("", obj.to_s)
12
+ end
13
+ end
14
+
7
15
  describe HexaPDF::Importer do
8
16
  before do
9
17
  @source = HexaPDF::Document.new
@@ -63,6 +71,12 @@ describe HexaPDF::Importer do
63
71
  assert_equal(["one", "two"], @obj[:array])
64
72
  end
65
73
 
74
+ it "duplicates the stream if it is a string" do
75
+ src_obj = @source.add({}, stream: 'data')
76
+ dst_obj = @importer.import(src_obj)
77
+ refute_same(dst_obj.data.stream, src_obj.data.stream)
78
+ end
79
+
66
80
  it "does not import objects of type Catalog or Pages" do
67
81
  @obj[:catalog] = @source.catalog
68
82
  @obj[:pages] = @source.catalog.pages
@@ -91,6 +91,11 @@ describe HexaPDF::Object do
91
91
  end
92
92
  end
93
93
 
94
+ it "returns the document or raises an error if none is set" do
95
+ assert_equal(:document, HexaPDF::Object.new(nil, document: :document).document)
96
+ assert_raises(HexaPDF::Error) { HexaPDF::Object.new(nil).document }
97
+ end
98
+
94
99
  describe "null?" do
95
100
  it "works for nil values" do
96
101
  assert(HexaPDF::Object.new(nil).null?)
@@ -105,7 +110,7 @@ describe HexaPDF::Object do
105
110
  invoked[:method] = true
106
111
  block.call("error", true)
107
112
  end
108
- assert(obj.validate {|*a| invoked[:block] = a})
113
+ assert(obj.validate {|*a| invoked[:block] = a })
109
114
  assert_equal([:method, :block], invoked.keys)
110
115
  assert_equal(["error", true], invoked[:block])
111
116
 
@@ -120,7 +125,7 @@ describe HexaPDF::Object do
120
125
  block.call("error", false)
121
126
  invoked[:after] = true
122
127
  end
123
- refute(obj.validate {|*a| invoked[:block] = a})
128
+ refute(obj.validate {|*a| invoked[:block] = a })
124
129
  refute(invoked.key?(:after))
125
130
  end
126
131
  end
@@ -150,11 +155,12 @@ describe HexaPDF::Object do
150
155
  assert_equal(:two, hash[HexaPDF::Object.new(:data, oid: 2)])
151
156
  end
152
157
 
153
- it "can be sorted together with Reference objects" do
158
+ it "is sortable w.r.t to other objects implementing #oid and #gen, like Reference" do
154
159
  a = HexaPDF::Object.new(:data, oid: 1)
155
160
  b = HexaPDF::Object.new(:data, oid: 1, gen: 1)
156
161
  c = HexaPDF::Reference.new(5, 7)
157
162
  assert_equal([a, b, c], [b, c, a].sort)
163
+ assert_nil(HexaPDF::Object.new(:data, oid: 1) <=> 5)
158
164
  end
159
165
 
160
166
  describe "deep_copy" do
@@ -165,12 +171,18 @@ describe HexaPDF::Object do
165
171
  assert_equal(copy.value, obj.value)
166
172
  refute_same(copy.value[:a], obj.value[:a])
167
173
  end
174
+
175
+ it "duplicates the stream if it is a string" do
176
+ obj = HexaPDF::Object.new(nil, stream: "data")
177
+ copy = obj.deep_copy
178
+ refute_same(copy.data.stream, obj.data.stream)
179
+ end
168
180
  end
169
181
 
170
182
  describe "validation" do
171
183
  before do
172
184
  @doc = Object.new
173
- @doc.define_singleton_method(:add) {|obj| obj.oid = 1}
185
+ @doc.define_singleton_method(:add) {|obj| obj.oid = 1 }
174
186
  end
175
187
 
176
188
  it "validates that the object is indirect if it must be indirect" do