hexapdf 0.1.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 (346) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTERS +3 -0
  3. data/LICENSE +26 -0
  4. data/README.md +88 -0
  5. data/Rakefile +121 -0
  6. data/VERSION +1 -0
  7. data/agpl-3.0.txt +661 -0
  8. data/bin/hexapdf +6 -0
  9. data/data/hexapdf/afm/Courier-Bold.afm +342 -0
  10. data/data/hexapdf/afm/Courier-BoldOblique.afm +342 -0
  11. data/data/hexapdf/afm/Courier-Oblique.afm +342 -0
  12. data/data/hexapdf/afm/Courier.afm +342 -0
  13. data/data/hexapdf/afm/Helvetica-Bold.afm +2827 -0
  14. data/data/hexapdf/afm/Helvetica-BoldOblique.afm +2827 -0
  15. data/data/hexapdf/afm/Helvetica-Oblique.afm +3051 -0
  16. data/data/hexapdf/afm/Helvetica.afm +3051 -0
  17. data/data/hexapdf/afm/MustRead.html +1 -0
  18. data/data/hexapdf/afm/Symbol.afm +213 -0
  19. data/data/hexapdf/afm/Times-Bold.afm +2588 -0
  20. data/data/hexapdf/afm/Times-BoldItalic.afm +2384 -0
  21. data/data/hexapdf/afm/Times-Italic.afm +2667 -0
  22. data/data/hexapdf/afm/Times-Roman.afm +2419 -0
  23. data/data/hexapdf/afm/ZapfDingbats.afm +225 -0
  24. data/data/hexapdf/encoding/glyphlist.txt +4305 -0
  25. data/data/hexapdf/encoding/zapfdingbats.txt +225 -0
  26. data/examples/arc.rb +50 -0
  27. data/examples/graphics.rb +274 -0
  28. data/examples/hello_world.rb +16 -0
  29. data/examples/machupicchu.jpg +0 -0
  30. data/examples/merging.rb +24 -0
  31. data/examples/optimizing.rb +20 -0
  32. data/examples/show_char_bboxes.rb +55 -0
  33. data/examples/standard_pdf_fonts.rb +72 -0
  34. data/examples/truetype.rb +45 -0
  35. data/lib/hexapdf/cli/extract.rb +128 -0
  36. data/lib/hexapdf/cli/info.rb +121 -0
  37. data/lib/hexapdf/cli/inspect.rb +157 -0
  38. data/lib/hexapdf/cli/modify.rb +218 -0
  39. data/lib/hexapdf/cli.rb +121 -0
  40. data/lib/hexapdf/configuration.rb +392 -0
  41. data/lib/hexapdf/content/canvas.rb +1974 -0
  42. data/lib/hexapdf/content/color_space.rb +364 -0
  43. data/lib/hexapdf/content/graphic_object/arc.rb +267 -0
  44. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +208 -0
  45. data/lib/hexapdf/content/graphic_object/solid_arc.rb +173 -0
  46. data/lib/hexapdf/content/graphic_object.rb +81 -0
  47. data/lib/hexapdf/content/graphics_state.rb +579 -0
  48. data/lib/hexapdf/content/operator.rb +1072 -0
  49. data/lib/hexapdf/content/parser.rb +204 -0
  50. data/lib/hexapdf/content/processor.rb +451 -0
  51. data/lib/hexapdf/content/transformation_matrix.rb +172 -0
  52. data/lib/hexapdf/content.rb +47 -0
  53. data/lib/hexapdf/data_dir.rb +51 -0
  54. data/lib/hexapdf/dictionary.rb +303 -0
  55. data/lib/hexapdf/dictionary_fields.rb +382 -0
  56. data/lib/hexapdf/document.rb +589 -0
  57. data/lib/hexapdf/document_utils.rb +209 -0
  58. data/lib/hexapdf/encryption/aes.rb +206 -0
  59. data/lib/hexapdf/encryption/arc4.rb +93 -0
  60. data/lib/hexapdf/encryption/fast_aes.rb +79 -0
  61. data/lib/hexapdf/encryption/fast_arc4.rb +67 -0
  62. data/lib/hexapdf/encryption/identity.rb +63 -0
  63. data/lib/hexapdf/encryption/ruby_aes.rb +447 -0
  64. data/lib/hexapdf/encryption/ruby_arc4.rb +96 -0
  65. data/lib/hexapdf/encryption/security_handler.rb +494 -0
  66. data/lib/hexapdf/encryption/standard_security_handler.rb +616 -0
  67. data/lib/hexapdf/encryption.rb +94 -0
  68. data/lib/hexapdf/error.rb +73 -0
  69. data/lib/hexapdf/filter/ascii85_decode.rb +160 -0
  70. data/lib/hexapdf/filter/ascii_hex_decode.rb +87 -0
  71. data/lib/hexapdf/filter/dct_decode.rb +57 -0
  72. data/lib/hexapdf/filter/encryption.rb +59 -0
  73. data/lib/hexapdf/filter/flate_decode.rb +93 -0
  74. data/lib/hexapdf/filter/jpx_decode.rb +56 -0
  75. data/lib/hexapdf/filter/lzw_decode.rb +191 -0
  76. data/lib/hexapdf/filter/predictor.rb +266 -0
  77. data/lib/hexapdf/filter/run_length_decode.rb +108 -0
  78. data/lib/hexapdf/filter.rb +176 -0
  79. data/lib/hexapdf/font/cmap/parser.rb +146 -0
  80. data/lib/hexapdf/font/cmap/writer.rb +176 -0
  81. data/lib/hexapdf/font/cmap.rb +90 -0
  82. data/lib/hexapdf/font/encoding/base.rb +77 -0
  83. data/lib/hexapdf/font/encoding/difference_encoding.rb +64 -0
  84. data/lib/hexapdf/font/encoding/glyph_list.rb +150 -0
  85. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +221 -0
  86. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +265 -0
  87. data/lib/hexapdf/font/encoding/standard_encoding.rb +205 -0
  88. data/lib/hexapdf/font/encoding/symbol_encoding.rb +244 -0
  89. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +280 -0
  90. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +250 -0
  91. data/lib/hexapdf/font/encoding.rb +68 -0
  92. data/lib/hexapdf/font/true_type/font.rb +179 -0
  93. data/lib/hexapdf/font/true_type/table/cmap.rb +103 -0
  94. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +384 -0
  95. data/lib/hexapdf/font/true_type/table/directory.rb +92 -0
  96. data/lib/hexapdf/font/true_type/table/glyf.rb +166 -0
  97. data/lib/hexapdf/font/true_type/table/head.rb +143 -0
  98. data/lib/hexapdf/font/true_type/table/hhea.rb +109 -0
  99. data/lib/hexapdf/font/true_type/table/hmtx.rb +79 -0
  100. data/lib/hexapdf/font/true_type/table/loca.rb +79 -0
  101. data/lib/hexapdf/font/true_type/table/maxp.rb +112 -0
  102. data/lib/hexapdf/font/true_type/table/name.rb +218 -0
  103. data/lib/hexapdf/font/true_type/table/os2.rb +200 -0
  104. data/lib/hexapdf/font/true_type/table/post.rb +230 -0
  105. data/lib/hexapdf/font/true_type/table.rb +155 -0
  106. data/lib/hexapdf/font/true_type.rb +48 -0
  107. data/lib/hexapdf/font/true_type_wrapper.rb +240 -0
  108. data/lib/hexapdf/font/type1/afm_parser.rb +230 -0
  109. data/lib/hexapdf/font/type1/character_metrics.rb +67 -0
  110. data/lib/hexapdf/font/type1/font.rb +123 -0
  111. data/lib/hexapdf/font/type1/font_metrics.rb +117 -0
  112. data/lib/hexapdf/font/type1/pfb_parser.rb +71 -0
  113. data/lib/hexapdf/font/type1.rb +52 -0
  114. data/lib/hexapdf/font/type1_wrapper.rb +193 -0
  115. data/lib/hexapdf/font_loader/from_configuration.rb +70 -0
  116. data/lib/hexapdf/font_loader/standard14.rb +98 -0
  117. data/lib/hexapdf/font_loader.rb +85 -0
  118. data/lib/hexapdf/font_utils.rb +89 -0
  119. data/lib/hexapdf/image_loader/jpeg.rb +166 -0
  120. data/lib/hexapdf/image_loader/pdf.rb +89 -0
  121. data/lib/hexapdf/image_loader/png.rb +410 -0
  122. data/lib/hexapdf/image_loader.rb +68 -0
  123. data/lib/hexapdf/importer.rb +139 -0
  124. data/lib/hexapdf/name_tree_node.rb +78 -0
  125. data/lib/hexapdf/number_tree_node.rb +67 -0
  126. data/lib/hexapdf/object.rb +363 -0
  127. data/lib/hexapdf/parser.rb +349 -0
  128. data/lib/hexapdf/rectangle.rb +99 -0
  129. data/lib/hexapdf/reference.rb +98 -0
  130. data/lib/hexapdf/revision.rb +206 -0
  131. data/lib/hexapdf/revisions.rb +194 -0
  132. data/lib/hexapdf/serializer.rb +326 -0
  133. data/lib/hexapdf/stream.rb +279 -0
  134. data/lib/hexapdf/task/dereference.rb +109 -0
  135. data/lib/hexapdf/task/optimize.rb +230 -0
  136. data/lib/hexapdf/task.rb +68 -0
  137. data/lib/hexapdf/tokenizer.rb +406 -0
  138. data/lib/hexapdf/type/catalog.rb +107 -0
  139. data/lib/hexapdf/type/embedded_file.rb +87 -0
  140. data/lib/hexapdf/type/file_specification.rb +232 -0
  141. data/lib/hexapdf/type/font.rb +81 -0
  142. data/lib/hexapdf/type/font_descriptor.rb +109 -0
  143. data/lib/hexapdf/type/font_simple.rb +190 -0
  144. data/lib/hexapdf/type/font_true_type.rb +47 -0
  145. data/lib/hexapdf/type/font_type1.rb +162 -0
  146. data/lib/hexapdf/type/form.rb +103 -0
  147. data/lib/hexapdf/type/graphics_state_parameter.rb +79 -0
  148. data/lib/hexapdf/type/image.rb +73 -0
  149. data/lib/hexapdf/type/info.rb +70 -0
  150. data/lib/hexapdf/type/names.rb +69 -0
  151. data/lib/hexapdf/type/object_stream.rb +224 -0
  152. data/lib/hexapdf/type/page.rb +355 -0
  153. data/lib/hexapdf/type/page_tree_node.rb +269 -0
  154. data/lib/hexapdf/type/resources.rb +212 -0
  155. data/lib/hexapdf/type/trailer.rb +128 -0
  156. data/lib/hexapdf/type/viewer_preferences.rb +73 -0
  157. data/lib/hexapdf/type/xref_stream.rb +204 -0
  158. data/lib/hexapdf/type.rb +67 -0
  159. data/lib/hexapdf/utils/bit_field.rb +87 -0
  160. data/lib/hexapdf/utils/bit_stream.rb +148 -0
  161. data/lib/hexapdf/utils/lru_cache.rb +65 -0
  162. data/lib/hexapdf/utils/math_helpers.rb +55 -0
  163. data/lib/hexapdf/utils/object_hash.rb +130 -0
  164. data/lib/hexapdf/utils/pdf_doc_encoding.rb +93 -0
  165. data/lib/hexapdf/utils/sorted_tree_node.rb +339 -0
  166. data/lib/hexapdf/version.rb +39 -0
  167. data/lib/hexapdf/writer.rb +199 -0
  168. data/lib/hexapdf/xref_section.rb +152 -0
  169. data/lib/hexapdf.rb +34 -0
  170. data/man/man1/hexapdf.1 +249 -0
  171. data/test/data/aes-test-vectors/CBCGFSbox-128-decrypt.data.gz +0 -0
  172. data/test/data/aes-test-vectors/CBCGFSbox-128-encrypt.data.gz +0 -0
  173. data/test/data/aes-test-vectors/CBCGFSbox-192-decrypt.data.gz +0 -0
  174. data/test/data/aes-test-vectors/CBCGFSbox-192-encrypt.data.gz +0 -0
  175. data/test/data/aes-test-vectors/CBCGFSbox-256-decrypt.data.gz +0 -0
  176. data/test/data/aes-test-vectors/CBCGFSbox-256-encrypt.data.gz +0 -0
  177. data/test/data/aes-test-vectors/CBCKeySbox-128-decrypt.data.gz +0 -0
  178. data/test/data/aes-test-vectors/CBCKeySbox-128-encrypt.data.gz +0 -0
  179. data/test/data/aes-test-vectors/CBCKeySbox-192-decrypt.data.gz +0 -0
  180. data/test/data/aes-test-vectors/CBCKeySbox-192-encrypt.data.gz +0 -0
  181. data/test/data/aes-test-vectors/CBCKeySbox-256-decrypt.data.gz +0 -0
  182. data/test/data/aes-test-vectors/CBCKeySbox-256-encrypt.data.gz +0 -0
  183. data/test/data/aes-test-vectors/CBCVarKey-128-decrypt.data.gz +0 -0
  184. data/test/data/aes-test-vectors/CBCVarKey-128-encrypt.data.gz +0 -0
  185. data/test/data/aes-test-vectors/CBCVarKey-192-decrypt.data.gz +0 -0
  186. data/test/data/aes-test-vectors/CBCVarKey-192-encrypt.data.gz +0 -0
  187. data/test/data/aes-test-vectors/CBCVarKey-256-decrypt.data.gz +0 -0
  188. data/test/data/aes-test-vectors/CBCVarKey-256-encrypt.data.gz +0 -0
  189. data/test/data/aes-test-vectors/CBCVarTxt-128-decrypt.data.gz +0 -0
  190. data/test/data/aes-test-vectors/CBCVarTxt-128-encrypt.data.gz +0 -0
  191. data/test/data/aes-test-vectors/CBCVarTxt-192-decrypt.data.gz +0 -0
  192. data/test/data/aes-test-vectors/CBCVarTxt-192-encrypt.data.gz +0 -0
  193. data/test/data/aes-test-vectors/CBCVarTxt-256-decrypt.data.gz +0 -0
  194. data/test/data/aes-test-vectors/CBCVarTxt-256-encrypt.data.gz +0 -0
  195. data/test/data/fonts/Ubuntu-Title.ttf +0 -0
  196. data/test/data/images/cmyk.jpg +0 -0
  197. data/test/data/images/fillbytes.jpg +0 -0
  198. data/test/data/images/gray.jpg +0 -0
  199. data/test/data/images/greyscale-1bit.png +0 -0
  200. data/test/data/images/greyscale-2bit.png +0 -0
  201. data/test/data/images/greyscale-4bit.png +0 -0
  202. data/test/data/images/greyscale-8bit.png +0 -0
  203. data/test/data/images/greyscale-alpha-8bit.png +0 -0
  204. data/test/data/images/greyscale-trns-8bit.png +0 -0
  205. data/test/data/images/greyscale-with-gamma1.0.png +0 -0
  206. data/test/data/images/greyscale-with-gamma1.5.png +0 -0
  207. data/test/data/images/indexed-1bit.png +0 -0
  208. data/test/data/images/indexed-2bit.png +0 -0
  209. data/test/data/images/indexed-4bit.png +0 -0
  210. data/test/data/images/indexed-8bit.png +0 -0
  211. data/test/data/images/indexed-alpha-4bit.png +0 -0
  212. data/test/data/images/indexed-alpha-8bit.png +0 -0
  213. data/test/data/images/rgb.jpg +0 -0
  214. data/test/data/images/truecolour-8bit.png +0 -0
  215. data/test/data/images/truecolour-alpha-8bit.png +0 -0
  216. data/test/data/images/truecolour-gama-chrm-8bit.png +0 -0
  217. data/test/data/images/truecolour-srgb-8bit.png +0 -0
  218. data/test/data/minimal.pdf +44 -0
  219. data/test/data/standard-security-handler/README +9 -0
  220. data/test/data/standard-security-handler/bothpwd-aes-128bit-V4.pdf +44 -0
  221. data/test/data/standard-security-handler/bothpwd-aes-256bit-V5.pdf +0 -0
  222. data/test/data/standard-security-handler/bothpwd-arc4-128bit-V2.pdf +43 -0
  223. data/test/data/standard-security-handler/bothpwd-arc4-128bit-V4.pdf +43 -0
  224. data/test/data/standard-security-handler/bothpwd-arc4-40bit-V1.pdf +0 -0
  225. data/test/data/standard-security-handler/nopwd-aes-128bit-V4.pdf +43 -0
  226. data/test/data/standard-security-handler/nopwd-aes-256bit-V5.pdf +0 -0
  227. data/test/data/standard-security-handler/nopwd-arc4-128bit-V2.pdf +43 -0
  228. data/test/data/standard-security-handler/nopwd-arc4-128bit-V4.pdf +43 -0
  229. data/test/data/standard-security-handler/nopwd-arc4-40bit-V1.pdf +43 -0
  230. data/test/data/standard-security-handler/ownerpwd-aes-128bit-V4.pdf +0 -0
  231. data/test/data/standard-security-handler/ownerpwd-aes-256bit-V5.pdf +43 -0
  232. data/test/data/standard-security-handler/ownerpwd-arc4-128bit-V2.pdf +43 -0
  233. data/test/data/standard-security-handler/ownerpwd-arc4-128bit-V4.pdf +43 -0
  234. data/test/data/standard-security-handler/ownerpwd-arc4-40bit-V1.pdf +43 -0
  235. data/test/data/standard-security-handler/userpwd-aes-128bit-V4.pdf +43 -0
  236. data/test/data/standard-security-handler/userpwd-aes-256bit-V5.pdf +43 -0
  237. data/test/data/standard-security-handler/userpwd-arc4-128bit-V2.pdf +0 -0
  238. data/test/data/standard-security-handler/userpwd-arc4-128bit-V4.pdf +0 -0
  239. data/test/data/standard-security-handler/userpwd-arc4-40bit-V1.pdf +43 -0
  240. data/test/hexapdf/common_tokenizer_tests.rb +204 -0
  241. data/test/hexapdf/content/common.rb +31 -0
  242. data/test/hexapdf/content/graphic_object/test_arc.rb +93 -0
  243. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +91 -0
  244. data/test/hexapdf/content/graphic_object/test_solid_arc.rb +86 -0
  245. data/test/hexapdf/content/test_canvas.rb +1113 -0
  246. data/test/hexapdf/content/test_color_space.rb +97 -0
  247. data/test/hexapdf/content/test_graphics_state.rb +138 -0
  248. data/test/hexapdf/content/test_operator.rb +619 -0
  249. data/test/hexapdf/content/test_parser.rb +66 -0
  250. data/test/hexapdf/content/test_processor.rb +156 -0
  251. data/test/hexapdf/content/test_transformation_matrix.rb +64 -0
  252. data/test/hexapdf/encryption/common.rb +87 -0
  253. data/test/hexapdf/encryption/test_aes.rb +121 -0
  254. data/test/hexapdf/encryption/test_arc4.rb +39 -0
  255. data/test/hexapdf/encryption/test_fast_aes.rb +17 -0
  256. data/test/hexapdf/encryption/test_fast_arc4.rb +12 -0
  257. data/test/hexapdf/encryption/test_identity.rb +21 -0
  258. data/test/hexapdf/encryption/test_ruby_aes.rb +23 -0
  259. data/test/hexapdf/encryption/test_ruby_arc4.rb +20 -0
  260. data/test/hexapdf/encryption/test_security_handler.rb +356 -0
  261. data/test/hexapdf/encryption/test_standard_security_handler.rb +274 -0
  262. data/test/hexapdf/filter/common.rb +53 -0
  263. data/test/hexapdf/filter/test_ascii85_decode.rb +60 -0
  264. data/test/hexapdf/filter/test_ascii_hex_decode.rb +33 -0
  265. data/test/hexapdf/filter/test_encryption.rb +24 -0
  266. data/test/hexapdf/filter/test_flate_decode.rb +35 -0
  267. data/test/hexapdf/filter/test_lzw_decode.rb +52 -0
  268. data/test/hexapdf/filter/test_predictor.rb +183 -0
  269. data/test/hexapdf/filter/test_run_length_decode.rb +32 -0
  270. data/test/hexapdf/font/cmap/test_parser.rb +67 -0
  271. data/test/hexapdf/font/cmap/test_writer.rb +58 -0
  272. data/test/hexapdf/font/encoding/test_base.rb +35 -0
  273. data/test/hexapdf/font/encoding/test_difference_encoding.rb +21 -0
  274. data/test/hexapdf/font/encoding/test_glyph_list.rb +59 -0
  275. data/test/hexapdf/font/encoding/test_zapf_dingbats_encoding.rb +16 -0
  276. data/test/hexapdf/font/test_encoding.rb +27 -0
  277. data/test/hexapdf/font/test_true_type_wrapper.rb +110 -0
  278. data/test/hexapdf/font/test_type1_wrapper.rb +66 -0
  279. data/test/hexapdf/font/true_type/common.rb +19 -0
  280. data/test/hexapdf/font/true_type/table/test_cmap.rb +59 -0
  281. data/test/hexapdf/font/true_type/table/test_cmap_subtable.rb +133 -0
  282. data/test/hexapdf/font/true_type/table/test_directory.rb +35 -0
  283. data/test/hexapdf/font/true_type/table/test_glyf.rb +58 -0
  284. data/test/hexapdf/font/true_type/table/test_head.rb +76 -0
  285. data/test/hexapdf/font/true_type/table/test_hhea.rb +40 -0
  286. data/test/hexapdf/font/true_type/table/test_hmtx.rb +38 -0
  287. data/test/hexapdf/font/true_type/table/test_loca.rb +43 -0
  288. data/test/hexapdf/font/true_type/table/test_maxp.rb +62 -0
  289. data/test/hexapdf/font/true_type/table/test_name.rb +95 -0
  290. data/test/hexapdf/font/true_type/table/test_os2.rb +65 -0
  291. data/test/hexapdf/font/true_type/table/test_post.rb +89 -0
  292. data/test/hexapdf/font/true_type/test_font.rb +120 -0
  293. data/test/hexapdf/font/true_type/test_table.rb +41 -0
  294. data/test/hexapdf/font/type1/test_afm_parser.rb +51 -0
  295. data/test/hexapdf/font/type1/test_font.rb +68 -0
  296. data/test/hexapdf/font/type1/test_pfb_parser.rb +37 -0
  297. data/test/hexapdf/font_loader/test_from_configuration.rb +28 -0
  298. data/test/hexapdf/font_loader/test_standard14.rb +22 -0
  299. data/test/hexapdf/image_loader/test_jpeg.rb +83 -0
  300. data/test/hexapdf/image_loader/test_pdf.rb +47 -0
  301. data/test/hexapdf/image_loader/test_png.rb +258 -0
  302. data/test/hexapdf/task/test_dereference.rb +46 -0
  303. data/test/hexapdf/task/test_optimize.rb +137 -0
  304. data/test/hexapdf/test_configuration.rb +82 -0
  305. data/test/hexapdf/test_data_dir.rb +32 -0
  306. data/test/hexapdf/test_dictionary.rb +284 -0
  307. data/test/hexapdf/test_dictionary_fields.rb +185 -0
  308. data/test/hexapdf/test_document.rb +574 -0
  309. data/test/hexapdf/test_document_utils.rb +144 -0
  310. data/test/hexapdf/test_filter.rb +96 -0
  311. data/test/hexapdf/test_font_utils.rb +47 -0
  312. data/test/hexapdf/test_importer.rb +78 -0
  313. data/test/hexapdf/test_object.rb +177 -0
  314. data/test/hexapdf/test_parser.rb +394 -0
  315. data/test/hexapdf/test_rectangle.rb +36 -0
  316. data/test/hexapdf/test_reference.rb +41 -0
  317. data/test/hexapdf/test_revision.rb +139 -0
  318. data/test/hexapdf/test_revisions.rb +93 -0
  319. data/test/hexapdf/test_serializer.rb +169 -0
  320. data/test/hexapdf/test_stream.rb +262 -0
  321. data/test/hexapdf/test_tokenizer.rb +30 -0
  322. data/test/hexapdf/test_writer.rb +120 -0
  323. data/test/hexapdf/test_xref_section.rb +35 -0
  324. data/test/hexapdf/type/test_catalog.rb +30 -0
  325. data/test/hexapdf/type/test_embedded_file.rb +16 -0
  326. data/test/hexapdf/type/test_file_specification.rb +148 -0
  327. data/test/hexapdf/type/test_font.rb +35 -0
  328. data/test/hexapdf/type/test_font_descriptor.rb +51 -0
  329. data/test/hexapdf/type/test_font_simple.rb +190 -0
  330. data/test/hexapdf/type/test_font_type1.rb +128 -0
  331. data/test/hexapdf/type/test_form.rb +60 -0
  332. data/test/hexapdf/type/test_info.rb +14 -0
  333. data/test/hexapdf/type/test_names.rb +9 -0
  334. data/test/hexapdf/type/test_object_stream.rb +84 -0
  335. data/test/hexapdf/type/test_page.rb +260 -0
  336. data/test/hexapdf/type/test_page_tree_node.rb +255 -0
  337. data/test/hexapdf/type/test_resources.rb +167 -0
  338. data/test/hexapdf/type/test_trailer.rb +109 -0
  339. data/test/hexapdf/type/test_xref_stream.rb +131 -0
  340. data/test/hexapdf/utils/test_bit_field.rb +47 -0
  341. data/test/hexapdf/utils/test_lru_cache.rb +22 -0
  342. data/test/hexapdf/utils/test_object_hash.rb +115 -0
  343. data/test/hexapdf/utils/test_pdf_doc_encoding.rb +18 -0
  344. data/test/hexapdf/utils/test_sorted_tree_node.rb +232 -0
  345. data/test/test_helper.rb +56 -0
  346. metadata +427 -0
