hexapdf 0.17.1 → 0.17.2

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 (255) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1024 -0
  3. data/LICENSE +29 -0
  4. data/README.md +129 -0
  5. data/Rakefile +109 -0
  6. data/agpl-3.0.txt +661 -0
  7. data/examples/001-hello_world.rb +16 -0
  8. data/examples/002-graphics.rb +275 -0
  9. data/examples/003-arcs.rb +50 -0
  10. data/examples/004-optimizing.rb +23 -0
  11. data/examples/005-merging.rb +27 -0
  12. data/examples/006-standard_pdf_fonts.rb +73 -0
  13. data/examples/007-truetype.rb +42 -0
  14. data/examples/008-show_char_bboxes.rb +55 -0
  15. data/examples/009-text_layouter_alignment.rb +47 -0
  16. data/examples/010-text_layouter_inline_boxes.rb +64 -0
  17. data/examples/011-text_layouter_line_wrapping.rb +57 -0
  18. data/examples/012-text_layouter_styling.rb +122 -0
  19. data/examples/013-text_layouter_shapes.rb +176 -0
  20. data/examples/014-text_in_polygon.rb +60 -0
  21. data/examples/015-boxes.rb +76 -0
  22. data/examples/016-frame_automatic_box_placement.rb +90 -0
  23. data/examples/017-frame_text_flow.rb +60 -0
  24. data/examples/018-composer.rb +44 -0
  25. data/examples/019-acro_form.rb +88 -0
  26. data/examples/emoji-smile.png +0 -0
  27. data/examples/emoji-wink.png +0 -0
  28. data/examples/machupicchu.jpg +0 -0
  29. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -0
  30. data/lib/hexapdf/content/graphic_object/geom2d.rb +13 -0
  31. data/lib/hexapdf/version.rb +1 -1
  32. data/test/data/aes-test-vectors/CBCGFSbox-128-decrypt.data.gz +0 -0
  33. data/test/data/aes-test-vectors/CBCGFSbox-128-encrypt.data.gz +0 -0
  34. data/test/data/aes-test-vectors/CBCGFSbox-192-decrypt.data.gz +0 -0
  35. data/test/data/aes-test-vectors/CBCGFSbox-192-encrypt.data.gz +0 -0
  36. data/test/data/aes-test-vectors/CBCGFSbox-256-decrypt.data.gz +0 -0
  37. data/test/data/aes-test-vectors/CBCGFSbox-256-encrypt.data.gz +0 -0
  38. data/test/data/aes-test-vectors/CBCKeySbox-128-decrypt.data.gz +0 -0
  39. data/test/data/aes-test-vectors/CBCKeySbox-128-encrypt.data.gz +0 -0
  40. data/test/data/aes-test-vectors/CBCKeySbox-192-decrypt.data.gz +0 -0
  41. data/test/data/aes-test-vectors/CBCKeySbox-192-encrypt.data.gz +0 -0
  42. data/test/data/aes-test-vectors/CBCKeySbox-256-decrypt.data.gz +0 -0
  43. data/test/data/aes-test-vectors/CBCKeySbox-256-encrypt.data.gz +0 -0
  44. data/test/data/aes-test-vectors/CBCVarKey-128-decrypt.data.gz +0 -0
  45. data/test/data/aes-test-vectors/CBCVarKey-128-encrypt.data.gz +0 -0
  46. data/test/data/aes-test-vectors/CBCVarKey-192-decrypt.data.gz +0 -0
  47. data/test/data/aes-test-vectors/CBCVarKey-192-encrypt.data.gz +0 -0
  48. data/test/data/aes-test-vectors/CBCVarKey-256-decrypt.data.gz +0 -0
  49. data/test/data/aes-test-vectors/CBCVarKey-256-encrypt.data.gz +0 -0
  50. data/test/data/aes-test-vectors/CBCVarTxt-128-decrypt.data.gz +0 -0
  51. data/test/data/aes-test-vectors/CBCVarTxt-128-encrypt.data.gz +0 -0
  52. data/test/data/aes-test-vectors/CBCVarTxt-192-decrypt.data.gz +0 -0
  53. data/test/data/aes-test-vectors/CBCVarTxt-192-encrypt.data.gz +0 -0
  54. data/test/data/aes-test-vectors/CBCVarTxt-256-decrypt.data.gz +0 -0
  55. data/test/data/aes-test-vectors/CBCVarTxt-256-encrypt.data.gz +0 -0
  56. data/test/data/fonts/Ubuntu-Title.ttf +0 -0
  57. data/test/data/images/cmyk.jpg +0 -0
  58. data/test/data/images/fillbytes.jpg +0 -0
  59. data/test/data/images/gray.jpg +0 -0
  60. data/test/data/images/greyscale-1bit.png +0 -0
  61. data/test/data/images/greyscale-2bit.png +0 -0
  62. data/test/data/images/greyscale-4bit.png +0 -0
  63. data/test/data/images/greyscale-8bit.png +0 -0
  64. data/test/data/images/greyscale-alpha-8bit.png +0 -0
  65. data/test/data/images/greyscale-trns-8bit.png +0 -0
  66. data/test/data/images/greyscale-with-gamma1.0.png +0 -0
  67. data/test/data/images/greyscale-with-gamma1.5.png +0 -0
  68. data/test/data/images/indexed-1bit.png +0 -0
  69. data/test/data/images/indexed-2bit.png +0 -0
  70. data/test/data/images/indexed-4bit.png +0 -0
  71. data/test/data/images/indexed-8bit.png +0 -0
  72. data/test/data/images/indexed-alpha-4bit.png +0 -0
  73. data/test/data/images/indexed-alpha-8bit.png +0 -0
  74. data/test/data/images/rgb.jpg +0 -0
  75. data/test/data/images/truecolour-8bit.png +0 -0
  76. data/test/data/images/truecolour-alpha-8bit.png +0 -0
  77. data/test/data/images/truecolour-gama-chrm-8bit.png +0 -0
  78. data/test/data/images/truecolour-srgb-8bit.png +0 -0
  79. data/test/data/images/ycck.jpg +0 -0
  80. data/test/data/minimal.pdf +44 -0
  81. data/test/data/standard-security-handler/README +9 -0
  82. data/test/data/standard-security-handler/bothpwd-aes-128bit-V4.pdf +44 -0
  83. data/test/data/standard-security-handler/bothpwd-aes-256bit-V5.pdf +0 -0
  84. data/test/data/standard-security-handler/bothpwd-arc4-128bit-V2.pdf +43 -0
  85. data/test/data/standard-security-handler/bothpwd-arc4-128bit-V4.pdf +43 -0
  86. data/test/data/standard-security-handler/bothpwd-arc4-40bit-V1.pdf +0 -0
  87. data/test/data/standard-security-handler/nopwd-aes-128bit-V4.pdf +43 -0
  88. data/test/data/standard-security-handler/nopwd-aes-256bit-V5.pdf +0 -0
  89. data/test/data/standard-security-handler/nopwd-arc4-128bit-V2.pdf +43 -0
  90. data/test/data/standard-security-handler/nopwd-arc4-128bit-V4.pdf +43 -0
  91. data/test/data/standard-security-handler/nopwd-arc4-40bit-V1.pdf +43 -0
  92. data/test/data/standard-security-handler/ownerpwd-aes-128bit-V4.pdf +0 -0
  93. data/test/data/standard-security-handler/ownerpwd-aes-256bit-V5.pdf +43 -0
  94. data/test/data/standard-security-handler/ownerpwd-arc4-128bit-V2.pdf +43 -0
  95. data/test/data/standard-security-handler/ownerpwd-arc4-128bit-V4.pdf +43 -0
  96. data/test/data/standard-security-handler/ownerpwd-arc4-40bit-V1.pdf +43 -0
  97. data/test/data/standard-security-handler/userpwd-aes-128bit-V4.pdf +43 -0
  98. data/test/data/standard-security-handler/userpwd-aes-256bit-V5.pdf +43 -0
  99. data/test/data/standard-security-handler/userpwd-arc4-128bit-V2.pdf +0 -0
  100. data/test/data/standard-security-handler/userpwd-arc4-128bit-V4.pdf +0 -0
  101. data/test/data/standard-security-handler/userpwd-arc4-40bit-V1.pdf +43 -0
  102. data/test/hexapdf/common_tokenizer_tests.rb +236 -0
  103. data/test/hexapdf/content/common.rb +39 -0
  104. data/test/hexapdf/content/graphic_object/test_arc.rb +102 -0
  105. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +90 -0
  106. data/test/hexapdf/content/graphic_object/test_geom2d.rb +79 -0
  107. data/test/hexapdf/content/graphic_object/test_solid_arc.rb +86 -0
  108. data/test/hexapdf/content/test_canvas.rb +1279 -0
  109. data/test/hexapdf/content/test_color_space.rb +176 -0
  110. data/test/hexapdf/content/test_graphics_state.rb +151 -0
  111. data/test/hexapdf/content/test_operator.rb +619 -0
  112. data/test/hexapdf/content/test_parser.rb +99 -0
  113. data/test/hexapdf/content/test_processor.rb +163 -0
  114. data/test/hexapdf/content/test_transformation_matrix.rb +64 -0
  115. data/test/hexapdf/document/test_files.rb +72 -0
  116. data/test/hexapdf/document/test_fonts.rb +60 -0
  117. data/test/hexapdf/document/test_images.rb +72 -0
  118. data/test/hexapdf/document/test_pages.rb +130 -0
  119. data/test/hexapdf/encryption/common.rb +87 -0
  120. data/test/hexapdf/encryption/test_aes.rb +129 -0
  121. data/test/hexapdf/encryption/test_arc4.rb +39 -0
  122. data/test/hexapdf/encryption/test_fast_aes.rb +17 -0
  123. data/test/hexapdf/encryption/test_fast_arc4.rb +12 -0
  124. data/test/hexapdf/encryption/test_identity.rb +21 -0
  125. data/test/hexapdf/encryption/test_ruby_aes.rb +23 -0
  126. data/test/hexapdf/encryption/test_ruby_arc4.rb +20 -0
  127. data/test/hexapdf/encryption/test_security_handler.rb +380 -0
  128. data/test/hexapdf/encryption/test_standard_security_handler.rb +322 -0
  129. data/test/hexapdf/filter/common.rb +53 -0
  130. data/test/hexapdf/filter/test_ascii85_decode.rb +59 -0
  131. data/test/hexapdf/filter/test_ascii_hex_decode.rb +38 -0
  132. data/test/hexapdf/filter/test_crypt.rb +21 -0
  133. data/test/hexapdf/filter/test_encryption.rb +24 -0
  134. data/test/hexapdf/filter/test_flate_decode.rb +44 -0
  135. data/test/hexapdf/filter/test_lzw_decode.rb +52 -0
  136. data/test/hexapdf/filter/test_predictor.rb +219 -0
  137. data/test/hexapdf/filter/test_run_length_decode.rb +32 -0
  138. data/test/hexapdf/font/cmap/test_parser.rb +102 -0
  139. data/test/hexapdf/font/cmap/test_writer.rb +66 -0
  140. data/test/hexapdf/font/encoding/test_base.rb +45 -0
  141. data/test/hexapdf/font/encoding/test_difference_encoding.rb +29 -0
  142. data/test/hexapdf/font/encoding/test_glyph_list.rb +59 -0
  143. data/test/hexapdf/font/encoding/test_zapf_dingbats_encoding.rb +16 -0
  144. data/test/hexapdf/font/test_cmap.rb +104 -0
  145. data/test/hexapdf/font/test_encoding.rb +27 -0
  146. data/test/hexapdf/font/test_invalid_glyph.rb +34 -0
  147. data/test/hexapdf/font/test_true_type_wrapper.rb +186 -0
  148. data/test/hexapdf/font/test_type1_wrapper.rb +107 -0
  149. data/test/hexapdf/font/true_type/common.rb +17 -0
  150. data/test/hexapdf/font/true_type/table/common.rb +27 -0
  151. data/test/hexapdf/font/true_type/table/test_cmap.rb +47 -0
  152. data/test/hexapdf/font/true_type/table/test_cmap_subtable.rb +141 -0
  153. data/test/hexapdf/font/true_type/table/test_directory.rb +30 -0
  154. data/test/hexapdf/font/true_type/table/test_glyf.rb +58 -0
  155. data/test/hexapdf/font/true_type/table/test_head.rb +56 -0
  156. data/test/hexapdf/font/true_type/table/test_hhea.rb +26 -0
  157. data/test/hexapdf/font/true_type/table/test_hmtx.rb +30 -0
  158. data/test/hexapdf/font/true_type/table/test_kern.rb +61 -0
  159. data/test/hexapdf/font/true_type/table/test_loca.rb +33 -0
  160. data/test/hexapdf/font/true_type/table/test_maxp.rb +50 -0
  161. data/test/hexapdf/font/true_type/table/test_name.rb +76 -0
  162. data/test/hexapdf/font/true_type/table/test_os2.rb +55 -0
  163. data/test/hexapdf/font/true_type/table/test_post.rb +78 -0
  164. data/test/hexapdf/font/true_type/test_builder.rb +42 -0
  165. data/test/hexapdf/font/true_type/test_font.rb +116 -0
  166. data/test/hexapdf/font/true_type/test_optimizer.rb +26 -0
  167. data/test/hexapdf/font/true_type/test_subsetter.rb +73 -0
  168. data/test/hexapdf/font/true_type/test_table.rb +48 -0
  169. data/test/hexapdf/font/type1/common.rb +6 -0
  170. data/test/hexapdf/font/type1/test_afm_parser.rb +65 -0
  171. data/test/hexapdf/font/type1/test_font.rb +104 -0
  172. data/test/hexapdf/font/type1/test_font_metrics.rb +22 -0
  173. data/test/hexapdf/font/type1/test_pfb_parser.rb +37 -0
  174. data/test/hexapdf/font_loader/test_from_configuration.rb +43 -0
  175. data/test/hexapdf/font_loader/test_from_file.rb +36 -0
  176. data/test/hexapdf/font_loader/test_standard14.rb +33 -0
  177. data/test/hexapdf/image_loader/test_jpeg.rb +93 -0
  178. data/test/hexapdf/image_loader/test_pdf.rb +47 -0
  179. data/test/hexapdf/image_loader/test_png.rb +259 -0
  180. data/test/hexapdf/layout/test_box.rb +154 -0
  181. data/test/hexapdf/layout/test_frame.rb +350 -0
  182. data/test/hexapdf/layout/test_image_box.rb +73 -0
  183. data/test/hexapdf/layout/test_inline_box.rb +71 -0
  184. data/test/hexapdf/layout/test_line.rb +206 -0
  185. data/test/hexapdf/layout/test_style.rb +790 -0
  186. data/test/hexapdf/layout/test_text_box.rb +140 -0
  187. data/test/hexapdf/layout/test_text_fragment.rb +375 -0
  188. data/test/hexapdf/layout/test_text_layouter.rb +758 -0
  189. data/test/hexapdf/layout/test_text_shaper.rb +62 -0
  190. data/test/hexapdf/layout/test_width_from_polygon.rb +109 -0
  191. data/test/hexapdf/task/test_dereference.rb +51 -0
  192. data/test/hexapdf/task/test_optimize.rb +162 -0
  193. data/test/hexapdf/test_composer.rb +258 -0
  194. data/test/hexapdf/test_configuration.rb +93 -0
  195. data/test/hexapdf/test_data_dir.rb +32 -0
  196. data/test/hexapdf/test_dictionary.rb +340 -0
  197. data/test/hexapdf/test_dictionary_fields.rb +269 -0
  198. data/test/hexapdf/test_document.rb +641 -0
  199. data/test/hexapdf/test_filter.rb +100 -0
  200. data/test/hexapdf/test_importer.rb +106 -0
  201. data/test/hexapdf/test_object.rb +258 -0
  202. data/test/hexapdf/test_parser.rb +645 -0
  203. data/test/hexapdf/test_pdf_array.rb +169 -0
  204. data/test/hexapdf/test_rectangle.rb +73 -0
  205. data/test/hexapdf/test_reference.rb +50 -0
  206. data/test/hexapdf/test_revision.rb +188 -0
  207. data/test/hexapdf/test_revisions.rb +196 -0
  208. data/test/hexapdf/test_serializer.rb +195 -0
  209. data/test/hexapdf/test_stream.rb +274 -0
  210. data/test/hexapdf/test_tokenizer.rb +80 -0
  211. data/test/hexapdf/test_type.rb +18 -0
  212. data/test/hexapdf/test_writer.rb +140 -0
  213. data/test/hexapdf/test_xref_section.rb +61 -0
  214. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +795 -0
  215. data/test/hexapdf/type/acro_form/test_button_field.rb +308 -0
  216. data/test/hexapdf/type/acro_form/test_choice_field.rb +220 -0
  217. data/test/hexapdf/type/acro_form/test_field.rb +259 -0
  218. data/test/hexapdf/type/acro_form/test_form.rb +357 -0
  219. data/test/hexapdf/type/acro_form/test_signature_field.rb +38 -0
  220. data/test/hexapdf/type/acro_form/test_text_field.rb +201 -0
  221. data/test/hexapdf/type/acro_form/test_variable_text_field.rb +88 -0
  222. data/test/hexapdf/type/actions/test_launch.rb +24 -0
  223. data/test/hexapdf/type/actions/test_uri.rb +23 -0
  224. data/test/hexapdf/type/annotations/test_markup_annotation.rb +22 -0
  225. data/test/hexapdf/type/annotations/test_text.rb +34 -0
  226. data/test/hexapdf/type/annotations/test_widget.rb +225 -0
  227. data/test/hexapdf/type/test_annotation.rb +97 -0
  228. data/test/hexapdf/type/test_catalog.rb +48 -0
  229. data/test/hexapdf/type/test_cid_font.rb +61 -0
  230. data/test/hexapdf/type/test_file_specification.rb +141 -0
  231. data/test/hexapdf/type/test_font.rb +67 -0
  232. data/test/hexapdf/type/test_font_descriptor.rb +61 -0
  233. data/test/hexapdf/type/test_font_simple.rb +176 -0
  234. data/test/hexapdf/type/test_font_true_type.rb +31 -0
  235. data/test/hexapdf/type/test_font_type0.rb +120 -0
  236. data/test/hexapdf/type/test_font_type1.rb +142 -0
  237. data/test/hexapdf/type/test_font_type3.rb +26 -0
  238. data/test/hexapdf/type/test_form.rb +120 -0
  239. data/test/hexapdf/type/test_image.rb +261 -0
  240. data/test/hexapdf/type/test_info.rb +9 -0
  241. data/test/hexapdf/type/test_object_stream.rb +117 -0
  242. data/test/hexapdf/type/test_page.rb +598 -0
  243. data/test/hexapdf/type/test_page_tree_node.rb +315 -0
  244. data/test/hexapdf/type/test_resources.rb +209 -0
  245. data/test/hexapdf/type/test_trailer.rb +116 -0
  246. data/test/hexapdf/type/test_xref_stream.rb +143 -0
  247. data/test/hexapdf/utils/test_bit_field.rb +63 -0
  248. data/test/hexapdf/utils/test_bit_stream.rb +69 -0
  249. data/test/hexapdf/utils/test_graphics_helpers.rb +37 -0
  250. data/test/hexapdf/utils/test_lru_cache.rb +22 -0
  251. data/test/hexapdf/utils/test_object_hash.rb +120 -0
  252. data/test/hexapdf/utils/test_pdf_doc_encoding.rb +18 -0
  253. data/test/hexapdf/utils/test_sorted_tree_node.rb +239 -0
  254. data/test/test_helper.rb +58 -0
  255. metadata +263 -3
