hexapdf 0.17.1 → 0.17.2

Sign up to get free protection for your applications and to get access to all the features.
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