@@ -0,0 +1,167 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/type/resources'
5
+ require 'hexapdf/document'
6
+
7
+ describe HexaPDF::Type::Resources do
8
+ before do
9
+ @doc = HexaPDF::Document.new
10
+ @res = HexaPDF::Type::Resources.new({}, document: @doc)
11
+ end
12
+
13
+ describe "color_space" do
14
+ it "works for device color spaces" do
15
+ assert_equal(HexaPDF::Content::ColorSpace::DeviceRGB::DEFAULT,
16
+ @res.color_space(:DeviceRGB))
17
+ assert_equal(HexaPDF::Content::ColorSpace::DeviceCMYK::DEFAULT,
18
+ @res.color_space(:DeviceCMYK))
19
+ assert_equal(HexaPDF::Content::ColorSpace::DeviceGray::DEFAULT,
20
+ @res.color_space(:DeviceGray))
21
+ end
22
+
23
+ it "works for color spaces defined only with a name" do
24
+ @res[:ColorSpace] = {CSName: :Pattern}
25
+ assert_kind_of(HexaPDF::Content::ColorSpace::Universal, @res.color_space(:CSName))
26
+ end
27
+
28
+ it "returns the universal color space for unknown color spaces, with resolved references" do
29
+ data = @doc.add(Some: :data)
30
+ @res[:ColorSpace] = {CSName: [:SomeUnknownColorSpace,
31
+ HexaPDF::Reference.new(data.oid, data.gen)]}
32
+ color_space = @res.color_space(:CSName)
33
+ assert_kind_of(HexaPDF::Content::ColorSpace::Universal, color_space)
34
+ assert_equal([:SomeUnknownColorSpace, data], color_space.definition)
35
+ end
36
+
37
+ it "fails if the specified name is neither a device color space nor in the dictionary" do
38
+ assert_raises(HexaPDF::Error) { @res.color_space(:UnknownColorSpace) }
39
+ end
40
+ end
41
+
42
+ describe "add_color_space" do
43
+ it "returns device color spaces without adding an entry" do
44
+ [HexaPDF::Content::ColorSpace::DeviceRGB::DEFAULT,
45
+ HexaPDF::Content::ColorSpace::DeviceCMYK::DEFAULT,
46
+ HexaPDF::Content::ColorSpace::DeviceGray::DEFAULT].each do |space|
47
+ name = @res.add_color_space(space)
48
+ assert_equal(space.family, name)
49
+ refute(@res.key?(:ColorSpace))
50
+ end
51
+ end
52
+
53
+ it "adds a color space that is not a device color space" do
54
+ space = HexaPDF::Content::ColorSpace::Universal.new([:DeviceN, :data])
55
+ name = @res.add_color_space(space)
56
+ assert(@res[:ColorSpace].key?(name))
57
+ assert_equal(space.definition, @res[:ColorSpace][name])
58
+ assert_equal(space, @res.color_space(name))
59
+ end
60
+
61
+ it "doesn't add the same color space twice" do
62
+ object = @doc.add(some: :data)
63
+ @res[:ColorSpace] = {space: [:DeviceN, HexaPDF::Reference.new(object.oid, object.gen)]}
64
+ space = HexaPDF::Content::ColorSpace::Universal.new([:DeviceN, object])
65
+ name = @res.add_color_space(space)
66
+ assert_equal(:space, name)
67
+ assert_equal(1, @res[:ColorSpace].value.size)
68
+ assert_equal(space, @res.color_space(name))
69
+ end
70
+
71
+ it "uses a unique color space name" do
72
+ @res[:ColorSpace] = {CS2: [:DeviceN, :test]}
73
+ space = HexaPDF::Content::ColorSpace::Universal.new([:DeviceN, :data])
74
+ name = @res.add_color_space(space)
75
+ refute_equal(:CS2, name)
76
+ assert_equal(2, @res[:ColorSpace].value.size)
77
+ end
78
+ end
79
+
80
+ describe "private object_getter" do
81
+ it "returns the named entry under the dictionary" do
82
+ @res[:XObject] = {name: :value}
83
+ assert_equal(:value, @res.xobject(:name))
84
+ end
85
+
86
+ it "fails if the specified name is not in the dictionary" do
87
+ assert_raises(HexaPDF::Error) { @res.xobject(:UnknownXObject) }
88
+ end
89
+ end
90
+
91
+ describe "private object_setter" do
92
+ it "adds the object to the specified subdictionary" do
93
+ obj = @doc.add(some: :xobject)
94
+ name = @res.add_xobject(obj)
95
+ assert(@res[:XObject].key?(name))
96
+ assert_equal(obj, @res[:XObject][name])
97
+ end
98
+
99
+ it "doesn't add the same object twice" do
100
+ obj = @doc.add(some: :xobject)
101
+ name = @res.add_xobject(obj)
102
+ name2 = @res.add_xobject(obj)
103
+ assert_equal(name, name2)
104
+ end
105
+ end
106
+
107
+ describe "xobject" do
108
+ it "invokes the object_getter method" do
109
+ assert_method_invoked(@res, :object_getter, [:XObject, :test]) do
110
+ @res.xobject(:test)
111
+ end
112
+ end
113
+ end
114
+
115
+ describe "add_xobject" do
116
+ it "invokes the object_setter method" do
117
+ assert_method_invoked(@res, :object_setter, [:XObject, 'XO', :test]) do
118
+ @res.add_xobject(:test)
119
+ end
120
+ end
121
+ end
122
+
123
+ describe "ext_gstate" do
124
+ it "invokes the object_getter method" do
125
+ assert_method_invoked(@res, :object_getter, [:ExtGState, :test]) do
126
+ @res.ext_gstate(:test)
127
+ end
128
+ end
129
+ end
130
+
131
+ describe "add_ext_gstate" do
132
+ it "invokes the object_setter method" do
133
+ assert_method_invoked(@res, :object_setter, [:ExtGState, 'GS', :test]) do
134
+ @res.add_ext_gstate(:test)
135
+ end
136
+ end
137
+ end
138
+
139
+ describe "find" do
140
+ it "invokes the object_getter method" do
141
+ assert_method_invoked(@res, :object_getter, [:Font, :test]) do
142
+ @res.font(:test)
143
+ end
144
+ end
145
+ end
146
+
147
+ describe "add_font" do
148
+ it "invokes the object_setter method" do
149
+ assert_method_invoked(@res, :object_setter, [:Font, 'F', :test]) do
150
+ @res.add_font(:test)
151
+ end
152
+ end
153
+ end
154
+
155
+ describe "validation" do
156
+ it "assigns the default value if ProcSet is not set" do
157
+ @res.validate
158
+ assert_equal([:PDF, :Text, :ImageB, :ImageC, :ImageI], @res[:ProcSet])
159
+ end
160
+
161
+ it "removes invalid procedure set names from ProcSet" do
162
+ @res[:ProcSet] = [:PDF, :Unknown]
163
+ @res.validate
164
+ assert_equal([:PDF], @res[:ProcSet])
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,109 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/type/trailer'
5
+ require 'hexapdf/object'
6
+ require 'hexapdf/type'
7
+
8
+ describe HexaPDF::Type::Trailer do
9
+ before do
10
+ @doc = Object.new
11
+ @doc.instance_variable_set(:@version, '1.2')
12
+ def (@doc).version=(v); @version = v; end
13
+ def (@doc).deref(obj); obj; end
14
+ def (@doc).wrap(obj, *); HexaPDF::Dictionary.new(obj, oid: (obj.oid rescue 0)); end
15
+ root = HexaPDF::Dictionary.new({}, oid: 3)
16
+ @obj = HexaPDF::Type::Trailer.new({Size: 10, Root: root}, document: @doc)
17
+ end
18
+
19
+ it "uses a custom type" do
20
+ assert_equal(:XXTrailer, @obj.type)
21
+ end
22
+
23
+ it "returns the catalog object, creating it if needed" do
24
+ doc = Minitest::Mock.new
25
+ doc.expect(:add, :val, [{Type: :Catalog}])
26
+ trailer = HexaPDF::Type::Trailer.new({}, document: doc)
27
+ assert_equal(:val, trailer.catalog)
28
+ doc.verify
29
+ assert_equal(:val, trailer.value[:Root])
30
+ end
31
+
32
+ it "returns the info object, creating it if needed" do
33
+ doc = Minitest::Mock.new
34
+ doc.expect(:add, :val, [{}, type: :XXInfo])
35
+ trailer = HexaPDF::Type::Trailer.new({}, document: doc)
36
+ assert_equal(:val, trailer.info)
37
+ doc.verify
38
+ assert_equal(:val, trailer.value[:Info])
39
+ end
40
+
41
+ describe "ID field" do
42
+ it "sets a random ID" do
43
+ @obj.set_random_id
44
+ assert_kind_of(Array, @obj[:ID])
45
+ assert_equal(2, @obj[:ID].length)
46
+ assert_same(@obj[:ID][0], @obj[:ID][1])
47
+ assert_kind_of(String, @obj[:ID][0])
48
+ end
49
+
50
+ it "updates the ID field" do
51
+ @obj.update_id
52
+ assert_same(@obj[:ID][0], @obj[:ID][1])
53
+
54
+ @obj.update_id
55
+ refute_same(@obj[:ID][0], @obj[:ID][1])
56
+ end
57
+ end
58
+
59
+ describe "validation" do
60
+ it "validates and corrects a missing ID entry" do
61
+ @obj.validate do |msg, correctable|
62
+ assert(correctable)
63
+ assert_match(/ID.*be set/, msg)
64
+ end
65
+ refute_nil(@obj[:ID])
66
+ end
67
+
68
+ it "validates and corrects a missing ID entry when an Encrypt dictionary is set" do
69
+ def (@doc).security_handler
70
+ obj = Object.new
71
+ def obj.encryption_key_valid?; true; end
72
+ obj
73
+ end
74
+ @obj[:Encrypt] = {}
75
+ @obj.validate do |msg, correctable|
76
+ assert(correctable)
77
+ assert_match(/ID.*Encrypt/, msg)
78
+ end
79
+ refute_nil(@obj[:ID])
80
+ end
81
+
82
+ it "corrects a missing Catalog entry" do
83
+ @obj.delete(:Root)
84
+ @obj.set_random_id
85
+ def (@doc).add(val) HexaPDF::Object.new(val, oid: 3) end
86
+
87
+ message = ''
88
+ refute(@obj.validate(auto_correct: false) {|m, _| message = m})
89
+ assert_match(/Catalog/, message)
90
+ assert(@obj.validate)
91
+ end
92
+
93
+ it "fails if the Encrypt dictionary is set but no security handler is available" do
94
+ def (@doc).security_handler; nil; end
95
+ @obj[:Encrypt] = {}
96
+ refute(@obj.validate)
97
+ end
98
+
99
+ it "fails if the Encrypt dictionary is set but the security handler's key is wrong" do
100
+ def (@doc).security_handler
101
+ obj = Object.new
102
+ def obj.encryption_key_valid?; false; end
103
+ obj
104
+ end
105
+ @obj[:Encrypt] = {}
106
+ refute(@obj.validate)
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,131 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/type/xref_stream'
5
+
6
+ describe HexaPDF::Type::XRefStream do
7
+ before do
8
+ @doc = Object.new
9
+ def (@doc).deref(obj); obj; end
10
+ @obj = HexaPDF::Type::XRefStream.new({}, oid: 1, document: @doc)
11
+ end
12
+
13
+ describe "xref_section" do
14
+ it "handles a missing /Index field" do
15
+ @obj[:Size] = 1
16
+ @obj[:W] = [2, 2, 2]
17
+ @obj.stream = [0, 65535, 1].pack('n*')
18
+ section = @obj.xref_section
19
+ assert_equal(1, section.each.to_a.size)
20
+ assert(section[0, 1].free?)
21
+ end
22
+
23
+ it "handles the three different field types and ignores unknown types" do
24
+ @obj[:Index] = [0, 4]
25
+ @obj[:W] = [2, 2, 2]
26
+ @obj.stream = [0, 65535, 1, 1, 200, 0, 2, 1, 5, 3, 0, 0].pack('n*')
27
+ section = @obj.xref_section
28
+ assert(section[0, 1].free?)
29
+ assert(section[1, 0].in_use?)
30
+ assert_equal(200, section[1, 0].pos)
31
+ assert(section[2, 0].compressed?)
32
+ assert_equal(1, section[2, 0].objstm)
33
+ assert_equal(5, section[2, 0].pos)
34
+ end
35
+
36
+ it "uses the default value for field one if its length is zero" do
37
+ @obj[:Index] = [3, 1]
38
+ @obj[:W] = [0, 1, 1]
39
+ @obj.stream = [200, 0].pack('C*')
40
+ section = @obj.xref_section
41
+ assert(section[3, 0].in_use?)
42
+ assert_equal(200, section[3, 0].pos)
43
+ end
44
+
45
+ it "uses the default value for field three if its length is zero" do
46
+ @obj[:Index] = [3, 1]
47
+ @obj[:W] = [1, 1, 0]
48
+ @obj.stream = [1, 200].pack('C*')
49
+ section = @obj.xref_section
50
+ assert(section[3, 0].in_use?)
51
+ assert_equal(200, section[3, 0].pos)
52
+ end
53
+
54
+ it "uses the default values for field one/three if their lengths are zero" do
55
+ @obj[:Index] = [3, 1]
56
+ @obj[:W] = [0, 1, 0]
57
+ @obj.stream = [200].pack('C*')
58
+ section = @obj.xref_section
59
+ assert(section[3, 0].in_use?)
60
+ assert_equal(200, section[3, 0].pos)
61
+ end
62
+
63
+ it "can handle multiple subsections" do
64
+ @obj[:Index] = [3, 1, 10, 1]
65
+ @obj[:W] = [0, 1, 0]
66
+ @obj.stream = [200, 250].pack('C*')
67
+ section = @obj.xref_section
68
+ assert(section[3, 0].in_use?)
69
+ assert_equal(200, section[3, 0].pos)
70
+ assert(section[10, 0].in_use?)
71
+ assert_equal(250, section[10, 0].pos)
72
+ end
73
+ end
74
+
75
+ describe "trailer" do
76
+ it "returns a dictionary without xref stream specific values" do
77
+ @obj[:Size] = 5
78
+ @obj[:ID] = ["a", "b"]
79
+ @obj[:Root] = 'x'
80
+ @obj[:Index] = [0, 5]
81
+ @obj[:W] = [1, 2, 2]
82
+ dict = @obj.trailer
83
+ assert_equal(3, dict.length)
84
+ assert_equal(5, dict[:Size])
85
+ assert_equal(["a", "b"], dict[:ID])
86
+ assert_equal('x', dict[:Root])
87
+ end
88
+ end
89
+
90
+ describe "update_with_xref_section_and_trailer" do
91
+ before do
92
+ @section = HexaPDF::XRefSection.new
93
+ @section.add_free_entry(0, 65535)
94
+ @section.add_in_use_entry(1, 0, 200)
95
+ @section.add_compressed_entry(2, 1, 5)
96
+ end
97
+
98
+ it "sets all necessary dictionary values" do
99
+ @obj.update_with_xref_section_and_trailer(@section, Size: 100)
100
+ assert_equal(:XRef, @obj.value[:Type])
101
+ assert_equal(100, @obj.value[:Size])
102
+ assert_equal([0, 3], @obj.value[:Index])
103
+ assert_equal([1, 1, 2], @obj.value[:W])
104
+ end
105
+
106
+ it "updates the stream with the new information" do
107
+ @obj.update_with_xref_section_and_trailer(@section, Size: 100)
108
+ section = @obj.xref_section
109
+ @section.each do |oid, gen, data|
110
+ if section[oid, gen] == data
111
+ section.delete(oid)
112
+ else
113
+ flunk("Data for object p#{oid}, #{gen}] is not equal")
114
+ end
115
+ end
116
+ assert_equal(0, section.each.to_a.size)
117
+ end
118
+
119
+ it "can write multiple subsections" do
120
+ @section.add_free_entry(10, 1)
121
+ @section.add_in_use_entry(11, 1, 100)
122
+ @obj.update_with_xref_section_and_trailer(@section, Size: 100)
123
+ assert_equal([0, 3, 10, 2], @obj.value[:Index])
124
+ end
125
+
126
+ it "fails for unsupported cross-reference entry types" do
127
+ @section.send(:[]=, 3, 0, HexaPDF::XRefSection::Entry.new(:unknown, 3, 0))
128
+ assert_raises(HexaPDF::Error) { @obj.update_with_xref_section_and_trailer(@section, {}) }
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,47 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/utils/bit_field'
5
+
6
+ class TestBitField
7
+ extend HexaPDF::Utils::BitField
8
+ attr_accessor :data
9
+ bit_field(:data, {bit0: 0, bit1: 1, bit5: 5}, lister: "list", getter: "get", setter: "set")
10
+ end
11
+
12
+ describe HexaPDF::Utils::BitField do
13
+ before do
14
+ @obj = TestBitField.new
15
+ end
16
+
17
+ it "returns all bit names using the lister method" do
18
+ @obj.data = 0b100011
19
+ assert_equal([:bit0, :bit1, :bit5], @obj.list)
20
+ @obj.data = 0b100001
21
+ assert_equal([:bit0, :bit5], @obj.list)
22
+ end
23
+
24
+ it "can check whether a given bit is set via the getter method" do
25
+ refute(@obj.get(:bit0))
26
+ @obj.data = 0b000001
27
+ assert(@obj.get(:bit0))
28
+ assert(@obj.get(0))
29
+ refute(@obj.get(:bit1))
30
+ refute(@obj.get(1))
31
+ end
32
+
33
+ it "can set a given bit via the setter method" do
34
+ assert_nil(@obj.data)
35
+ @obj.set(:bit0, :bit1, :bit5)
36
+ assert_equal(0b100011, @obj.data)
37
+ @obj.set(:bit0, 5, clear_existing: true)
38
+ assert_equal(0b100001, @obj.data)
39
+ end
40
+
41
+ it "fails if an unknown bit name or bit index is used with one of the methods" do
42
+ e = assert_raises(ArgumentError) { @obj.get(10) }
43
+ assert_equal("Invalid bit field name or index '10' for TestBitField#data", e.message)
44
+ e = assert_raises(ArgumentError) { @obj.get(:bit10) }
45
+ assert_equal("Invalid bit field name or index 'bit10' for TestBitField#data", e.message)
46
+ end
47
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/utils/lru_cache'
5
+
6
+ describe HexaPDF::Utils::LRUCache do
7
+ before do
8
+ @cache = HexaPDF::Utils::LRUCache.new(5)
9
+ 5.times {|i| @cache[i] = i * 2}
10
+ end
11
+
12
+ it "removes the LRU item when the size is reached" do
13
+ assert([1, 2], @cache.instance_variable_get(:@cache).first)
14
+ @cache[6] = 7
15
+ assert([2, 4], @cache.instance_variable_get(:@cache).first)
16
+ end
17
+
18
+ it "freshes an item on access" do
19
+ @cache[1]
20
+ assert([2, 4], @cache.instance_variable_get(:@cache).first)
21
+ end
22
+ end
@@ -0,0 +1,115 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/utils/object_hash'
5
+
6
+ describe HexaPDF::Utils::ObjectHash do
7
+ before do
8
+ @hash = HexaPDF::Utils::ObjectHash.new
9
+ end
10
+
11
+ describe "[]" do
12
+ it "works with both an object number and a generation number" do
13
+ @hash[1, 5] = 5
14
+ assert_equal(5, @hash[1, 5])
15
+ assert_nil(@hash[1, 4])
16
+ assert_nil(@hash[2, 5])
17
+ end
18
+
19
+ it "works with an object number only" do
20
+ @hash[1, 5] = 5
21
+ assert_equal(5, @hash[1])
22
+ assert_nil(@hash[2])
23
+ end
24
+ end
25
+
26
+ describe "[]=" do
27
+ it "allows adding an entry" do
28
+ @hash[1, 5] = 5
29
+ assert_equal(5, @hash[1, 5])
30
+ end
31
+
32
+ it "allows overwriting an existing entry for an object number" do
33
+ @hash[1, 0] = 5
34
+ @hash[1, 0] = 6
35
+ assert_equal(6, @hash[1, 0])
36
+
37
+ @hash[1, 1] = 5
38
+ assert_equal(5, @hash[1, 1])
39
+ assert_nil(@hash[1, 0])
40
+ end
41
+ end
42
+
43
+ describe "entry?" do
44
+ it "checks if an entry for a specific object number exists" do
45
+ refute(@hash.entry?(1))
46
+ @hash[1, 1] = 5
47
+ assert(@hash.entry?(1))
48
+ end
49
+
50
+ it "checks if an entry for a specific object and generation number exists" do
51
+ refute(@hash.entry?(1, 1))
52
+ @hash[1, 1] = 5
53
+ assert(@hash.entry?(1, 1))
54
+ refute(@hash.entry?(1, 0))
55
+ end
56
+ end
57
+
58
+ it "returns the generation number for an object number with gen_for_oid" do
59
+ assert_nil(@hash.gen_for_oid(1))
60
+ @hash[1, 5] = 5
61
+ assert_equal(5, @hash.gen_for_oid(1))
62
+ end
63
+
64
+ it "deletes an entry via delete" do
65
+ @hash[1, 0] = 5
66
+ @hash.delete(1)
67
+ assert_nil(@hash[1])
68
+ end
69
+
70
+ describe "each" do
71
+ it "acts as an enumerable object" do
72
+ @hash[1, 0] = 5
73
+ @hash[2, 3] = 6
74
+ @hash[3, 2] = 7
75
+ assert_equal([[1, 0, 5], [2, 3, 6], [3, 2, 7]], @hash.each.to_a)
76
+
77
+ @hash.each do |oid, gen, data|
78
+ assert_equal(data, @hash[oid, gen])
79
+ end
80
+ end
81
+
82
+ it "allows key insertion during iteration" do
83
+ @hash[1, 0] = 5
84
+ count = 0
85
+ @hash.each { count += 1; @hash[2, 0] = 6 }
86
+ assert_equal(1, count)
87
+ end
88
+ end
89
+
90
+ describe "max_oid" do
91
+ it "is zero when no objects are stored" do
92
+ assert_equal(0, @hash.max_oid)
93
+ @hash[1, 0] = 5
94
+ @hash.delete(1)
95
+ assert_equal(0, @hash.max_oid)
96
+ end
97
+
98
+ it "changes accordingly when data is inserted" do
99
+ @hash[1, 0] = 5
100
+ assert_equal(1, @hash.max_oid)
101
+ @hash[5, 0] = 5
102
+ assert_equal(5, @hash.max_oid)
103
+ @hash[3, 0] = 5
104
+ assert_equal(5, @hash.max_oid)
105
+ end
106
+
107
+ it "changes accordingly when data is deleted" do
108
+ @hash[1, 0] = @hash[3, 0] = @hash[5, 0] = 5
109
+ @hash.delete(1)
110
+ assert_equal(5, @hash.max_oid)
111
+ @hash.delete(5)
112
+ assert_equal(3, @hash.max_oid)
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/utils/pdf_doc_encoding'
5
+
6
+ describe HexaPDF::Utils::PDFDocEncoding do
7
+ before do
8
+ @obj = HexaPDF::Utils::PDFDocEncoding
9
+ end
10
+
11
+ describe "convert_to_utf8" do
12
+ it "converts the given string to UTF-8" do
13
+ result = @obj.convert_to_utf8("Testing\x9c\x92".b)
14
+ assert_equal(Encoding::UTF_8, result.encoding)
15
+ assert_equal("Testing\u0153\u2122", result)
16
+ end
17
+ end
18
+ end