@@ -0,0 +1,100 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/filter'
5
+ require 'stringio'
6
+ require 'tempfile'
7
+
8
+ describe HexaPDF::Filter do
9
+ before do
10
+ @obj = HexaPDF::Filter
11
+ @str = ''
12
+ 40.times { @str << [rand(2**32)].pack('N') }
13
+ end
14
+
15
+ describe "source_from_string" do
16
+ it "doesn't modify the given string" do
17
+ str = @str.dup
18
+ @obj.source_from_string(@str).resume.slice!(0, 10)
19
+ assert_equal(str, @str)
20
+ end
21
+
22
+ it "returns the whole string" do
23
+ assert_equal(@str, collector(@obj.source_from_string(@str)))
24
+ end
25
+ end
26
+
27
+ describe "source_from_io" do
28
+ before do
29
+ @io = StringIO.new(@str.dup)
30
+ end
31
+
32
+ def from_io(**opts)
33
+ collector(@obj.source_from_io(@io, **opts))
34
+ end
35
+
36
+ it "converts an IO into a source via #source_from_io" do
37
+ assert_equal(@str, from_io)
38
+
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))
42
+
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))
46
+ assert_equal(100, @obj.source_from_io(@io, length: 100).length)
47
+
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))
52
+
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))
56
+ end
57
+
58
+ it "fails if not all requested bytes could be read" do
59
+ assert_raises(HexaPDF::FilterError) { from_io(length: 200) }
60
+ end
61
+ end
62
+
63
+ describe "source_from_file" do
64
+ before do
65
+ @file = Tempfile.new('hexapdf-filter')
66
+ @file.write(@str)
67
+ @file.close
68
+ end
69
+
70
+ after do
71
+ @file.unlink
72
+ end
73
+
74
+ def from_file(**opts)
75
+ @obj.source_from_file(@file.path, **opts)
76
+ end
77
+
78
+ it "converts the file into a source fiber" do
79
+ assert_equal(@str, collector(from_file))
80
+ assert_equal(@file.size, from_file.length)
81
+
82
+ assert_equal(@str[100..-1], collector(from_file(pos: 100)))
83
+ assert_equal(@str[100..-1].length, from_file(pos: 100).length)
84
+
85
+ assert_equal(@str[50..99], collector(from_file(pos: 50, length: 50)))
86
+ assert_equal(50, from_file(length: 50).length)
87
+ end
88
+
89
+ it "fails if more bytes are requested than stored in the file" do
90
+ assert_raises(HexaPDF::FilterError) { collector(from_file(length: 200)) }
91
+ end
92
+ end
93
+
94
+ it "collects the binary string from a source via #string_from_source" do
95
+ source = @obj.source_from_io(StringIO.new(@str), chunk_size: 50)
96
+ result = @obj.string_from_source(source)
97
+ assert_equal(@str, result)
98
+ assert_equal(Encoding::BINARY, result.encoding)
99
+ end
100
+ end
@@ -0,0 +1,106 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/importer'
5
+ require 'hexapdf/document'
6
+
7
+ describe HexaPDF::Importer::NullableWeakRef do
8
+ it "returns nil instead of an error when the referred-to object is GCed" do
9
+ refs = []
10
+ obj = nil
11
+ 100.times do
12
+ refs << HexaPDF::Importer::NullableWeakRef.new(Object.new)
13
+ ObjectSpace.garbage_collect
14
+ ObjectSpace.garbage_collect
15
+ break if (obj = refs.find {|ref| !ref.weakref_alive? })
16
+ end
17
+ assert_equal("", obj.to_s)
18
+ end
19
+ end
20
+
21
+ describe HexaPDF::Importer do
22
+ before do
23
+ @source = HexaPDF::Document.new
24
+ obj = @source.add("test")
25
+ @hash = @source.wrap({key: "value"})
26
+ @obj = @source.add({hash: @hash, array: ["one", "two"],
27
+ ref: HexaPDF::Reference.new(obj.oid, obj.gen),
28
+ others: [:symbol, 5, 5.5, nil, true, false]})
29
+ @source.pages.add
30
+ @source.pages.root[:Rotate] = 90
31
+ @dest = HexaPDF::Document.new
32
+ @importer = HexaPDF::Importer.for(source: @source, destination: @dest)
33
+ end
34
+
35
+ describe "::for" do
36
+ it "caches the importer" do
37
+ assert_same(@importer, HexaPDF::Importer.for(source: @source, destination: @dest))
38
+ end
39
+ end
40
+
41
+ describe "import" do
42
+ it "updates the associated document" do
43
+ obj = @importer.import(@obj)
44
+ assert_same(obj.document, @dest)
45
+ obj = @importer.import(@hash)
46
+ assert_same(obj.document, @dest)
47
+ end
48
+
49
+ it "imports an object only once" do
50
+ obj = @importer.import(@obj)
51
+ assert_same(obj, @importer.import(@obj))
52
+ assert_equal(2, @dest.each.to_a.size)
53
+ end
54
+
55
+ it "re-imports an object that was imported but then deleted" do
56
+ obj = @importer.import(@obj)
57
+ @dest.delete(obj)
58
+ refute_same(obj, @importer.import(@obj))
59
+ end
60
+
61
+ it "can import a direct object" do
62
+ obj = @importer.import(key: @obj)
63
+ assert(@dest.object?(obj[:key]))
64
+ end
65
+
66
+ it "copies the data of the imported objects" do
67
+ data = {key: @obj, str: "str"}
68
+ obj = @importer.import(data)
69
+ obj[:str].upcase!
70
+ obj[:key][:hash][:key].upcase!
71
+ obj[:key][:hash][:data] = :value
72
+ obj[:key][:array].unshift
73
+ obj[:key][:array][0].upcase!
74
+
75
+ assert_equal("str", data[:str])
76
+ assert_equal("value", @obj[:hash][:key])
77
+ assert_equal(["one", "two"], @obj[:array])
78
+ end
79
+
80
+ it "duplicates the stream if it is a string" do
81
+ src_obj = @source.add({}, stream: 'data')
82
+ dst_obj = @importer.import(src_obj)
83
+ refute_same(dst_obj.data.stream, src_obj.data.stream)
84
+ end
85
+
86
+ it "does not import objects of type Catalog or Pages" do
87
+ @obj[:catalog] = @source.catalog
88
+ @obj[:pages] = @source.catalog.pages
89
+ obj = @importer.import(@obj)
90
+
91
+ assert_nil(obj[:catalog])
92
+ assert_nil(obj[:pages])
93
+ end
94
+
95
+ it "imports Page objects correctly by copying the inherited values" do
96
+ page = @importer.import(@source.pages[0])
97
+ assert_equal(90, page[:Rotate])
98
+ end
99
+
100
+ it "raise an error if the given object doesn't belong to the source document" do
101
+ other_doc = HexaPDF::Document.new
102
+ other_obj = other_doc.add("test")
103
+ assert_raises(HexaPDF::Error) { @importer.import(other_obj) }
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,258 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/object'
5
+ require 'hexapdf/reference'
6
+ require 'hexapdf/document'
7
+
8
+ describe HexaPDF::Object do
9
+ describe "class.deep_copy" do
10
+ it "handles general, duplicatable classes" do
11
+ x = "test"
12
+ assert_equal("test", HexaPDF::Object.deep_copy(x))
13
+ refute_same(x, HexaPDF::Object.deep_copy(x))
14
+ end
15
+
16
+ it "handles arrays" do
17
+ x = [5, 6, [1, 2, 3]]
18
+ y = HexaPDF::Object.deep_copy(x)
19
+ x[2][0] = 4
20
+ assert_equal([5, 6, [1, 2, 3]], y)
21
+ end
22
+
23
+ it "handles hashes" do
24
+ x = {a: 5, b: 6, c: {a: 1, b: 2}}
25
+ y = HexaPDF::Object.deep_copy(x)
26
+ x[:c][:a] = 4
27
+ assert_equal({a: 5, b: 6, c: {a: 1, b: 2}}, y)
28
+ end
29
+
30
+ it "handles PDF references" do
31
+ x = HexaPDF::Reference.new(1, 2)
32
+ assert_same(x, HexaPDF::Object.deep_copy(x))
33
+ end
34
+
35
+ it "handles PDF objects" do
36
+ x = HexaPDF::Object.new("test")
37
+ assert_equal("test", HexaPDF::Object.deep_copy(x))
38
+
39
+ x.must_be_indirect = true
40
+ assert_same(x, HexaPDF::Object.deep_copy(x))
41
+
42
+ x.must_be_indirect = false
43
+ x.oid = 1
44
+ assert_same(x, HexaPDF::Object.deep_copy(x))
45
+ end
46
+ end
47
+
48
+ describe "initialize" do
49
+ it "uses a simple value as is" do
50
+ obj = HexaPDF::Object.new(5)
51
+ assert_equal(5, obj.value)
52
+ end
53
+
54
+ it "reuses the data object of a HexaPDF::Object" do
55
+ obj = HexaPDF::Object.new(5)
56
+ assert_same(obj.data, HexaPDF::Object.new(obj).data)
57
+ end
58
+
59
+ it "uses a provided PDFData structure" do
60
+ obj = HexaPDF::PDFData.new(5)
61
+ assert_equal(obj, HexaPDF::Object.new(obj).data)
62
+ end
63
+ end
64
+
65
+ describe "getters and setters" do
66
+ before do
67
+ @obj = HexaPDF::Object.new(5)
68
+ end
69
+
70
+ it "can get/set oid" do
71
+ @obj.oid = 7
72
+ assert_equal(7, @obj.oid)
73
+ end
74
+
75
+ it "can get/set gen" do
76
+ @obj.gen = 7
77
+ assert_equal(7, @obj.gen)
78
+ end
79
+
80
+ it "can get/set the value" do
81
+ @obj.value = :test
82
+ assert_equal(:test, @obj.value)
83
+ end
84
+ end
85
+
86
+ it "returns the document or raises an error if none is set" do
87
+ assert_equal(:document, HexaPDF::Object.new(nil, document: :document).document)
88
+ assert_raises(HexaPDF::Error) { HexaPDF::Object.new(nil).document }
89
+ end
90
+
91
+ describe "null?" do
92
+ it "works for nil values" do
93
+ assert(HexaPDF::Object.new(nil).null?)
94
+ end
95
+ end
96
+
97
+ describe "validate" do
98
+ before do
99
+ @obj = HexaPDF::Object.new(5)
100
+ end
101
+
102
+ it "invokes perform_validation correctly" do
103
+ invoked = false
104
+ @obj.define_singleton_method(:perform_validation) { invoked = true }
105
+ assert(@obj.validate)
106
+ assert(invoked)
107
+ end
108
+
109
+ it "yields all arguments yieled by perform_validation" do
110
+ invoked = []
111
+ @obj.define_singleton_method(:perform_validation) do |&block|
112
+ block.call("error", true, :object)
113
+ end
114
+ assert(@obj.validate {|*a| invoked << a })
115
+ assert_equal([["error", true, :object]], invoked)
116
+ end
117
+
118
+ it "provides self as third argument if none is yielded by perform_validation" do
119
+ invoked = []
120
+ @obj.define_singleton_method(:perform_validation) do |&block|
121
+ block.call("error", true)
122
+ end
123
+ assert(@obj.validate {|*a| invoked << a })
124
+ assert_equal([["error", true, @obj]], invoked)
125
+ end
126
+
127
+ it "yields all problems when auto_correct is true" do
128
+ invoked = []
129
+ @obj.define_singleton_method(:perform_validation) do |&block|
130
+ invoked << :before
131
+ block.call("error", false)
132
+ invoked << :after
133
+ block.call("error2", true)
134
+ invoked << :last
135
+ end
136
+ refute(@obj.validate)
137
+ assert_equal([:before, :after, :last], invoked)
138
+ end
139
+
140
+ it "stops at the first uncorrectable problem if auto_correct is false" do
141
+ invoked = []
142
+ @obj.define_singleton_method(:perform_validation) do |&block|
143
+ invoked << :before
144
+ block.call("error", false)
145
+ invoked << :after
146
+ end
147
+ refute(@obj.validate(auto_correct: false))
148
+ assert_equal([:before], invoked)
149
+ end
150
+ end
151
+
152
+ it "can represent itself during inspection" do
153
+ obj = HexaPDF::Object.new(5, oid: 5)
154
+ assert_match(/\[5, 0\].*value=5/, obj.inspect)
155
+ end
156
+
157
+ it "can be compared to another object or reference" do
158
+ obj = HexaPDF::Object.new(5, oid: 5)
159
+
160
+ assert_equal(obj, HexaPDF::Object.new(obj))
161
+ refute_equal(obj, HexaPDF::Object.new(5, oid: 5))
162
+ refute_equal(obj, HexaPDF::Object.new(6, oid: 5))
163
+ refute_equal(obj, HexaPDF::Object.new(5, oid: 1))
164
+ refute_equal(obj, HexaPDF::Object.new(5, oid: 5, gen: 1))
165
+
166
+ assert_equal(obj, HexaPDF::Reference.new(5, 0))
167
+ end
168
+
169
+ it "works correctly as hash key, is interchangable in this regard with Reference objects" do
170
+ hash = {}
171
+ hash[HexaPDF::Reference.new(1)] = :one
172
+ hash[HexaPDF::Object.new(:val, oid: 2)] = :two
173
+ assert_equal(:one, hash[HexaPDF::Reference.new(1, 0)])
174
+ assert_equal(:one, hash[HexaPDF::Object.new(:data, oid: 1)])
175
+ assert_equal(:two, hash[HexaPDF::Reference.new(2)])
176
+ assert_equal(:two, hash[HexaPDF::Object.new(:data, oid: 2)])
177
+ end
178
+
179
+ it "is sortable w.r.t to other objects implementing #oid and #gen, like Reference" do
180
+ a = HexaPDF::Object.new(:data, oid: 1)
181
+ b = HexaPDF::Object.new(:data, oid: 1, gen: 1)
182
+ c = HexaPDF::Reference.new(5, 7)
183
+ assert_equal([a, b, c], [b, c, a].sort)
184
+ assert_nil(HexaPDF::Object.new(:data, oid: 1) <=> 5)
185
+ end
186
+
187
+ describe "deep_copy" do
188
+ it "creates an independent object" do
189
+ obj = HexaPDF::Object.new({a: "mystring", b: HexaPDF::Reference.new(1, 0), c: 5})
190
+ copy = obj.deep_copy
191
+ refute_equal(copy, obj)
192
+ assert_equal(copy.value, obj.value)
193
+ refute_same(copy.value[:a], obj.value[:a])
194
+ end
195
+
196
+ it "duplicates the stream if it is a string" do
197
+ obj = HexaPDF::Object.new(nil, stream: "data")
198
+ copy = obj.deep_copy
199
+ refute_same(copy.data.stream, obj.data.stream)
200
+ end
201
+ end
202
+
203
+ describe "caching" do
204
+ before do
205
+ @obj = HexaPDF::Object.new({}, document: HexaPDF::Document.new)
206
+ end
207
+
208
+ it "can set and return a cached value" do
209
+ assert_equal(:value, @obj.cache(:data, :value))
210
+ assert_equal(:value, @obj.cache(:data, :other))
211
+ assert_equal(:value, @obj.cache(:block) { :value })
212
+ assert_equal(:other, @obj.cache(:data, :other, update: true))
213
+ end
214
+
215
+ it "can check for the existence of a cached value" do
216
+ refute(@obj.cached?(:data))
217
+ @obj.cache(:data, :value)
218
+ assert(@obj.cached?(:data))
219
+ end
220
+
221
+ it "can clear all cached values" do
222
+ @obj.cache(:data, :value)
223
+ assert(@obj.cached?(:data))
224
+ @obj.clear_cache
225
+ refute(@obj.cached?(:data))
226
+ end
227
+ end
228
+
229
+ describe "validation" do
230
+ before do
231
+ @doc = Object.new
232
+ @doc.define_singleton_method(:add) {|obj| obj.oid = 1 }
233
+ end
234
+
235
+ it "validates that the object is indirect if it must be indirect" do
236
+ obj = HexaPDF::Object.new(6, document: @doc)
237
+
238
+ obj.validate
239
+ assert_equal(0, obj.oid)
240
+
241
+ obj.must_be_indirect = true
242
+ obj.validate
243
+ assert_equal(1, obj.oid)
244
+ end
245
+
246
+ it "validates collection values" do
247
+ x = HexaPDF::Object.new(:x, document: @doc)
248
+ x.must_be_indirect = true
249
+ y = HexaPDF::Object.new(:y, document: @doc)
250
+ y.must_be_indirect = true
251
+
252
+ obj = HexaPDF::Object.new([1, 2, 3, [4, x], {X: [y, 5]}])
253
+ obj.validate
254
+ assert_equal(1, x.oid)
255
+ assert_equal(1, y.oid)
256
+ end
257
+ end
258
+ end